Fix gnu11 fallout on SPARC
[official-gcc.git] / gcc / omp-low.c
blob62911fa21d2c5d7ce97b45e894fc7c1509f4814c
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 "basic-block.h"
33 #include "tree-ssa-alias.h"
34 #include "internal-fn.h"
35 #include "gimple-fold.h"
36 #include "gimple-expr.h"
37 #include "is-a.h"
38 #include "gimple.h"
39 #include "gimplify.h"
40 #include "gimple-iterator.h"
41 #include "gimplify-me.h"
42 #include "gimple-walk.h"
43 #include "tree-iterator.h"
44 #include "tree-inline.h"
45 #include "langhooks.h"
46 #include "diagnostic-core.h"
47 #include "gimple-ssa.h"
48 #include "cgraph.h"
49 #include "tree-cfg.h"
50 #include "tree-phinodes.h"
51 #include "ssa-iterators.h"
52 #include "tree-ssanames.h"
53 #include "tree-into-ssa.h"
54 #include "expr.h"
55 #include "tree-dfa.h"
56 #include "tree-ssa.h"
57 #include "flags.h"
58 #include "hashtab.h"
59 #include "hash-set.h"
60 #include "vec.h"
61 #include "machmode.h"
62 #include "hard-reg-set.h"
63 #include "input.h"
64 #include "function.h"
65 #include "expr.h"
66 #include "tree-pass.h"
67 #include "except.h"
68 #include "splay-tree.h"
69 #include "optabs.h"
70 #include "cfgloop.h"
71 #include "target.h"
72 #include "omp-low.h"
73 #include "gimple-low.h"
74 #include "tree-cfgcleanup.h"
75 #include "pretty-print.h"
76 #include "ipa-prop.h"
77 #include "tree-nested.h"
78 #include "tree-eh.h"
79 #include "cilk.h"
82 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
83 phases. The first phase scans the function looking for OMP statements
84 and then for variables that must be replaced to satisfy data sharing
85 clauses. The second phase expands code for the constructs, as well as
86 re-gimplifying things when variables have been replaced with complex
87 expressions.
89 Final code generation is done by pass_expand_omp. The flowgraph is
90 scanned for parallel regions which are then moved to a new
91 function, to be invoked by the thread library. */
93 /* Parallel region information. Every parallel and workshare
94 directive is enclosed between two markers, the OMP_* directive
95 and a corresponding OMP_RETURN statement. */
97 struct omp_region
99 /* The enclosing region. */
100 struct omp_region *outer;
102 /* First child region. */
103 struct omp_region *inner;
105 /* Next peer region. */
106 struct omp_region *next;
108 /* Block containing the omp directive as its last stmt. */
109 basic_block entry;
111 /* Block containing the OMP_RETURN as its last stmt. */
112 basic_block exit;
114 /* Block containing the OMP_CONTINUE as its last stmt. */
115 basic_block cont;
117 /* If this is a combined parallel+workshare region, this is a list
118 of additional arguments needed by the combined parallel+workshare
119 library call. */
120 vec<tree, va_gc> *ws_args;
122 /* The code for the omp directive of this region. */
123 enum gimple_code type;
125 /* Schedule kind, only used for OMP_FOR type regions. */
126 enum omp_clause_schedule_kind sched_kind;
128 /* True if this is a combined parallel+workshare region. */
129 bool is_combined_parallel;
132 /* Context structure. Used to store information about each parallel
133 directive in the code. */
135 typedef struct omp_context
137 /* This field must be at the beginning, as we do "inheritance": Some
138 callback functions for tree-inline.c (e.g., omp_copy_decl)
139 receive a copy_body_data pointer that is up-casted to an
140 omp_context pointer. */
141 copy_body_data cb;
143 /* The tree of contexts corresponding to the encountered constructs. */
144 struct omp_context *outer;
145 gimple stmt;
147 /* Map variables to fields in a structure that allows communication
148 between sending and receiving threads. */
149 splay_tree field_map;
150 tree record_type;
151 tree sender_decl;
152 tree receiver_decl;
154 /* These are used just by task contexts, if task firstprivate fn is
155 needed. srecord_type is used to communicate from the thread
156 that encountered the task construct to task firstprivate fn,
157 record_type is allocated by GOMP_task, initialized by task firstprivate
158 fn and passed to the task body fn. */
159 splay_tree sfield_map;
160 tree srecord_type;
162 /* A chain of variables to add to the top-level block surrounding the
163 construct. In the case of a parallel, this is in the child function. */
164 tree block_vars;
166 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
167 barriers should jump to during omplower pass. */
168 tree cancel_label;
170 /* What to do with variables with implicitly determined sharing
171 attributes. */
172 enum omp_clause_default_kind default_kind;
174 /* Nesting depth of this context. Used to beautify error messages re
175 invalid gotos. The outermost ctx is depth 1, with depth 0 being
176 reserved for the main body of the function. */
177 int depth;
179 /* True if this parallel directive is nested within another. */
180 bool is_nested;
182 /* True if this construct can be cancelled. */
183 bool cancellable;
184 } omp_context;
187 struct omp_for_data_loop
189 tree v, n1, n2, step;
190 enum tree_code cond_code;
193 /* A structure describing the main elements of a parallel loop. */
195 struct omp_for_data
197 struct omp_for_data_loop loop;
198 tree chunk_size;
199 gimple for_stmt;
200 tree pre, iter_type;
201 int collapse;
202 bool have_nowait, have_ordered;
203 enum omp_clause_schedule_kind sched_kind;
204 struct omp_for_data_loop *loops;
208 static splay_tree all_contexts;
209 static int taskreg_nesting_level;
210 static int target_nesting_level;
211 static struct omp_region *root_omp_region;
212 static bitmap task_shared_vars;
213 static vec<omp_context *> taskreg_contexts;
215 static void scan_omp (gimple_seq *, omp_context *);
216 static tree scan_omp_1_op (tree *, int *, void *);
218 #define WALK_SUBSTMTS \
219 case GIMPLE_BIND: \
220 case GIMPLE_TRY: \
221 case GIMPLE_CATCH: \
222 case GIMPLE_EH_FILTER: \
223 case GIMPLE_TRANSACTION: \
224 /* The sub-statements for these should be walked. */ \
225 *handled_ops_p = false; \
226 break;
228 /* Convenience function for calling scan_omp_1_op on tree operands. */
230 static inline tree
231 scan_omp_op (tree *tp, omp_context *ctx)
233 struct walk_stmt_info wi;
235 memset (&wi, 0, sizeof (wi));
236 wi.info = ctx;
237 wi.want_locations = true;
239 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
242 static void lower_omp (gimple_seq *, omp_context *);
243 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
244 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
246 /* Find an OpenMP clause of type KIND within CLAUSES. */
248 tree
249 find_omp_clause (tree clauses, enum omp_clause_code kind)
251 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
252 if (OMP_CLAUSE_CODE (clauses) == kind)
253 return clauses;
255 return NULL_TREE;
258 /* Return true if CTX is for an omp parallel. */
260 static inline bool
261 is_parallel_ctx (omp_context *ctx)
263 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
267 /* Return true if CTX is for an omp task. */
269 static inline bool
270 is_task_ctx (omp_context *ctx)
272 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
276 /* Return true if CTX is for an omp parallel or omp task. */
278 static inline bool
279 is_taskreg_ctx (omp_context *ctx)
281 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
282 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
286 /* Return true if REGION is a combined parallel+workshare region. */
288 static inline bool
289 is_combined_parallel (struct omp_region *region)
291 return region->is_combined_parallel;
295 /* Extract the header elements of parallel loop FOR_STMT and store
296 them into *FD. */
298 static void
299 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
300 struct omp_for_data_loop *loops)
302 tree t, var, *collapse_iter, *collapse_count;
303 tree count = NULL_TREE, iter_type = long_integer_type_node;
304 struct omp_for_data_loop *loop;
305 int i;
306 struct omp_for_data_loop dummy_loop;
307 location_t loc = gimple_location (for_stmt);
308 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
309 bool distribute = gimple_omp_for_kind (for_stmt)
310 == GF_OMP_FOR_KIND_DISTRIBUTE;
312 fd->for_stmt = for_stmt;
313 fd->pre = NULL;
314 fd->collapse = gimple_omp_for_collapse (for_stmt);
315 if (fd->collapse > 1)
316 fd->loops = loops;
317 else
318 fd->loops = &fd->loop;
320 fd->have_nowait = distribute || simd;
321 fd->have_ordered = false;
322 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
323 fd->chunk_size = NULL_TREE;
324 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
325 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
326 collapse_iter = NULL;
327 collapse_count = NULL;
329 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
330 switch (OMP_CLAUSE_CODE (t))
332 case OMP_CLAUSE_NOWAIT:
333 fd->have_nowait = true;
334 break;
335 case OMP_CLAUSE_ORDERED:
336 fd->have_ordered = true;
337 break;
338 case OMP_CLAUSE_SCHEDULE:
339 gcc_assert (!distribute);
340 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
341 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
342 break;
343 case OMP_CLAUSE_DIST_SCHEDULE:
344 gcc_assert (distribute);
345 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
346 break;
347 case OMP_CLAUSE_COLLAPSE:
348 if (fd->collapse > 1)
350 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
351 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
353 break;
354 default:
355 break;
358 /* FIXME: for now map schedule(auto) to schedule(static).
359 There should be analysis to determine whether all iterations
360 are approximately the same amount of work (then schedule(static)
361 is best) or if it varies (then schedule(dynamic,N) is better). */
362 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
364 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
365 gcc_assert (fd->chunk_size == NULL);
367 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
368 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
369 gcc_assert (fd->chunk_size == NULL);
370 else if (fd->chunk_size == NULL)
372 /* We only need to compute a default chunk size for ordered
373 static loops and dynamic loops. */
374 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
375 || fd->have_ordered)
376 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
377 ? integer_zero_node : integer_one_node;
380 for (i = 0; i < fd->collapse; i++)
382 if (fd->collapse == 1)
383 loop = &fd->loop;
384 else if (loops != NULL)
385 loop = loops + i;
386 else
387 loop = &dummy_loop;
389 loop->v = gimple_omp_for_index (for_stmt, i);
390 gcc_assert (SSA_VAR_P (loop->v));
391 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
392 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
393 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
394 loop->n1 = gimple_omp_for_initial (for_stmt, i);
396 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
397 loop->n2 = gimple_omp_for_final (for_stmt, i);
398 switch (loop->cond_code)
400 case LT_EXPR:
401 case GT_EXPR:
402 break;
403 case NE_EXPR:
404 gcc_assert (gimple_omp_for_kind (for_stmt)
405 == GF_OMP_FOR_KIND_CILKSIMD
406 || (gimple_omp_for_kind (for_stmt)
407 == GF_OMP_FOR_KIND_CILKFOR));
408 break;
409 case LE_EXPR:
410 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
411 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
412 else
413 loop->n2 = fold_build2_loc (loc,
414 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
415 build_int_cst (TREE_TYPE (loop->n2), 1));
416 loop->cond_code = LT_EXPR;
417 break;
418 case GE_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 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
424 build_int_cst (TREE_TYPE (loop->n2), 1));
425 loop->cond_code = GT_EXPR;
426 break;
427 default:
428 gcc_unreachable ();
431 t = gimple_omp_for_incr (for_stmt, i);
432 gcc_assert (TREE_OPERAND (t, 0) == var);
433 switch (TREE_CODE (t))
435 case PLUS_EXPR:
436 loop->step = TREE_OPERAND (t, 1);
437 break;
438 case POINTER_PLUS_EXPR:
439 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
440 break;
441 case MINUS_EXPR:
442 loop->step = TREE_OPERAND (t, 1);
443 loop->step = fold_build1_loc (loc,
444 NEGATE_EXPR, TREE_TYPE (loop->step),
445 loop->step);
446 break;
447 default:
448 gcc_unreachable ();
451 if (simd
452 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
453 && !fd->have_ordered))
455 if (fd->collapse == 1)
456 iter_type = TREE_TYPE (loop->v);
457 else if (i == 0
458 || TYPE_PRECISION (iter_type)
459 < TYPE_PRECISION (TREE_TYPE (loop->v)))
460 iter_type
461 = build_nonstandard_integer_type
462 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
464 else if (iter_type != long_long_unsigned_type_node)
466 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
467 iter_type = long_long_unsigned_type_node;
468 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
469 && TYPE_PRECISION (TREE_TYPE (loop->v))
470 >= TYPE_PRECISION (iter_type))
472 tree n;
474 if (loop->cond_code == LT_EXPR)
475 n = fold_build2_loc (loc,
476 PLUS_EXPR, TREE_TYPE (loop->v),
477 loop->n2, loop->step);
478 else
479 n = loop->n1;
480 if (TREE_CODE (n) != INTEGER_CST
481 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
482 iter_type = long_long_unsigned_type_node;
484 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
485 > TYPE_PRECISION (iter_type))
487 tree n1, n2;
489 if (loop->cond_code == LT_EXPR)
491 n1 = loop->n1;
492 n2 = fold_build2_loc (loc,
493 PLUS_EXPR, TREE_TYPE (loop->v),
494 loop->n2, loop->step);
496 else
498 n1 = fold_build2_loc (loc,
499 MINUS_EXPR, TREE_TYPE (loop->v),
500 loop->n2, loop->step);
501 n2 = loop->n1;
503 if (TREE_CODE (n1) != INTEGER_CST
504 || TREE_CODE (n2) != INTEGER_CST
505 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
506 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
507 iter_type = long_long_unsigned_type_node;
511 if (collapse_count && *collapse_count == NULL)
513 t = fold_binary (loop->cond_code, boolean_type_node,
514 fold_convert (TREE_TYPE (loop->v), loop->n1),
515 fold_convert (TREE_TYPE (loop->v), loop->n2));
516 if (t && integer_zerop (t))
517 count = build_zero_cst (long_long_unsigned_type_node);
518 else if ((i == 0 || count != NULL_TREE)
519 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
520 && TREE_CONSTANT (loop->n1)
521 && TREE_CONSTANT (loop->n2)
522 && TREE_CODE (loop->step) == INTEGER_CST)
524 tree itype = TREE_TYPE (loop->v);
526 if (POINTER_TYPE_P (itype))
527 itype = signed_type_for (itype);
528 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
529 t = fold_build2_loc (loc,
530 PLUS_EXPR, itype,
531 fold_convert_loc (loc, itype, loop->step), t);
532 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
533 fold_convert_loc (loc, itype, loop->n2));
534 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
535 fold_convert_loc (loc, itype, loop->n1));
536 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
537 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
538 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
539 fold_build1_loc (loc, NEGATE_EXPR, itype,
540 fold_convert_loc (loc, itype,
541 loop->step)));
542 else
543 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
544 fold_convert_loc (loc, itype, loop->step));
545 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
546 if (count != NULL_TREE)
547 count = fold_build2_loc (loc,
548 MULT_EXPR, long_long_unsigned_type_node,
549 count, t);
550 else
551 count = t;
552 if (TREE_CODE (count) != INTEGER_CST)
553 count = NULL_TREE;
555 else if (count && !integer_zerop (count))
556 count = NULL_TREE;
560 if (count
561 && !simd
562 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
563 || fd->have_ordered))
565 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
566 iter_type = long_long_unsigned_type_node;
567 else
568 iter_type = long_integer_type_node;
570 else if (collapse_iter && *collapse_iter != NULL)
571 iter_type = TREE_TYPE (*collapse_iter);
572 fd->iter_type = iter_type;
573 if (collapse_iter && *collapse_iter == NULL)
574 *collapse_iter = create_tmp_var (iter_type, ".iter");
575 if (collapse_count && *collapse_count == NULL)
577 if (count)
578 *collapse_count = fold_convert_loc (loc, iter_type, count);
579 else
580 *collapse_count = create_tmp_var (iter_type, ".count");
583 if (fd->collapse > 1)
585 fd->loop.v = *collapse_iter;
586 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
587 fd->loop.n2 = *collapse_count;
588 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
589 fd->loop.cond_code = LT_EXPR;
594 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
595 is the immediate dominator of PAR_ENTRY_BB, return true if there
596 are no data dependencies that would prevent expanding the parallel
597 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
599 When expanding a combined parallel+workshare region, the call to
600 the child function may need additional arguments in the case of
601 GIMPLE_OMP_FOR regions. In some cases, these arguments are
602 computed out of variables passed in from the parent to the child
603 via 'struct .omp_data_s'. For instance:
605 #pragma omp parallel for schedule (guided, i * 4)
606 for (j ...)
608 Is lowered into:
610 # BLOCK 2 (PAR_ENTRY_BB)
611 .omp_data_o.i = i;
612 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
614 # BLOCK 3 (WS_ENTRY_BB)
615 .omp_data_i = &.omp_data_o;
616 D.1667 = .omp_data_i->i;
617 D.1598 = D.1667 * 4;
618 #pragma omp for schedule (guided, D.1598)
620 When we outline the parallel region, the call to the child function
621 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
622 that value is computed *after* the call site. So, in principle we
623 cannot do the transformation.
625 To see whether the code in WS_ENTRY_BB blocks the combined
626 parallel+workshare call, we collect all the variables used in the
627 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
628 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
629 call.
631 FIXME. If we had the SSA form built at this point, we could merely
632 hoist the code in block 3 into block 2 and be done with it. But at
633 this point we don't have dataflow information and though we could
634 hack something up here, it is really not worth the aggravation. */
636 static bool
637 workshare_safe_to_combine_p (basic_block ws_entry_bb)
639 struct omp_for_data fd;
640 gimple ws_stmt = last_stmt (ws_entry_bb);
642 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
643 return true;
645 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
647 extract_omp_for_data (ws_stmt, &fd, NULL);
649 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
650 return false;
651 if (fd.iter_type != long_integer_type_node)
652 return false;
654 /* FIXME. We give up too easily here. If any of these arguments
655 are not constants, they will likely involve variables that have
656 been mapped into fields of .omp_data_s for sharing with the child
657 function. With appropriate data flow, it would be possible to
658 see through this. */
659 if (!is_gimple_min_invariant (fd.loop.n1)
660 || !is_gimple_min_invariant (fd.loop.n2)
661 || !is_gimple_min_invariant (fd.loop.step)
662 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
663 return false;
665 return true;
669 /* Collect additional arguments needed to emit a combined
670 parallel+workshare call. WS_STMT is the workshare directive being
671 expanded. */
673 static vec<tree, va_gc> *
674 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
676 tree t;
677 location_t loc = gimple_location (ws_stmt);
678 vec<tree, va_gc> *ws_args;
680 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
682 struct omp_for_data fd;
683 tree n1, n2;
685 extract_omp_for_data (ws_stmt, &fd, NULL);
686 n1 = fd.loop.n1;
687 n2 = fd.loop.n2;
689 if (gimple_omp_for_combined_into_p (ws_stmt))
691 tree innerc
692 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
693 OMP_CLAUSE__LOOPTEMP_);
694 gcc_assert (innerc);
695 n1 = OMP_CLAUSE_DECL (innerc);
696 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
697 OMP_CLAUSE__LOOPTEMP_);
698 gcc_assert (innerc);
699 n2 = OMP_CLAUSE_DECL (innerc);
702 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
704 t = fold_convert_loc (loc, long_integer_type_node, n1);
705 ws_args->quick_push (t);
707 t = fold_convert_loc (loc, long_integer_type_node, n2);
708 ws_args->quick_push (t);
710 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
711 ws_args->quick_push (t);
713 if (fd.chunk_size)
715 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
716 ws_args->quick_push (t);
719 return ws_args;
721 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
723 /* Number of sections is equal to the number of edges from the
724 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
725 the exit of the sections region. */
726 basic_block bb = single_succ (gimple_bb (ws_stmt));
727 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
728 vec_alloc (ws_args, 1);
729 ws_args->quick_push (t);
730 return ws_args;
733 gcc_unreachable ();
737 /* Discover whether REGION is a combined parallel+workshare region. */
739 static void
740 determine_parallel_type (struct omp_region *region)
742 basic_block par_entry_bb, par_exit_bb;
743 basic_block ws_entry_bb, ws_exit_bb;
745 if (region == NULL || region->inner == NULL
746 || region->exit == NULL || region->inner->exit == NULL
747 || region->inner->cont == NULL)
748 return;
750 /* We only support parallel+for and parallel+sections. */
751 if (region->type != GIMPLE_OMP_PARALLEL
752 || (region->inner->type != GIMPLE_OMP_FOR
753 && region->inner->type != GIMPLE_OMP_SECTIONS))
754 return;
756 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
757 WS_EXIT_BB -> PAR_EXIT_BB. */
758 par_entry_bb = region->entry;
759 par_exit_bb = region->exit;
760 ws_entry_bb = region->inner->entry;
761 ws_exit_bb = region->inner->exit;
763 if (single_succ (par_entry_bb) == ws_entry_bb
764 && single_succ (ws_exit_bb) == par_exit_bb
765 && workshare_safe_to_combine_p (ws_entry_bb)
766 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
767 || (last_and_only_stmt (ws_entry_bb)
768 && last_and_only_stmt (par_exit_bb))))
770 gimple par_stmt = last_stmt (par_entry_bb);
771 gimple ws_stmt = last_stmt (ws_entry_bb);
773 if (region->inner->type == GIMPLE_OMP_FOR)
775 /* If this is a combined parallel loop, we need to determine
776 whether or not to use the combined library calls. There
777 are two cases where we do not apply the transformation:
778 static loops and any kind of ordered loop. In the first
779 case, we already open code the loop so there is no need
780 to do anything else. In the latter case, the combined
781 parallel loop call would still need extra synchronization
782 to implement ordered semantics, so there would not be any
783 gain in using the combined call. */
784 tree clauses = gimple_omp_for_clauses (ws_stmt);
785 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
786 if (c == NULL
787 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
788 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
790 region->is_combined_parallel = false;
791 region->inner->is_combined_parallel = false;
792 return;
796 region->is_combined_parallel = true;
797 region->inner->is_combined_parallel = true;
798 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
803 /* Return true if EXPR is variable sized. */
805 static inline bool
806 is_variable_sized (const_tree expr)
808 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
811 /* Return true if DECL is a reference type. */
813 static inline bool
814 is_reference (tree decl)
816 return lang_hooks.decls.omp_privatize_by_reference (decl);
819 /* Lookup variables in the decl or field splay trees. The "maybe" form
820 allows for the variable form to not have been entered, otherwise we
821 assert that the variable must have been entered. */
823 static inline tree
824 lookup_decl (tree var, omp_context *ctx)
826 tree *n = ctx->cb.decl_map->get (var);
827 return *n;
830 static inline tree
831 maybe_lookup_decl (const_tree var, omp_context *ctx)
833 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
834 return n ? *n : NULL_TREE;
837 static inline tree
838 lookup_field (tree var, omp_context *ctx)
840 splay_tree_node n;
841 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
842 return (tree) n->value;
845 static inline tree
846 lookup_sfield (tree var, omp_context *ctx)
848 splay_tree_node n;
849 n = splay_tree_lookup (ctx->sfield_map
850 ? ctx->sfield_map : ctx->field_map,
851 (splay_tree_key) var);
852 return (tree) n->value;
855 static inline tree
856 maybe_lookup_field (tree var, omp_context *ctx)
858 splay_tree_node n;
859 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
860 return n ? (tree) n->value : NULL_TREE;
863 /* Return true if DECL should be copied by pointer. SHARED_CTX is
864 the parallel context if DECL is to be shared. */
866 static bool
867 use_pointer_for_field (tree decl, omp_context *shared_ctx)
869 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
870 return true;
872 /* We can only use copy-in/copy-out semantics for shared variables
873 when we know the value is not accessible from an outer scope. */
874 if (shared_ctx)
876 /* ??? Trivially accessible from anywhere. But why would we even
877 be passing an address in this case? Should we simply assert
878 this to be false, or should we have a cleanup pass that removes
879 these from the list of mappings? */
880 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
881 return true;
883 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
884 without analyzing the expression whether or not its location
885 is accessible to anyone else. In the case of nested parallel
886 regions it certainly may be. */
887 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
888 return true;
890 /* Do not use copy-in/copy-out for variables that have their
891 address taken. */
892 if (TREE_ADDRESSABLE (decl))
893 return true;
895 /* lower_send_shared_vars only uses copy-in, but not copy-out
896 for these. */
897 if (TREE_READONLY (decl)
898 || ((TREE_CODE (decl) == RESULT_DECL
899 || TREE_CODE (decl) == PARM_DECL)
900 && DECL_BY_REFERENCE (decl)))
901 return false;
903 /* Disallow copy-in/out in nested parallel if
904 decl is shared in outer parallel, otherwise
905 each thread could store the shared variable
906 in its own copy-in location, making the
907 variable no longer really shared. */
908 if (shared_ctx->is_nested)
910 omp_context *up;
912 for (up = shared_ctx->outer; up; up = up->outer)
913 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
914 break;
916 if (up)
918 tree c;
920 for (c = gimple_omp_taskreg_clauses (up->stmt);
921 c; c = OMP_CLAUSE_CHAIN (c))
922 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
923 && OMP_CLAUSE_DECL (c) == decl)
924 break;
926 if (c)
927 goto maybe_mark_addressable_and_ret;
931 /* For tasks avoid using copy-in/out. As tasks can be
932 deferred or executed in different thread, when GOMP_task
933 returns, the task hasn't necessarily terminated. */
934 if (is_task_ctx (shared_ctx))
936 tree outer;
937 maybe_mark_addressable_and_ret:
938 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
939 if (is_gimple_reg (outer))
941 /* Taking address of OUTER in lower_send_shared_vars
942 might need regimplification of everything that uses the
943 variable. */
944 if (!task_shared_vars)
945 task_shared_vars = BITMAP_ALLOC (NULL);
946 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
947 TREE_ADDRESSABLE (outer) = 1;
949 return true;
953 return false;
956 /* Construct a new automatic decl similar to VAR. */
958 static tree
959 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
961 tree copy = copy_var_decl (var, name, type);
963 DECL_CONTEXT (copy) = current_function_decl;
964 DECL_CHAIN (copy) = ctx->block_vars;
965 ctx->block_vars = copy;
967 return copy;
970 static tree
971 omp_copy_decl_1 (tree var, omp_context *ctx)
973 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
976 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
977 as appropriate. */
978 static tree
979 omp_build_component_ref (tree obj, tree field)
981 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
982 if (TREE_THIS_VOLATILE (field))
983 TREE_THIS_VOLATILE (ret) |= 1;
984 if (TREE_READONLY (field))
985 TREE_READONLY (ret) |= 1;
986 return ret;
989 /* Build tree nodes to access the field for VAR on the receiver side. */
991 static tree
992 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
994 tree x, field = lookup_field (var, ctx);
996 /* If the receiver record type was remapped in the child function,
997 remap the field into the new record type. */
998 x = maybe_lookup_field (field, ctx);
999 if (x != NULL)
1000 field = x;
1002 x = build_simple_mem_ref (ctx->receiver_decl);
1003 x = omp_build_component_ref (x, field);
1004 if (by_ref)
1005 x = build_simple_mem_ref (x);
1007 return x;
1010 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1011 of a parallel, this is a component reference; for workshare constructs
1012 this is some variable. */
1014 static tree
1015 build_outer_var_ref (tree var, omp_context *ctx)
1017 tree x;
1019 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1020 x = var;
1021 else if (is_variable_sized (var))
1023 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1024 x = build_outer_var_ref (x, ctx);
1025 x = build_simple_mem_ref (x);
1027 else if (is_taskreg_ctx (ctx))
1029 bool by_ref = use_pointer_for_field (var, NULL);
1030 x = build_receiver_ref (var, by_ref, ctx);
1032 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1033 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1035 /* #pragma omp simd isn't a worksharing construct, and can reference even
1036 private vars in its linear etc. clauses. */
1037 x = NULL_TREE;
1038 if (ctx->outer && is_taskreg_ctx (ctx))
1039 x = lookup_decl (var, ctx->outer);
1040 else if (ctx->outer)
1041 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1042 if (x == NULL_TREE)
1043 x = var;
1045 else if (ctx->outer)
1046 x = lookup_decl (var, ctx->outer);
1047 else if (is_reference (var))
1048 /* This can happen with orphaned constructs. If var is reference, it is
1049 possible it is shared and as such valid. */
1050 x = var;
1051 else
1052 gcc_unreachable ();
1054 if (is_reference (var))
1055 x = build_simple_mem_ref (x);
1057 return x;
1060 /* Build tree nodes to access the field for VAR on the sender side. */
1062 static tree
1063 build_sender_ref (tree var, omp_context *ctx)
1065 tree field = lookup_sfield (var, ctx);
1066 return omp_build_component_ref (ctx->sender_decl, field);
1069 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1071 static void
1072 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1074 tree field, type, sfield = NULL_TREE;
1076 gcc_assert ((mask & 1) == 0
1077 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1078 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1079 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1081 type = TREE_TYPE (var);
1082 if (mask & 4)
1084 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1085 type = build_pointer_type (build_pointer_type (type));
1087 else if (by_ref)
1088 type = build_pointer_type (type);
1089 else if ((mask & 3) == 1 && is_reference (var))
1090 type = TREE_TYPE (type);
1092 field = build_decl (DECL_SOURCE_LOCATION (var),
1093 FIELD_DECL, DECL_NAME (var), type);
1095 /* Remember what variable this field was created for. This does have a
1096 side effect of making dwarf2out ignore this member, so for helpful
1097 debugging we clear it later in delete_omp_context. */
1098 DECL_ABSTRACT_ORIGIN (field) = var;
1099 if (type == TREE_TYPE (var))
1101 DECL_ALIGN (field) = DECL_ALIGN (var);
1102 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1103 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1105 else
1106 DECL_ALIGN (field) = TYPE_ALIGN (type);
1108 if ((mask & 3) == 3)
1110 insert_field_into_struct (ctx->record_type, field);
1111 if (ctx->srecord_type)
1113 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1114 FIELD_DECL, DECL_NAME (var), type);
1115 DECL_ABSTRACT_ORIGIN (sfield) = var;
1116 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1117 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1118 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1119 insert_field_into_struct (ctx->srecord_type, sfield);
1122 else
1124 if (ctx->srecord_type == NULL_TREE)
1126 tree t;
1128 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1129 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1130 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1132 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1133 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1134 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1135 insert_field_into_struct (ctx->srecord_type, sfield);
1136 splay_tree_insert (ctx->sfield_map,
1137 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1138 (splay_tree_value) sfield);
1141 sfield = field;
1142 insert_field_into_struct ((mask & 1) ? ctx->record_type
1143 : ctx->srecord_type, field);
1146 if (mask & 1)
1147 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1148 (splay_tree_value) field);
1149 if ((mask & 2) && ctx->sfield_map)
1150 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1151 (splay_tree_value) sfield);
1154 static tree
1155 install_var_local (tree var, omp_context *ctx)
1157 tree new_var = omp_copy_decl_1 (var, ctx);
1158 insert_decl_map (&ctx->cb, var, new_var);
1159 return new_var;
1162 /* Adjust the replacement for DECL in CTX for the new context. This means
1163 copying the DECL_VALUE_EXPR, and fixing up the type. */
1165 static void
1166 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1168 tree new_decl, size;
1170 new_decl = lookup_decl (decl, ctx);
1172 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1174 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1175 && DECL_HAS_VALUE_EXPR_P (decl))
1177 tree ve = DECL_VALUE_EXPR (decl);
1178 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1179 SET_DECL_VALUE_EXPR (new_decl, ve);
1180 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1183 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1185 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1186 if (size == error_mark_node)
1187 size = TYPE_SIZE (TREE_TYPE (new_decl));
1188 DECL_SIZE (new_decl) = size;
1190 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1191 if (size == error_mark_node)
1192 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1193 DECL_SIZE_UNIT (new_decl) = size;
1197 /* The callback for remap_decl. Search all containing contexts for a
1198 mapping of the variable; this avoids having to duplicate the splay
1199 tree ahead of time. We know a mapping doesn't already exist in the
1200 given context. Create new mappings to implement default semantics. */
1202 static tree
1203 omp_copy_decl (tree var, copy_body_data *cb)
1205 omp_context *ctx = (omp_context *) cb;
1206 tree new_var;
1208 if (TREE_CODE (var) == LABEL_DECL)
1210 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1211 DECL_CONTEXT (new_var) = current_function_decl;
1212 insert_decl_map (&ctx->cb, var, new_var);
1213 return new_var;
1216 while (!is_taskreg_ctx (ctx))
1218 ctx = ctx->outer;
1219 if (ctx == NULL)
1220 return var;
1221 new_var = maybe_lookup_decl (var, ctx);
1222 if (new_var)
1223 return new_var;
1226 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1227 return var;
1229 return error_mark_node;
1233 /* Debugging dumps for parallel regions. */
1234 void dump_omp_region (FILE *, struct omp_region *, int);
1235 void debug_omp_region (struct omp_region *);
1236 void debug_all_omp_regions (void);
1238 /* Dump the parallel region tree rooted at REGION. */
1240 void
1241 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1243 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1244 gimple_code_name[region->type]);
1246 if (region->inner)
1247 dump_omp_region (file, region->inner, indent + 4);
1249 if (region->cont)
1251 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1252 region->cont->index);
1255 if (region->exit)
1256 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1257 region->exit->index);
1258 else
1259 fprintf (file, "%*s[no exit marker]\n", indent, "");
1261 if (region->next)
1262 dump_omp_region (file, region->next, indent);
1265 DEBUG_FUNCTION void
1266 debug_omp_region (struct omp_region *region)
1268 dump_omp_region (stderr, region, 0);
1271 DEBUG_FUNCTION void
1272 debug_all_omp_regions (void)
1274 dump_omp_region (stderr, root_omp_region, 0);
1278 /* Create a new parallel region starting at STMT inside region PARENT. */
1280 static struct omp_region *
1281 new_omp_region (basic_block bb, enum gimple_code type,
1282 struct omp_region *parent)
1284 struct omp_region *region = XCNEW (struct omp_region);
1286 region->outer = parent;
1287 region->entry = bb;
1288 region->type = type;
1290 if (parent)
1292 /* This is a nested region. Add it to the list of inner
1293 regions in PARENT. */
1294 region->next = parent->inner;
1295 parent->inner = region;
1297 else
1299 /* This is a toplevel region. Add it to the list of toplevel
1300 regions in ROOT_OMP_REGION. */
1301 region->next = root_omp_region;
1302 root_omp_region = region;
1305 return region;
1308 /* Release the memory associated with the region tree rooted at REGION. */
1310 static void
1311 free_omp_region_1 (struct omp_region *region)
1313 struct omp_region *i, *n;
1315 for (i = region->inner; i ; i = n)
1317 n = i->next;
1318 free_omp_region_1 (i);
1321 free (region);
1324 /* Release the memory for the entire omp region tree. */
1326 void
1327 free_omp_regions (void)
1329 struct omp_region *r, *n;
1330 for (r = root_omp_region; r ; r = n)
1332 n = r->next;
1333 free_omp_region_1 (r);
1335 root_omp_region = NULL;
1339 /* Create a new context, with OUTER_CTX being the surrounding context. */
1341 static omp_context *
1342 new_omp_context (gimple stmt, omp_context *outer_ctx)
1344 omp_context *ctx = XCNEW (omp_context);
1346 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1347 (splay_tree_value) ctx);
1348 ctx->stmt = stmt;
1350 if (outer_ctx)
1352 ctx->outer = outer_ctx;
1353 ctx->cb = outer_ctx->cb;
1354 ctx->cb.block = NULL;
1355 ctx->depth = outer_ctx->depth + 1;
1357 else
1359 ctx->cb.src_fn = current_function_decl;
1360 ctx->cb.dst_fn = current_function_decl;
1361 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1362 gcc_checking_assert (ctx->cb.src_node);
1363 ctx->cb.dst_node = ctx->cb.src_node;
1364 ctx->cb.src_cfun = cfun;
1365 ctx->cb.copy_decl = omp_copy_decl;
1366 ctx->cb.eh_lp_nr = 0;
1367 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1368 ctx->depth = 1;
1371 ctx->cb.decl_map = new hash_map<tree, tree>;
1373 return ctx;
1376 static gimple_seq maybe_catch_exception (gimple_seq);
1378 /* Finalize task copyfn. */
1380 static void
1381 finalize_task_copyfn (gimple task_stmt)
1383 struct function *child_cfun;
1384 tree child_fn;
1385 gimple_seq seq = NULL, new_seq;
1386 gimple bind;
1388 child_fn = gimple_omp_task_copy_fn (task_stmt);
1389 if (child_fn == NULL_TREE)
1390 return;
1392 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1393 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1395 push_cfun (child_cfun);
1396 bind = gimplify_body (child_fn, false);
1397 gimple_seq_add_stmt (&seq, bind);
1398 new_seq = maybe_catch_exception (seq);
1399 if (new_seq != seq)
1401 bind = gimple_build_bind (NULL, new_seq, NULL);
1402 seq = NULL;
1403 gimple_seq_add_stmt (&seq, bind);
1405 gimple_set_body (child_fn, seq);
1406 pop_cfun ();
1408 /* Inform the callgraph about the new function. */
1409 cgraph_node::add_new_function (child_fn, false);
1412 /* Destroy a omp_context data structures. Called through the splay tree
1413 value delete callback. */
1415 static void
1416 delete_omp_context (splay_tree_value value)
1418 omp_context *ctx = (omp_context *) value;
1420 delete ctx->cb.decl_map;
1422 if (ctx->field_map)
1423 splay_tree_delete (ctx->field_map);
1424 if (ctx->sfield_map)
1425 splay_tree_delete (ctx->sfield_map);
1427 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1428 it produces corrupt debug information. */
1429 if (ctx->record_type)
1431 tree t;
1432 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1433 DECL_ABSTRACT_ORIGIN (t) = NULL;
1435 if (ctx->srecord_type)
1437 tree t;
1438 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1439 DECL_ABSTRACT_ORIGIN (t) = NULL;
1442 if (is_task_ctx (ctx))
1443 finalize_task_copyfn (ctx->stmt);
1445 XDELETE (ctx);
1448 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1449 context. */
1451 static void
1452 fixup_child_record_type (omp_context *ctx)
1454 tree f, type = ctx->record_type;
1456 /* ??? It isn't sufficient to just call remap_type here, because
1457 variably_modified_type_p doesn't work the way we expect for
1458 record types. Testing each field for whether it needs remapping
1459 and creating a new record by hand works, however. */
1460 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1461 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1462 break;
1463 if (f)
1465 tree name, new_fields = NULL;
1467 type = lang_hooks.types.make_type (RECORD_TYPE);
1468 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1469 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1470 TYPE_DECL, name, type);
1471 TYPE_NAME (type) = name;
1473 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1475 tree new_f = copy_node (f);
1476 DECL_CONTEXT (new_f) = type;
1477 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1478 DECL_CHAIN (new_f) = new_fields;
1479 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1480 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1481 &ctx->cb, NULL);
1482 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1483 &ctx->cb, NULL);
1484 new_fields = new_f;
1486 /* Arrange to be able to look up the receiver field
1487 given the sender field. */
1488 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1489 (splay_tree_value) new_f);
1491 TYPE_FIELDS (type) = nreverse (new_fields);
1492 layout_type (type);
1495 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1498 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1499 specified by CLAUSES. */
1501 static void
1502 scan_sharing_clauses (tree clauses, omp_context *ctx)
1504 tree c, decl;
1505 bool scan_array_reductions = false;
1507 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1509 bool by_ref;
1511 switch (OMP_CLAUSE_CODE (c))
1513 case OMP_CLAUSE_PRIVATE:
1514 decl = OMP_CLAUSE_DECL (c);
1515 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1516 goto do_private;
1517 else if (!is_variable_sized (decl))
1518 install_var_local (decl, ctx);
1519 break;
1521 case OMP_CLAUSE_SHARED:
1522 decl = OMP_CLAUSE_DECL (c);
1523 /* Ignore shared directives in teams construct. */
1524 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1526 /* Global variables don't need to be copied,
1527 the receiver side will use them directly. */
1528 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1529 if (is_global_var (odecl))
1530 break;
1531 insert_decl_map (&ctx->cb, decl, odecl);
1532 break;
1534 gcc_assert (is_taskreg_ctx (ctx));
1535 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1536 || !is_variable_sized (decl));
1537 /* Global variables don't need to be copied,
1538 the receiver side will use them directly. */
1539 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1540 break;
1541 by_ref = use_pointer_for_field (decl, ctx);
1542 if (! TREE_READONLY (decl)
1543 || TREE_ADDRESSABLE (decl)
1544 || by_ref
1545 || is_reference (decl))
1547 install_var_field (decl, by_ref, 3, ctx);
1548 install_var_local (decl, ctx);
1549 break;
1551 /* We don't need to copy const scalar vars back. */
1552 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1553 goto do_private;
1555 case OMP_CLAUSE_LASTPRIVATE:
1556 /* Let the corresponding firstprivate clause create
1557 the variable. */
1558 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1559 break;
1560 /* FALLTHRU */
1562 case OMP_CLAUSE_FIRSTPRIVATE:
1563 case OMP_CLAUSE_REDUCTION:
1564 case OMP_CLAUSE_LINEAR:
1565 decl = OMP_CLAUSE_DECL (c);
1566 do_private:
1567 if (is_variable_sized (decl))
1569 if (is_task_ctx (ctx))
1570 install_var_field (decl, false, 1, ctx);
1571 break;
1573 else if (is_taskreg_ctx (ctx))
1575 bool global
1576 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1577 by_ref = use_pointer_for_field (decl, NULL);
1579 if (is_task_ctx (ctx)
1580 && (global || by_ref || is_reference (decl)))
1582 install_var_field (decl, false, 1, ctx);
1583 if (!global)
1584 install_var_field (decl, by_ref, 2, ctx);
1586 else if (!global)
1587 install_var_field (decl, by_ref, 3, ctx);
1589 install_var_local (decl, ctx);
1590 break;
1592 case OMP_CLAUSE__LOOPTEMP_:
1593 gcc_assert (is_parallel_ctx (ctx));
1594 decl = OMP_CLAUSE_DECL (c);
1595 install_var_field (decl, false, 3, ctx);
1596 install_var_local (decl, ctx);
1597 break;
1599 case OMP_CLAUSE_COPYPRIVATE:
1600 case OMP_CLAUSE_COPYIN:
1601 decl = OMP_CLAUSE_DECL (c);
1602 by_ref = use_pointer_for_field (decl, NULL);
1603 install_var_field (decl, by_ref, 3, ctx);
1604 break;
1606 case OMP_CLAUSE_DEFAULT:
1607 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1608 break;
1610 case OMP_CLAUSE_FINAL:
1611 case OMP_CLAUSE_IF:
1612 case OMP_CLAUSE_NUM_THREADS:
1613 case OMP_CLAUSE_NUM_TEAMS:
1614 case OMP_CLAUSE_THREAD_LIMIT:
1615 case OMP_CLAUSE_DEVICE:
1616 case OMP_CLAUSE_SCHEDULE:
1617 case OMP_CLAUSE_DIST_SCHEDULE:
1618 case OMP_CLAUSE_DEPEND:
1619 case OMP_CLAUSE__CILK_FOR_COUNT_:
1620 if (ctx->outer)
1621 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1622 break;
1624 case OMP_CLAUSE_TO:
1625 case OMP_CLAUSE_FROM:
1626 case OMP_CLAUSE_MAP:
1627 if (ctx->outer)
1628 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1629 decl = OMP_CLAUSE_DECL (c);
1630 /* Global variables with "omp declare target" attribute
1631 don't need to be copied, the receiver side will use them
1632 directly. */
1633 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1634 && DECL_P (decl)
1635 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1636 && lookup_attribute ("omp declare target",
1637 DECL_ATTRIBUTES (decl)))
1638 break;
1639 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1640 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1642 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1643 #pragma omp target data, there is nothing to map for
1644 those. */
1645 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1646 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1647 break;
1649 if (DECL_P (decl))
1651 if (DECL_SIZE (decl)
1652 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1654 tree decl2 = DECL_VALUE_EXPR (decl);
1655 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1656 decl2 = TREE_OPERAND (decl2, 0);
1657 gcc_assert (DECL_P (decl2));
1658 install_var_field (decl2, true, 3, ctx);
1659 install_var_local (decl2, ctx);
1660 install_var_local (decl, ctx);
1662 else
1664 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1665 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1666 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1667 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1668 install_var_field (decl, true, 7, ctx);
1669 else
1670 install_var_field (decl, true, 3, ctx);
1671 if (gimple_omp_target_kind (ctx->stmt)
1672 == GF_OMP_TARGET_KIND_REGION)
1673 install_var_local (decl, ctx);
1676 else
1678 tree base = get_base_address (decl);
1679 tree nc = OMP_CLAUSE_CHAIN (c);
1680 if (DECL_P (base)
1681 && nc != NULL_TREE
1682 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1683 && OMP_CLAUSE_DECL (nc) == base
1684 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1685 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1687 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1688 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1690 else
1692 if (ctx->outer)
1694 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1695 decl = OMP_CLAUSE_DECL (c);
1697 gcc_assert (!splay_tree_lookup (ctx->field_map,
1698 (splay_tree_key) decl));
1699 tree field
1700 = build_decl (OMP_CLAUSE_LOCATION (c),
1701 FIELD_DECL, NULL_TREE, ptr_type_node);
1702 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1703 insert_field_into_struct (ctx->record_type, field);
1704 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1705 (splay_tree_value) field);
1708 break;
1710 case OMP_CLAUSE_NOWAIT:
1711 case OMP_CLAUSE_ORDERED:
1712 case OMP_CLAUSE_COLLAPSE:
1713 case OMP_CLAUSE_UNTIED:
1714 case OMP_CLAUSE_MERGEABLE:
1715 case OMP_CLAUSE_PROC_BIND:
1716 case OMP_CLAUSE_SAFELEN:
1717 break;
1719 case OMP_CLAUSE_ALIGNED:
1720 decl = OMP_CLAUSE_DECL (c);
1721 if (is_global_var (decl)
1722 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1723 install_var_local (decl, ctx);
1724 break;
1726 default:
1727 gcc_unreachable ();
1731 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1733 switch (OMP_CLAUSE_CODE (c))
1735 case OMP_CLAUSE_LASTPRIVATE:
1736 /* Let the corresponding firstprivate clause create
1737 the variable. */
1738 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1739 scan_array_reductions = true;
1740 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1741 break;
1742 /* FALLTHRU */
1744 case OMP_CLAUSE_PRIVATE:
1745 case OMP_CLAUSE_FIRSTPRIVATE:
1746 case OMP_CLAUSE_REDUCTION:
1747 case OMP_CLAUSE_LINEAR:
1748 decl = OMP_CLAUSE_DECL (c);
1749 if (is_variable_sized (decl))
1750 install_var_local (decl, ctx);
1751 fixup_remapped_decl (decl, ctx,
1752 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1753 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1754 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1755 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1756 scan_array_reductions = true;
1757 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1758 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1759 scan_array_reductions = true;
1760 break;
1762 case OMP_CLAUSE_SHARED:
1763 /* Ignore shared directives in teams construct. */
1764 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1765 break;
1766 decl = OMP_CLAUSE_DECL (c);
1767 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1768 fixup_remapped_decl (decl, ctx, false);
1769 break;
1771 case OMP_CLAUSE_MAP:
1772 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1773 break;
1774 decl = OMP_CLAUSE_DECL (c);
1775 if (DECL_P (decl)
1776 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1777 && lookup_attribute ("omp declare target",
1778 DECL_ATTRIBUTES (decl)))
1779 break;
1780 if (DECL_P (decl))
1782 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1783 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1784 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1786 tree new_decl = lookup_decl (decl, ctx);
1787 TREE_TYPE (new_decl)
1788 = remap_type (TREE_TYPE (decl), &ctx->cb);
1790 else if (DECL_SIZE (decl)
1791 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1793 tree decl2 = DECL_VALUE_EXPR (decl);
1794 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1795 decl2 = TREE_OPERAND (decl2, 0);
1796 gcc_assert (DECL_P (decl2));
1797 fixup_remapped_decl (decl2, ctx, false);
1798 fixup_remapped_decl (decl, ctx, true);
1800 else
1801 fixup_remapped_decl (decl, ctx, false);
1803 break;
1805 case OMP_CLAUSE_COPYPRIVATE:
1806 case OMP_CLAUSE_COPYIN:
1807 case OMP_CLAUSE_DEFAULT:
1808 case OMP_CLAUSE_IF:
1809 case OMP_CLAUSE_NUM_THREADS:
1810 case OMP_CLAUSE_NUM_TEAMS:
1811 case OMP_CLAUSE_THREAD_LIMIT:
1812 case OMP_CLAUSE_DEVICE:
1813 case OMP_CLAUSE_SCHEDULE:
1814 case OMP_CLAUSE_DIST_SCHEDULE:
1815 case OMP_CLAUSE_NOWAIT:
1816 case OMP_CLAUSE_ORDERED:
1817 case OMP_CLAUSE_COLLAPSE:
1818 case OMP_CLAUSE_UNTIED:
1819 case OMP_CLAUSE_FINAL:
1820 case OMP_CLAUSE_MERGEABLE:
1821 case OMP_CLAUSE_PROC_BIND:
1822 case OMP_CLAUSE_SAFELEN:
1823 case OMP_CLAUSE_ALIGNED:
1824 case OMP_CLAUSE_DEPEND:
1825 case OMP_CLAUSE__LOOPTEMP_:
1826 case OMP_CLAUSE_TO:
1827 case OMP_CLAUSE_FROM:
1828 case OMP_CLAUSE__CILK_FOR_COUNT_:
1829 break;
1831 default:
1832 gcc_unreachable ();
1836 if (scan_array_reductions)
1837 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1838 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1839 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1841 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1842 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1844 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1845 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1846 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1847 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1848 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1849 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1852 /* Create a new name for omp child function. Returns an identifier. If
1853 IS_CILK_FOR is true then the suffix for the child function is
1854 "_cilk_for_fn." */
1856 static tree
1857 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1859 if (is_cilk_for)
1860 return clone_function_name (current_function_decl, "_cilk_for_fn");
1861 return clone_function_name (current_function_decl,
1862 task_copy ? "_omp_cpyfn" : "_omp_fn");
1865 /* Returns the type of the induction variable for the child function for
1866 _Cilk_for and the types for _high and _low variables based on TYPE. */
1868 static tree
1869 cilk_for_check_loop_diff_type (tree type)
1871 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
1873 if (TYPE_UNSIGNED (type))
1874 return uint32_type_node;
1875 else
1876 return integer_type_node;
1878 else
1880 if (TYPE_UNSIGNED (type))
1881 return uint64_type_node;
1882 else
1883 return long_long_integer_type_node;
1887 /* Build a decl for the omp child function. It'll not contain a body
1888 yet, just the bare decl. */
1890 static void
1891 create_omp_child_function (omp_context *ctx, bool task_copy)
1893 tree decl, type, name, t;
1895 tree cilk_for_count
1896 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
1897 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1898 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
1899 tree cilk_var_type = NULL_TREE;
1901 name = create_omp_child_function_name (task_copy,
1902 cilk_for_count != NULL_TREE);
1903 if (task_copy)
1904 type = build_function_type_list (void_type_node, ptr_type_node,
1905 ptr_type_node, NULL_TREE);
1906 else if (cilk_for_count)
1908 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
1909 cilk_var_type = cilk_for_check_loop_diff_type (type);
1910 type = build_function_type_list (void_type_node, ptr_type_node,
1911 cilk_var_type, cilk_var_type, NULL_TREE);
1913 else
1914 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1916 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1918 if (!task_copy)
1919 ctx->cb.dst_fn = decl;
1920 else
1921 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1923 TREE_STATIC (decl) = 1;
1924 TREE_USED (decl) = 1;
1925 DECL_ARTIFICIAL (decl) = 1;
1926 DECL_IGNORED_P (decl) = 0;
1927 TREE_PUBLIC (decl) = 0;
1928 DECL_UNINLINABLE (decl) = 1;
1929 DECL_EXTERNAL (decl) = 0;
1930 DECL_CONTEXT (decl) = NULL_TREE;
1931 DECL_INITIAL (decl) = make_node (BLOCK);
1932 bool target_p = false;
1933 if (lookup_attribute ("omp declare target",
1934 DECL_ATTRIBUTES (current_function_decl)))
1935 target_p = true;
1936 else
1938 omp_context *octx;
1939 for (octx = ctx; octx; octx = octx->outer)
1940 if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
1941 && gimple_omp_target_kind (octx->stmt)
1942 == GF_OMP_TARGET_KIND_REGION)
1944 target_p = true;
1945 break;
1948 if (target_p)
1949 DECL_ATTRIBUTES (decl)
1950 = tree_cons (get_identifier ("omp declare target"),
1951 NULL_TREE, DECL_ATTRIBUTES (decl));
1953 t = build_decl (DECL_SOURCE_LOCATION (decl),
1954 RESULT_DECL, NULL_TREE, void_type_node);
1955 DECL_ARTIFICIAL (t) = 1;
1956 DECL_IGNORED_P (t) = 1;
1957 DECL_CONTEXT (t) = decl;
1958 DECL_RESULT (decl) = t;
1960 /* _Cilk_for's child function requires two extra parameters called
1961 __low and __high that are set the by Cilk runtime when it calls this
1962 function. */
1963 if (cilk_for_count)
1965 t = build_decl (DECL_SOURCE_LOCATION (decl),
1966 PARM_DECL, get_identifier ("__high"), cilk_var_type);
1967 DECL_ARTIFICIAL (t) = 1;
1968 DECL_NAMELESS (t) = 1;
1969 DECL_ARG_TYPE (t) = ptr_type_node;
1970 DECL_CONTEXT (t) = current_function_decl;
1971 TREE_USED (t) = 1;
1972 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1973 DECL_ARGUMENTS (decl) = t;
1975 t = build_decl (DECL_SOURCE_LOCATION (decl),
1976 PARM_DECL, get_identifier ("__low"), cilk_var_type);
1977 DECL_ARTIFICIAL (t) = 1;
1978 DECL_NAMELESS (t) = 1;
1979 DECL_ARG_TYPE (t) = ptr_type_node;
1980 DECL_CONTEXT (t) = current_function_decl;
1981 TREE_USED (t) = 1;
1982 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1983 DECL_ARGUMENTS (decl) = t;
1986 tree data_name = get_identifier (".omp_data_i");
1987 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
1988 ptr_type_node);
1989 DECL_ARTIFICIAL (t) = 1;
1990 DECL_NAMELESS (t) = 1;
1991 DECL_ARG_TYPE (t) = ptr_type_node;
1992 DECL_CONTEXT (t) = current_function_decl;
1993 TREE_USED (t) = 1;
1994 if (cilk_for_count)
1995 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1996 DECL_ARGUMENTS (decl) = t;
1997 if (!task_copy)
1998 ctx->receiver_decl = t;
1999 else
2001 t = build_decl (DECL_SOURCE_LOCATION (decl),
2002 PARM_DECL, get_identifier (".omp_data_o"),
2003 ptr_type_node);
2004 DECL_ARTIFICIAL (t) = 1;
2005 DECL_NAMELESS (t) = 1;
2006 DECL_ARG_TYPE (t) = ptr_type_node;
2007 DECL_CONTEXT (t) = current_function_decl;
2008 TREE_USED (t) = 1;
2009 TREE_ADDRESSABLE (t) = 1;
2010 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2011 DECL_ARGUMENTS (decl) = t;
2014 /* Allocate memory for the function structure. The call to
2015 allocate_struct_function clobbers CFUN, so we need to restore
2016 it afterward. */
2017 push_struct_function (decl);
2018 cfun->function_end_locus = gimple_location (ctx->stmt);
2019 pop_cfun ();
2022 /* Callback for walk_gimple_seq. Check if combined parallel
2023 contains gimple_omp_for_combined_into_p OMP_FOR. */
2025 static tree
2026 find_combined_for (gimple_stmt_iterator *gsi_p,
2027 bool *handled_ops_p,
2028 struct walk_stmt_info *wi)
2030 gimple stmt = gsi_stmt (*gsi_p);
2032 *handled_ops_p = true;
2033 switch (gimple_code (stmt))
2035 WALK_SUBSTMTS;
2037 case GIMPLE_OMP_FOR:
2038 if (gimple_omp_for_combined_into_p (stmt)
2039 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2041 wi->info = stmt;
2042 return integer_zero_node;
2044 break;
2045 default:
2046 break;
2048 return NULL;
2051 /* Scan an OpenMP parallel directive. */
2053 static void
2054 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2056 omp_context *ctx;
2057 tree name;
2058 gimple stmt = gsi_stmt (*gsi);
2060 /* Ignore parallel directives with empty bodies, unless there
2061 are copyin clauses. */
2062 if (optimize > 0
2063 && empty_body_p (gimple_omp_body (stmt))
2064 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2065 OMP_CLAUSE_COPYIN) == NULL)
2067 gsi_replace (gsi, gimple_build_nop (), false);
2068 return;
2071 if (gimple_omp_parallel_combined_p (stmt))
2073 gimple for_stmt;
2074 struct walk_stmt_info wi;
2076 memset (&wi, 0, sizeof (wi));
2077 wi.val_only = true;
2078 walk_gimple_seq (gimple_omp_body (stmt),
2079 find_combined_for, NULL, &wi);
2080 for_stmt = (gimple) wi.info;
2081 if (for_stmt)
2083 struct omp_for_data fd;
2084 extract_omp_for_data (for_stmt, &fd, NULL);
2085 /* We need two temporaries with fd.loop.v type (istart/iend)
2086 and then (fd.collapse - 1) temporaries with the same
2087 type for count2 ... countN-1 vars if not constant. */
2088 size_t count = 2, i;
2089 tree type = fd.iter_type;
2090 if (fd.collapse > 1
2091 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2092 count += fd.collapse - 1;
2093 for (i = 0; i < count; i++)
2095 tree temp = create_tmp_var (type, NULL);
2096 tree c = build_omp_clause (UNKNOWN_LOCATION,
2097 OMP_CLAUSE__LOOPTEMP_);
2098 insert_decl_map (&outer_ctx->cb, temp, temp);
2099 OMP_CLAUSE_DECL (c) = temp;
2100 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2101 gimple_omp_parallel_set_clauses (stmt, c);
2106 ctx = new_omp_context (stmt, outer_ctx);
2107 taskreg_contexts.safe_push (ctx);
2108 if (taskreg_nesting_level > 1)
2109 ctx->is_nested = true;
2110 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2111 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2112 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2113 name = create_tmp_var_name (".omp_data_s");
2114 name = build_decl (gimple_location (stmt),
2115 TYPE_DECL, name, ctx->record_type);
2116 DECL_ARTIFICIAL (name) = 1;
2117 DECL_NAMELESS (name) = 1;
2118 TYPE_NAME (ctx->record_type) = name;
2119 create_omp_child_function (ctx, false);
2120 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2122 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2123 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2125 if (TYPE_FIELDS (ctx->record_type) == NULL)
2126 ctx->record_type = ctx->receiver_decl = NULL;
2129 /* Scan an OpenMP task directive. */
2131 static void
2132 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2134 omp_context *ctx;
2135 tree name, t;
2136 gimple stmt = gsi_stmt (*gsi);
2138 /* Ignore task directives with empty bodies. */
2139 if (optimize > 0
2140 && empty_body_p (gimple_omp_body (stmt)))
2142 gsi_replace (gsi, gimple_build_nop (), false);
2143 return;
2146 ctx = new_omp_context (stmt, outer_ctx);
2147 taskreg_contexts.safe_push (ctx);
2148 if (taskreg_nesting_level > 1)
2149 ctx->is_nested = true;
2150 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2151 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2152 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2153 name = create_tmp_var_name (".omp_data_s");
2154 name = build_decl (gimple_location (stmt),
2155 TYPE_DECL, name, ctx->record_type);
2156 DECL_ARTIFICIAL (name) = 1;
2157 DECL_NAMELESS (name) = 1;
2158 TYPE_NAME (ctx->record_type) = name;
2159 create_omp_child_function (ctx, false);
2160 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2162 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2164 if (ctx->srecord_type)
2166 name = create_tmp_var_name (".omp_data_a");
2167 name = build_decl (gimple_location (stmt),
2168 TYPE_DECL, name, ctx->srecord_type);
2169 DECL_ARTIFICIAL (name) = 1;
2170 DECL_NAMELESS (name) = 1;
2171 TYPE_NAME (ctx->srecord_type) = name;
2172 create_omp_child_function (ctx, true);
2175 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2177 if (TYPE_FIELDS (ctx->record_type) == NULL)
2179 ctx->record_type = ctx->receiver_decl = NULL;
2180 t = build_int_cst (long_integer_type_node, 0);
2181 gimple_omp_task_set_arg_size (stmt, t);
2182 t = build_int_cst (long_integer_type_node, 1);
2183 gimple_omp_task_set_arg_align (stmt, t);
2188 /* If any decls have been made addressable during scan_omp,
2189 adjust their fields if needed, and layout record types
2190 of parallel/task constructs. */
2192 static void
2193 finish_taskreg_scan (omp_context *ctx)
2195 if (ctx->record_type == NULL_TREE)
2196 return;
2198 /* If any task_shared_vars were needed, verify all
2199 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2200 statements if use_pointer_for_field hasn't changed
2201 because of that. If it did, update field types now. */
2202 if (task_shared_vars)
2204 tree c;
2206 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2207 c; c = OMP_CLAUSE_CHAIN (c))
2208 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2210 tree decl = OMP_CLAUSE_DECL (c);
2212 /* Global variables don't need to be copied,
2213 the receiver side will use them directly. */
2214 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2215 continue;
2216 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2217 || !use_pointer_for_field (decl, ctx))
2218 continue;
2219 tree field = lookup_field (decl, ctx);
2220 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2221 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2222 continue;
2223 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2224 TREE_THIS_VOLATILE (field) = 0;
2225 DECL_USER_ALIGN (field) = 0;
2226 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2227 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2228 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2229 if (ctx->srecord_type)
2231 tree sfield = lookup_sfield (decl, ctx);
2232 TREE_TYPE (sfield) = TREE_TYPE (field);
2233 TREE_THIS_VOLATILE (sfield) = 0;
2234 DECL_USER_ALIGN (sfield) = 0;
2235 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2236 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2237 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2242 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2244 layout_type (ctx->record_type);
2245 fixup_child_record_type (ctx);
2247 else
2249 location_t loc = gimple_location (ctx->stmt);
2250 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2251 /* Move VLA fields to the end. */
2252 p = &TYPE_FIELDS (ctx->record_type);
2253 while (*p)
2254 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2255 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2257 *q = *p;
2258 *p = TREE_CHAIN (*p);
2259 TREE_CHAIN (*q) = NULL_TREE;
2260 q = &TREE_CHAIN (*q);
2262 else
2263 p = &DECL_CHAIN (*p);
2264 *p = vla_fields;
2265 layout_type (ctx->record_type);
2266 fixup_child_record_type (ctx);
2267 if (ctx->srecord_type)
2268 layout_type (ctx->srecord_type);
2269 tree t = fold_convert_loc (loc, long_integer_type_node,
2270 TYPE_SIZE_UNIT (ctx->record_type));
2271 gimple_omp_task_set_arg_size (ctx->stmt, t);
2272 t = build_int_cst (long_integer_type_node,
2273 TYPE_ALIGN_UNIT (ctx->record_type));
2274 gimple_omp_task_set_arg_align (ctx->stmt, t);
2279 /* Scan an OpenMP loop directive. */
2281 static void
2282 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2284 omp_context *ctx;
2285 size_t i;
2287 ctx = new_omp_context (stmt, outer_ctx);
2289 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2291 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2292 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2294 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2295 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2296 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2297 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2299 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2302 /* Scan an OpenMP sections directive. */
2304 static void
2305 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2307 omp_context *ctx;
2309 ctx = new_omp_context (stmt, outer_ctx);
2310 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2311 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2314 /* Scan an OpenMP single directive. */
2316 static void
2317 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2319 omp_context *ctx;
2320 tree name;
2322 ctx = new_omp_context (stmt, outer_ctx);
2323 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2324 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2325 name = create_tmp_var_name (".omp_copy_s");
2326 name = build_decl (gimple_location (stmt),
2327 TYPE_DECL, name, ctx->record_type);
2328 TYPE_NAME (ctx->record_type) = name;
2330 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2331 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2333 if (TYPE_FIELDS (ctx->record_type) == NULL)
2334 ctx->record_type = NULL;
2335 else
2336 layout_type (ctx->record_type);
2339 /* Scan an OpenMP target{, data, update} directive. */
2341 static void
2342 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2344 omp_context *ctx;
2345 tree name;
2346 int kind = gimple_omp_target_kind (stmt);
2348 ctx = new_omp_context (stmt, outer_ctx);
2349 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2350 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2351 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2352 name = create_tmp_var_name (".omp_data_t");
2353 name = build_decl (gimple_location (stmt),
2354 TYPE_DECL, name, ctx->record_type);
2355 DECL_ARTIFICIAL (name) = 1;
2356 DECL_NAMELESS (name) = 1;
2357 TYPE_NAME (ctx->record_type) = name;
2358 if (kind == GF_OMP_TARGET_KIND_REGION)
2360 create_omp_child_function (ctx, false);
2361 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2364 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2365 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2367 if (TYPE_FIELDS (ctx->record_type) == NULL)
2368 ctx->record_type = ctx->receiver_decl = NULL;
2369 else
2371 TYPE_FIELDS (ctx->record_type)
2372 = nreverse (TYPE_FIELDS (ctx->record_type));
2373 #ifdef ENABLE_CHECKING
2374 tree field;
2375 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2376 for (field = TYPE_FIELDS (ctx->record_type);
2377 field;
2378 field = DECL_CHAIN (field))
2379 gcc_assert (DECL_ALIGN (field) == align);
2380 #endif
2381 layout_type (ctx->record_type);
2382 if (kind == GF_OMP_TARGET_KIND_REGION)
2383 fixup_child_record_type (ctx);
2387 /* Scan an OpenMP teams directive. */
2389 static void
2390 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2392 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2393 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2394 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2397 /* Check OpenMP nesting restrictions. */
2398 static bool
2399 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2401 if (ctx != NULL)
2403 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2404 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2406 error_at (gimple_location (stmt),
2407 "OpenMP constructs may not be nested inside simd region");
2408 return false;
2410 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2412 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2413 || (gimple_omp_for_kind (stmt)
2414 != GF_OMP_FOR_KIND_DISTRIBUTE))
2415 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2417 error_at (gimple_location (stmt),
2418 "only distribute or parallel constructs are allowed to "
2419 "be closely nested inside teams construct");
2420 return false;
2424 switch (gimple_code (stmt))
2426 case GIMPLE_OMP_FOR:
2427 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2428 return true;
2429 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2431 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2433 error_at (gimple_location (stmt),
2434 "distribute construct must be closely nested inside "
2435 "teams construct");
2436 return false;
2438 return true;
2440 /* FALLTHRU */
2441 case GIMPLE_CALL:
2442 if (is_gimple_call (stmt)
2443 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2444 == BUILT_IN_GOMP_CANCEL
2445 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2446 == BUILT_IN_GOMP_CANCELLATION_POINT))
2448 const char *bad = NULL;
2449 const char *kind = NULL;
2450 if (ctx == NULL)
2452 error_at (gimple_location (stmt), "orphaned %qs construct",
2453 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2454 == BUILT_IN_GOMP_CANCEL
2455 ? "#pragma omp cancel"
2456 : "#pragma omp cancellation point");
2457 return false;
2459 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2460 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2461 : 0)
2463 case 1:
2464 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2465 bad = "#pragma omp parallel";
2466 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2467 == BUILT_IN_GOMP_CANCEL
2468 && !integer_zerop (gimple_call_arg (stmt, 1)))
2469 ctx->cancellable = true;
2470 kind = "parallel";
2471 break;
2472 case 2:
2473 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2474 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2475 bad = "#pragma omp for";
2476 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2477 == BUILT_IN_GOMP_CANCEL
2478 && !integer_zerop (gimple_call_arg (stmt, 1)))
2480 ctx->cancellable = true;
2481 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2482 OMP_CLAUSE_NOWAIT))
2483 warning_at (gimple_location (stmt), 0,
2484 "%<#pragma omp cancel for%> inside "
2485 "%<nowait%> for construct");
2486 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2487 OMP_CLAUSE_ORDERED))
2488 warning_at (gimple_location (stmt), 0,
2489 "%<#pragma omp cancel for%> inside "
2490 "%<ordered%> for construct");
2492 kind = "for";
2493 break;
2494 case 4:
2495 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2496 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2497 bad = "#pragma omp sections";
2498 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2499 == BUILT_IN_GOMP_CANCEL
2500 && !integer_zerop (gimple_call_arg (stmt, 1)))
2502 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2504 ctx->cancellable = true;
2505 if (find_omp_clause (gimple_omp_sections_clauses
2506 (ctx->stmt),
2507 OMP_CLAUSE_NOWAIT))
2508 warning_at (gimple_location (stmt), 0,
2509 "%<#pragma omp cancel sections%> inside "
2510 "%<nowait%> sections construct");
2512 else
2514 gcc_assert (ctx->outer
2515 && gimple_code (ctx->outer->stmt)
2516 == GIMPLE_OMP_SECTIONS);
2517 ctx->outer->cancellable = true;
2518 if (find_omp_clause (gimple_omp_sections_clauses
2519 (ctx->outer->stmt),
2520 OMP_CLAUSE_NOWAIT))
2521 warning_at (gimple_location (stmt), 0,
2522 "%<#pragma omp cancel sections%> inside "
2523 "%<nowait%> sections construct");
2526 kind = "sections";
2527 break;
2528 case 8:
2529 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2530 bad = "#pragma omp task";
2531 else
2532 ctx->cancellable = true;
2533 kind = "taskgroup";
2534 break;
2535 default:
2536 error_at (gimple_location (stmt), "invalid arguments");
2537 return false;
2539 if (bad)
2541 error_at (gimple_location (stmt),
2542 "%<%s %s%> construct not closely nested inside of %qs",
2543 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2544 == BUILT_IN_GOMP_CANCEL
2545 ? "#pragma omp cancel"
2546 : "#pragma omp cancellation point", kind, bad);
2547 return false;
2550 /* FALLTHRU */
2551 case GIMPLE_OMP_SECTIONS:
2552 case GIMPLE_OMP_SINGLE:
2553 for (; ctx != NULL; ctx = ctx->outer)
2554 switch (gimple_code (ctx->stmt))
2556 case GIMPLE_OMP_FOR:
2557 case GIMPLE_OMP_SECTIONS:
2558 case GIMPLE_OMP_SINGLE:
2559 case GIMPLE_OMP_ORDERED:
2560 case GIMPLE_OMP_MASTER:
2561 case GIMPLE_OMP_TASK:
2562 case GIMPLE_OMP_CRITICAL:
2563 if (is_gimple_call (stmt))
2565 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2566 != BUILT_IN_GOMP_BARRIER)
2567 return true;
2568 error_at (gimple_location (stmt),
2569 "barrier region may not be closely nested inside "
2570 "of work-sharing, critical, ordered, master or "
2571 "explicit task region");
2572 return false;
2574 error_at (gimple_location (stmt),
2575 "work-sharing region may not be closely nested inside "
2576 "of work-sharing, critical, ordered, master or explicit "
2577 "task region");
2578 return false;
2579 case GIMPLE_OMP_PARALLEL:
2580 return true;
2581 default:
2582 break;
2584 break;
2585 case GIMPLE_OMP_MASTER:
2586 for (; ctx != NULL; ctx = ctx->outer)
2587 switch (gimple_code (ctx->stmt))
2589 case GIMPLE_OMP_FOR:
2590 case GIMPLE_OMP_SECTIONS:
2591 case GIMPLE_OMP_SINGLE:
2592 case GIMPLE_OMP_TASK:
2593 error_at (gimple_location (stmt),
2594 "master region may not be closely nested inside "
2595 "of work-sharing or explicit task region");
2596 return false;
2597 case GIMPLE_OMP_PARALLEL:
2598 return true;
2599 default:
2600 break;
2602 break;
2603 case GIMPLE_OMP_ORDERED:
2604 for (; ctx != NULL; ctx = ctx->outer)
2605 switch (gimple_code (ctx->stmt))
2607 case GIMPLE_OMP_CRITICAL:
2608 case GIMPLE_OMP_TASK:
2609 error_at (gimple_location (stmt),
2610 "ordered region may not be closely nested inside "
2611 "of critical or explicit task region");
2612 return false;
2613 case GIMPLE_OMP_FOR:
2614 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2615 OMP_CLAUSE_ORDERED) == NULL)
2617 error_at (gimple_location (stmt),
2618 "ordered region must be closely nested inside "
2619 "a loop region with an ordered clause");
2620 return false;
2622 return true;
2623 case GIMPLE_OMP_PARALLEL:
2624 error_at (gimple_location (stmt),
2625 "ordered region must be closely nested inside "
2626 "a loop region with an ordered clause");
2627 return false;
2628 default:
2629 break;
2631 break;
2632 case GIMPLE_OMP_CRITICAL:
2633 for (; ctx != NULL; ctx = ctx->outer)
2634 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2635 && (gimple_omp_critical_name (stmt)
2636 == gimple_omp_critical_name (ctx->stmt)))
2638 error_at (gimple_location (stmt),
2639 "critical region may not be nested inside a critical "
2640 "region with the same name");
2641 return false;
2643 break;
2644 case GIMPLE_OMP_TEAMS:
2645 if (ctx == NULL
2646 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2647 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2649 error_at (gimple_location (stmt),
2650 "teams construct not closely nested inside of target "
2651 "region");
2652 return false;
2654 break;
2655 case GIMPLE_OMP_TARGET:
2656 for (; ctx != NULL; ctx = ctx->outer)
2657 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
2658 && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION)
2660 const char *name;
2661 switch (gimple_omp_target_kind (stmt))
2663 case GF_OMP_TARGET_KIND_REGION: name = "target"; break;
2664 case GF_OMP_TARGET_KIND_DATA: name = "target data"; break;
2665 case GF_OMP_TARGET_KIND_UPDATE: name = "target update"; break;
2666 default: gcc_unreachable ();
2668 warning_at (gimple_location (stmt), 0,
2669 "%s construct inside of target region", name);
2671 break;
2672 default:
2673 break;
2675 return true;
2679 /* Helper function scan_omp.
2681 Callback for walk_tree or operators in walk_gimple_stmt used to
2682 scan for OpenMP directives in TP. */
2684 static tree
2685 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2687 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2688 omp_context *ctx = (omp_context *) wi->info;
2689 tree t = *tp;
2691 switch (TREE_CODE (t))
2693 case VAR_DECL:
2694 case PARM_DECL:
2695 case LABEL_DECL:
2696 case RESULT_DECL:
2697 if (ctx)
2698 *tp = remap_decl (t, &ctx->cb);
2699 break;
2701 default:
2702 if (ctx && TYPE_P (t))
2703 *tp = remap_type (t, &ctx->cb);
2704 else if (!DECL_P (t))
2706 *walk_subtrees = 1;
2707 if (ctx)
2709 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2710 if (tem != TREE_TYPE (t))
2712 if (TREE_CODE (t) == INTEGER_CST)
2713 *tp = wide_int_to_tree (tem, t);
2714 else
2715 TREE_TYPE (t) = tem;
2719 break;
2722 return NULL_TREE;
2725 /* Return true if FNDECL is a setjmp or a longjmp. */
2727 static bool
2728 setjmp_or_longjmp_p (const_tree fndecl)
2730 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2731 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2732 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2733 return true;
2735 tree declname = DECL_NAME (fndecl);
2736 if (!declname)
2737 return false;
2738 const char *name = IDENTIFIER_POINTER (declname);
2739 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2743 /* Helper function for scan_omp.
2745 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2746 the current statement in GSI. */
2748 static tree
2749 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2750 struct walk_stmt_info *wi)
2752 gimple stmt = gsi_stmt (*gsi);
2753 omp_context *ctx = (omp_context *) wi->info;
2755 if (gimple_has_location (stmt))
2756 input_location = gimple_location (stmt);
2758 /* Check the OpenMP nesting restrictions. */
2759 bool remove = false;
2760 if (is_gimple_omp (stmt))
2761 remove = !check_omp_nesting_restrictions (stmt, ctx);
2762 else if (is_gimple_call (stmt))
2764 tree fndecl = gimple_call_fndecl (stmt);
2765 if (fndecl)
2767 if (setjmp_or_longjmp_p (fndecl)
2768 && ctx
2769 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2770 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2772 remove = true;
2773 error_at (gimple_location (stmt),
2774 "setjmp/longjmp inside simd construct");
2776 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2777 switch (DECL_FUNCTION_CODE (fndecl))
2779 case BUILT_IN_GOMP_BARRIER:
2780 case BUILT_IN_GOMP_CANCEL:
2781 case BUILT_IN_GOMP_CANCELLATION_POINT:
2782 case BUILT_IN_GOMP_TASKYIELD:
2783 case BUILT_IN_GOMP_TASKWAIT:
2784 case BUILT_IN_GOMP_TASKGROUP_START:
2785 case BUILT_IN_GOMP_TASKGROUP_END:
2786 remove = !check_omp_nesting_restrictions (stmt, ctx);
2787 break;
2788 default:
2789 break;
2793 if (remove)
2795 stmt = gimple_build_nop ();
2796 gsi_replace (gsi, stmt, false);
2799 *handled_ops_p = true;
2801 switch (gimple_code (stmt))
2803 case GIMPLE_OMP_PARALLEL:
2804 taskreg_nesting_level++;
2805 scan_omp_parallel (gsi, ctx);
2806 taskreg_nesting_level--;
2807 break;
2809 case GIMPLE_OMP_TASK:
2810 taskreg_nesting_level++;
2811 scan_omp_task (gsi, ctx);
2812 taskreg_nesting_level--;
2813 break;
2815 case GIMPLE_OMP_FOR:
2816 scan_omp_for (stmt, ctx);
2817 break;
2819 case GIMPLE_OMP_SECTIONS:
2820 scan_omp_sections (stmt, ctx);
2821 break;
2823 case GIMPLE_OMP_SINGLE:
2824 scan_omp_single (stmt, ctx);
2825 break;
2827 case GIMPLE_OMP_SECTION:
2828 case GIMPLE_OMP_MASTER:
2829 case GIMPLE_OMP_TASKGROUP:
2830 case GIMPLE_OMP_ORDERED:
2831 case GIMPLE_OMP_CRITICAL:
2832 ctx = new_omp_context (stmt, ctx);
2833 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2834 break;
2836 case GIMPLE_OMP_TARGET:
2837 scan_omp_target (stmt, ctx);
2838 break;
2840 case GIMPLE_OMP_TEAMS:
2841 scan_omp_teams (stmt, ctx);
2842 break;
2844 case GIMPLE_BIND:
2846 tree var;
2848 *handled_ops_p = false;
2849 if (ctx)
2850 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2851 insert_decl_map (&ctx->cb, var, var);
2853 break;
2854 default:
2855 *handled_ops_p = false;
2856 break;
2859 return NULL_TREE;
2863 /* Scan all the statements starting at the current statement. CTX
2864 contains context information about the OpenMP directives and
2865 clauses found during the scan. */
2867 static void
2868 scan_omp (gimple_seq *body_p, omp_context *ctx)
2870 location_t saved_location;
2871 struct walk_stmt_info wi;
2873 memset (&wi, 0, sizeof (wi));
2874 wi.info = ctx;
2875 wi.want_locations = true;
2877 saved_location = input_location;
2878 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2879 input_location = saved_location;
2882 /* Re-gimplification and code generation routines. */
2884 /* Build a call to GOMP_barrier. */
2886 static gimple
2887 build_omp_barrier (tree lhs)
2889 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2890 : BUILT_IN_GOMP_BARRIER);
2891 gimple g = gimple_build_call (fndecl, 0);
2892 if (lhs)
2893 gimple_call_set_lhs (g, lhs);
2894 return g;
2897 /* If a context was created for STMT when it was scanned, return it. */
2899 static omp_context *
2900 maybe_lookup_ctx (gimple stmt)
2902 splay_tree_node n;
2903 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2904 return n ? (omp_context *) n->value : NULL;
2908 /* Find the mapping for DECL in CTX or the immediately enclosing
2909 context that has a mapping for DECL.
2911 If CTX is a nested parallel directive, we may have to use the decl
2912 mappings created in CTX's parent context. Suppose that we have the
2913 following parallel nesting (variable UIDs showed for clarity):
2915 iD.1562 = 0;
2916 #omp parallel shared(iD.1562) -> outer parallel
2917 iD.1562 = iD.1562 + 1;
2919 #omp parallel shared (iD.1562) -> inner parallel
2920 iD.1562 = iD.1562 - 1;
2922 Each parallel structure will create a distinct .omp_data_s structure
2923 for copying iD.1562 in/out of the directive:
2925 outer parallel .omp_data_s.1.i -> iD.1562
2926 inner parallel .omp_data_s.2.i -> iD.1562
2928 A shared variable mapping will produce a copy-out operation before
2929 the parallel directive and a copy-in operation after it. So, in
2930 this case we would have:
2932 iD.1562 = 0;
2933 .omp_data_o.1.i = iD.1562;
2934 #omp parallel shared(iD.1562) -> outer parallel
2935 .omp_data_i.1 = &.omp_data_o.1
2936 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2938 .omp_data_o.2.i = iD.1562; -> **
2939 #omp parallel shared(iD.1562) -> inner parallel
2940 .omp_data_i.2 = &.omp_data_o.2
2941 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2944 ** This is a problem. The symbol iD.1562 cannot be referenced
2945 inside the body of the outer parallel region. But since we are
2946 emitting this copy operation while expanding the inner parallel
2947 directive, we need to access the CTX structure of the outer
2948 parallel directive to get the correct mapping:
2950 .omp_data_o.2.i = .omp_data_i.1->i
2952 Since there may be other workshare or parallel directives enclosing
2953 the parallel directive, it may be necessary to walk up the context
2954 parent chain. This is not a problem in general because nested
2955 parallelism happens only rarely. */
2957 static tree
2958 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2960 tree t;
2961 omp_context *up;
2963 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2964 t = maybe_lookup_decl (decl, up);
2966 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2968 return t ? t : decl;
2972 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2973 in outer contexts. */
2975 static tree
2976 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2978 tree t = NULL;
2979 omp_context *up;
2981 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2982 t = maybe_lookup_decl (decl, up);
2984 return t ? t : decl;
2988 /* Construct the initialization value for reduction CLAUSE. */
2990 tree
2991 omp_reduction_init (tree clause, tree type)
2993 location_t loc = OMP_CLAUSE_LOCATION (clause);
2994 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2996 case PLUS_EXPR:
2997 case MINUS_EXPR:
2998 case BIT_IOR_EXPR:
2999 case BIT_XOR_EXPR:
3000 case TRUTH_OR_EXPR:
3001 case TRUTH_ORIF_EXPR:
3002 case TRUTH_XOR_EXPR:
3003 case NE_EXPR:
3004 return build_zero_cst (type);
3006 case MULT_EXPR:
3007 case TRUTH_AND_EXPR:
3008 case TRUTH_ANDIF_EXPR:
3009 case EQ_EXPR:
3010 return fold_convert_loc (loc, type, integer_one_node);
3012 case BIT_AND_EXPR:
3013 return fold_convert_loc (loc, type, integer_minus_one_node);
3015 case MAX_EXPR:
3016 if (SCALAR_FLOAT_TYPE_P (type))
3018 REAL_VALUE_TYPE max, min;
3019 if (HONOR_INFINITIES (TYPE_MODE (type)))
3021 real_inf (&max);
3022 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3024 else
3025 real_maxval (&min, 1, TYPE_MODE (type));
3026 return build_real (type, min);
3028 else
3030 gcc_assert (INTEGRAL_TYPE_P (type));
3031 return TYPE_MIN_VALUE (type);
3034 case MIN_EXPR:
3035 if (SCALAR_FLOAT_TYPE_P (type))
3037 REAL_VALUE_TYPE max;
3038 if (HONOR_INFINITIES (TYPE_MODE (type)))
3039 real_inf (&max);
3040 else
3041 real_maxval (&max, 0, TYPE_MODE (type));
3042 return build_real (type, max);
3044 else
3046 gcc_assert (INTEGRAL_TYPE_P (type));
3047 return TYPE_MAX_VALUE (type);
3050 default:
3051 gcc_unreachable ();
3055 /* Return alignment to be assumed for var in CLAUSE, which should be
3056 OMP_CLAUSE_ALIGNED. */
3058 static tree
3059 omp_clause_aligned_alignment (tree clause)
3061 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3062 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3064 /* Otherwise return implementation defined alignment. */
3065 unsigned int al = 1;
3066 enum machine_mode mode, vmode;
3067 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3068 if (vs)
3069 vs = 1 << floor_log2 (vs);
3070 static enum mode_class classes[]
3071 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3072 for (int i = 0; i < 4; i += 2)
3073 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3074 mode != VOIDmode;
3075 mode = GET_MODE_WIDER_MODE (mode))
3077 vmode = targetm.vectorize.preferred_simd_mode (mode);
3078 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3079 continue;
3080 while (vs
3081 && GET_MODE_SIZE (vmode) < vs
3082 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3083 vmode = GET_MODE_2XWIDER_MODE (vmode);
3085 tree type = lang_hooks.types.type_for_mode (mode, 1);
3086 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3087 continue;
3088 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3089 / GET_MODE_SIZE (mode));
3090 if (TYPE_MODE (type) != vmode)
3091 continue;
3092 if (TYPE_ALIGN_UNIT (type) > al)
3093 al = TYPE_ALIGN_UNIT (type);
3095 return build_int_cst (integer_type_node, al);
3098 /* Return maximum possible vectorization factor for the target. */
3100 static int
3101 omp_max_vf (void)
3103 if (!optimize
3104 || optimize_debug
3105 || !flag_tree_loop_optimize
3106 || (!flag_tree_loop_vectorize
3107 && (global_options_set.x_flag_tree_loop_vectorize
3108 || global_options_set.x_flag_tree_vectorize)))
3109 return 1;
3111 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3112 if (vs)
3114 vs = 1 << floor_log2 (vs);
3115 return vs;
3117 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3118 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3119 return GET_MODE_NUNITS (vqimode);
3120 return 1;
3123 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3124 privatization. */
3126 static bool
3127 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3128 tree &idx, tree &lane, tree &ivar, tree &lvar)
3130 if (max_vf == 0)
3132 max_vf = omp_max_vf ();
3133 if (max_vf > 1)
3135 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3136 OMP_CLAUSE_SAFELEN);
3137 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3138 max_vf = 1;
3139 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3140 max_vf) == -1)
3141 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3143 if (max_vf > 1)
3145 idx = create_tmp_var (unsigned_type_node, NULL);
3146 lane = create_tmp_var (unsigned_type_node, NULL);
3149 if (max_vf == 1)
3150 return false;
3152 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3153 tree avar = create_tmp_var_raw (atype, NULL);
3154 if (TREE_ADDRESSABLE (new_var))
3155 TREE_ADDRESSABLE (avar) = 1;
3156 DECL_ATTRIBUTES (avar)
3157 = tree_cons (get_identifier ("omp simd array"), NULL,
3158 DECL_ATTRIBUTES (avar));
3159 gimple_add_tmp_var (avar);
3160 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3161 NULL_TREE, NULL_TREE);
3162 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3163 NULL_TREE, NULL_TREE);
3164 if (DECL_P (new_var))
3166 SET_DECL_VALUE_EXPR (new_var, lvar);
3167 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3169 return true;
3172 /* Helper function of lower_rec_input_clauses. For a reference
3173 in simd reduction, add an underlying variable it will reference. */
3175 static void
3176 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3178 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3179 if (TREE_CONSTANT (z))
3181 const char *name = NULL;
3182 if (DECL_NAME (new_vard))
3183 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3185 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3186 gimple_add_tmp_var (z);
3187 TREE_ADDRESSABLE (z) = 1;
3188 z = build_fold_addr_expr_loc (loc, z);
3189 gimplify_assign (new_vard, z, ilist);
3193 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3194 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3195 private variables. Initialization statements go in ILIST, while calls
3196 to destructors go in DLIST. */
3198 static void
3199 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3200 omp_context *ctx, struct omp_for_data *fd)
3202 tree c, dtor, copyin_seq, x, ptr;
3203 bool copyin_by_ref = false;
3204 bool lastprivate_firstprivate = false;
3205 bool reduction_omp_orig_ref = false;
3206 int pass;
3207 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3208 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3209 int max_vf = 0;
3210 tree lane = NULL_TREE, idx = NULL_TREE;
3211 tree ivar = NULL_TREE, lvar = NULL_TREE;
3212 gimple_seq llist[2] = { NULL, NULL };
3214 copyin_seq = NULL;
3216 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3217 with data sharing clauses referencing variable sized vars. That
3218 is unnecessarily hard to support and very unlikely to result in
3219 vectorized code anyway. */
3220 if (is_simd)
3221 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3222 switch (OMP_CLAUSE_CODE (c))
3224 case OMP_CLAUSE_LINEAR:
3225 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3226 max_vf = 1;
3227 /* FALLTHRU */
3228 case OMP_CLAUSE_REDUCTION:
3229 case OMP_CLAUSE_PRIVATE:
3230 case OMP_CLAUSE_FIRSTPRIVATE:
3231 case OMP_CLAUSE_LASTPRIVATE:
3232 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3233 max_vf = 1;
3234 break;
3235 default:
3236 continue;
3239 /* Do all the fixed sized types in the first pass, and the variable sized
3240 types in the second pass. This makes sure that the scalar arguments to
3241 the variable sized types are processed before we use them in the
3242 variable sized operations. */
3243 for (pass = 0; pass < 2; ++pass)
3245 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3247 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3248 tree var, new_var;
3249 bool by_ref;
3250 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3252 switch (c_kind)
3254 case OMP_CLAUSE_PRIVATE:
3255 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3256 continue;
3257 break;
3258 case OMP_CLAUSE_SHARED:
3259 /* Ignore shared directives in teams construct. */
3260 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3261 continue;
3262 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3264 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3265 continue;
3267 case OMP_CLAUSE_FIRSTPRIVATE:
3268 case OMP_CLAUSE_COPYIN:
3269 case OMP_CLAUSE_LINEAR:
3270 break;
3271 case OMP_CLAUSE_REDUCTION:
3272 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3273 reduction_omp_orig_ref = true;
3274 break;
3275 case OMP_CLAUSE__LOOPTEMP_:
3276 /* Handle _looptemp_ clauses only on parallel. */
3277 if (fd)
3278 continue;
3279 break;
3280 case OMP_CLAUSE_LASTPRIVATE:
3281 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3283 lastprivate_firstprivate = true;
3284 if (pass != 0)
3285 continue;
3287 /* Even without corresponding firstprivate, if
3288 decl is Fortran allocatable, it needs outer var
3289 reference. */
3290 else if (pass == 0
3291 && lang_hooks.decls.omp_private_outer_ref
3292 (OMP_CLAUSE_DECL (c)))
3293 lastprivate_firstprivate = true;
3294 break;
3295 case OMP_CLAUSE_ALIGNED:
3296 if (pass == 0)
3297 continue;
3298 var = OMP_CLAUSE_DECL (c);
3299 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3300 && !is_global_var (var))
3302 new_var = maybe_lookup_decl (var, ctx);
3303 if (new_var == NULL_TREE)
3304 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3305 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3306 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3307 omp_clause_aligned_alignment (c));
3308 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3309 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3310 gimplify_and_add (x, ilist);
3312 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3313 && is_global_var (var))
3315 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3316 new_var = lookup_decl (var, ctx);
3317 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3318 t = build_fold_addr_expr_loc (clause_loc, t);
3319 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3320 t = build_call_expr_loc (clause_loc, t2, 2, t,
3321 omp_clause_aligned_alignment (c));
3322 t = fold_convert_loc (clause_loc, ptype, t);
3323 x = create_tmp_var (ptype, NULL);
3324 t = build2 (MODIFY_EXPR, ptype, x, t);
3325 gimplify_and_add (t, ilist);
3326 t = build_simple_mem_ref_loc (clause_loc, x);
3327 SET_DECL_VALUE_EXPR (new_var, t);
3328 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3330 continue;
3331 default:
3332 continue;
3335 new_var = var = OMP_CLAUSE_DECL (c);
3336 if (c_kind != OMP_CLAUSE_COPYIN)
3337 new_var = lookup_decl (var, ctx);
3339 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3341 if (pass != 0)
3342 continue;
3344 else if (is_variable_sized (var))
3346 /* For variable sized types, we need to allocate the
3347 actual storage here. Call alloca and store the
3348 result in the pointer decl that we created elsewhere. */
3349 if (pass == 0)
3350 continue;
3352 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3354 gimple stmt;
3355 tree tmp, atmp;
3357 ptr = DECL_VALUE_EXPR (new_var);
3358 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3359 ptr = TREE_OPERAND (ptr, 0);
3360 gcc_assert (DECL_P (ptr));
3361 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3363 /* void *tmp = __builtin_alloca */
3364 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3365 stmt = gimple_build_call (atmp, 1, x);
3366 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3367 gimple_add_tmp_var (tmp);
3368 gimple_call_set_lhs (stmt, tmp);
3370 gimple_seq_add_stmt (ilist, stmt);
3372 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3373 gimplify_assign (ptr, x, ilist);
3376 else if (is_reference (var))
3378 /* For references that are being privatized for Fortran,
3379 allocate new backing storage for the new pointer
3380 variable. This allows us to avoid changing all the
3381 code that expects a pointer to something that expects
3382 a direct variable. */
3383 if (pass == 0)
3384 continue;
3386 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3387 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3389 x = build_receiver_ref (var, false, ctx);
3390 x = build_fold_addr_expr_loc (clause_loc, x);
3392 else if (TREE_CONSTANT (x))
3394 /* For reduction in SIMD loop, defer adding the
3395 initialization of the reference, because if we decide
3396 to use SIMD array for it, the initilization could cause
3397 expansion ICE. */
3398 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3399 x = NULL_TREE;
3400 else
3402 const char *name = NULL;
3403 if (DECL_NAME (var))
3404 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3406 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3407 name);
3408 gimple_add_tmp_var (x);
3409 TREE_ADDRESSABLE (x) = 1;
3410 x = build_fold_addr_expr_loc (clause_loc, x);
3413 else
3415 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3416 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3419 if (x)
3421 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3422 gimplify_assign (new_var, x, ilist);
3425 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3427 else if (c_kind == OMP_CLAUSE_REDUCTION
3428 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3430 if (pass == 0)
3431 continue;
3433 else if (pass != 0)
3434 continue;
3436 switch (OMP_CLAUSE_CODE (c))
3438 case OMP_CLAUSE_SHARED:
3439 /* Ignore shared directives in teams construct. */
3440 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3441 continue;
3442 /* Shared global vars are just accessed directly. */
3443 if (is_global_var (new_var))
3444 break;
3445 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3446 needs to be delayed until after fixup_child_record_type so
3447 that we get the correct type during the dereference. */
3448 by_ref = use_pointer_for_field (var, ctx);
3449 x = build_receiver_ref (var, by_ref, ctx);
3450 SET_DECL_VALUE_EXPR (new_var, x);
3451 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3453 /* ??? If VAR is not passed by reference, and the variable
3454 hasn't been initialized yet, then we'll get a warning for
3455 the store into the omp_data_s structure. Ideally, we'd be
3456 able to notice this and not store anything at all, but
3457 we're generating code too early. Suppress the warning. */
3458 if (!by_ref)
3459 TREE_NO_WARNING (var) = 1;
3460 break;
3462 case OMP_CLAUSE_LASTPRIVATE:
3463 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3464 break;
3465 /* FALLTHRU */
3467 case OMP_CLAUSE_PRIVATE:
3468 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3469 x = build_outer_var_ref (var, ctx);
3470 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3472 if (is_task_ctx (ctx))
3473 x = build_receiver_ref (var, false, ctx);
3474 else
3475 x = build_outer_var_ref (var, ctx);
3477 else
3478 x = NULL;
3479 do_private:
3480 tree nx;
3481 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3482 if (is_simd)
3484 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3485 if ((TREE_ADDRESSABLE (new_var) || nx || y
3486 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3487 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3488 idx, lane, ivar, lvar))
3490 if (nx)
3491 x = lang_hooks.decls.omp_clause_default_ctor
3492 (c, unshare_expr (ivar), x);
3493 if (nx && x)
3494 gimplify_and_add (x, &llist[0]);
3495 if (y)
3497 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3498 if (y)
3500 gimple_seq tseq = NULL;
3502 dtor = y;
3503 gimplify_stmt (&dtor, &tseq);
3504 gimple_seq_add_seq (&llist[1], tseq);
3507 break;
3510 if (nx)
3511 gimplify_and_add (nx, ilist);
3512 /* FALLTHRU */
3514 do_dtor:
3515 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3516 if (x)
3518 gimple_seq tseq = NULL;
3520 dtor = x;
3521 gimplify_stmt (&dtor, &tseq);
3522 gimple_seq_add_seq (dlist, tseq);
3524 break;
3526 case OMP_CLAUSE_LINEAR:
3527 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3528 goto do_firstprivate;
3529 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3530 x = NULL;
3531 else
3532 x = build_outer_var_ref (var, ctx);
3533 goto do_private;
3535 case OMP_CLAUSE_FIRSTPRIVATE:
3536 if (is_task_ctx (ctx))
3538 if (is_reference (var) || is_variable_sized (var))
3539 goto do_dtor;
3540 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3541 ctx))
3542 || use_pointer_for_field (var, NULL))
3544 x = build_receiver_ref (var, false, ctx);
3545 SET_DECL_VALUE_EXPR (new_var, x);
3546 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3547 goto do_dtor;
3550 do_firstprivate:
3551 x = build_outer_var_ref (var, ctx);
3552 if (is_simd)
3554 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3555 && gimple_omp_for_combined_into_p (ctx->stmt))
3557 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3558 tree stept = TREE_TYPE (t);
3559 tree ct = find_omp_clause (clauses,
3560 OMP_CLAUSE__LOOPTEMP_);
3561 gcc_assert (ct);
3562 tree l = OMP_CLAUSE_DECL (ct);
3563 tree n1 = fd->loop.n1;
3564 tree step = fd->loop.step;
3565 tree itype = TREE_TYPE (l);
3566 if (POINTER_TYPE_P (itype))
3567 itype = signed_type_for (itype);
3568 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3569 if (TYPE_UNSIGNED (itype)
3570 && fd->loop.cond_code == GT_EXPR)
3571 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3572 fold_build1 (NEGATE_EXPR, itype, l),
3573 fold_build1 (NEGATE_EXPR,
3574 itype, step));
3575 else
3576 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3577 t = fold_build2 (MULT_EXPR, stept,
3578 fold_convert (stept, l), t);
3580 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3582 x = lang_hooks.decls.omp_clause_linear_ctor
3583 (c, new_var, x, t);
3584 gimplify_and_add (x, ilist);
3585 goto do_dtor;
3588 if (POINTER_TYPE_P (TREE_TYPE (x)))
3589 x = fold_build2 (POINTER_PLUS_EXPR,
3590 TREE_TYPE (x), x, t);
3591 else
3592 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3595 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3596 || TREE_ADDRESSABLE (new_var))
3597 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3598 idx, lane, ivar, lvar))
3600 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3602 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3603 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3604 gimplify_and_add (x, ilist);
3605 gimple_stmt_iterator gsi
3606 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3607 gimple g
3608 = gimple_build_assign (unshare_expr (lvar), iv);
3609 gsi_insert_before_without_update (&gsi, g,
3610 GSI_SAME_STMT);
3611 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3612 enum tree_code code = PLUS_EXPR;
3613 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3614 code = POINTER_PLUS_EXPR;
3615 g = gimple_build_assign_with_ops (code, iv, iv, t);
3616 gsi_insert_before_without_update (&gsi, g,
3617 GSI_SAME_STMT);
3618 break;
3620 x = lang_hooks.decls.omp_clause_copy_ctor
3621 (c, unshare_expr (ivar), x);
3622 gimplify_and_add (x, &llist[0]);
3623 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3624 if (x)
3626 gimple_seq tseq = NULL;
3628 dtor = x;
3629 gimplify_stmt (&dtor, &tseq);
3630 gimple_seq_add_seq (&llist[1], tseq);
3632 break;
3635 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3636 gimplify_and_add (x, ilist);
3637 goto do_dtor;
3639 case OMP_CLAUSE__LOOPTEMP_:
3640 gcc_assert (is_parallel_ctx (ctx));
3641 x = build_outer_var_ref (var, ctx);
3642 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3643 gimplify_and_add (x, ilist);
3644 break;
3646 case OMP_CLAUSE_COPYIN:
3647 by_ref = use_pointer_for_field (var, NULL);
3648 x = build_receiver_ref (var, by_ref, ctx);
3649 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3650 append_to_statement_list (x, &copyin_seq);
3651 copyin_by_ref |= by_ref;
3652 break;
3654 case OMP_CLAUSE_REDUCTION:
3655 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3657 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3658 gimple tseq;
3659 x = build_outer_var_ref (var, ctx);
3661 if (is_reference (var)
3662 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3663 TREE_TYPE (x)))
3664 x = build_fold_addr_expr_loc (clause_loc, x);
3665 SET_DECL_VALUE_EXPR (placeholder, x);
3666 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3667 tree new_vard = new_var;
3668 if (is_reference (var))
3670 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3671 new_vard = TREE_OPERAND (new_var, 0);
3672 gcc_assert (DECL_P (new_vard));
3674 if (is_simd
3675 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3676 idx, lane, ivar, lvar))
3678 if (new_vard == new_var)
3680 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3681 SET_DECL_VALUE_EXPR (new_var, ivar);
3683 else
3685 SET_DECL_VALUE_EXPR (new_vard,
3686 build_fold_addr_expr (ivar));
3687 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3689 x = lang_hooks.decls.omp_clause_default_ctor
3690 (c, unshare_expr (ivar),
3691 build_outer_var_ref (var, ctx));
3692 if (x)
3693 gimplify_and_add (x, &llist[0]);
3694 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3696 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3697 lower_omp (&tseq, ctx);
3698 gimple_seq_add_seq (&llist[0], tseq);
3700 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3701 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3702 lower_omp (&tseq, ctx);
3703 gimple_seq_add_seq (&llist[1], tseq);
3704 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3705 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3706 if (new_vard == new_var)
3707 SET_DECL_VALUE_EXPR (new_var, lvar);
3708 else
3709 SET_DECL_VALUE_EXPR (new_vard,
3710 build_fold_addr_expr (lvar));
3711 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3712 if (x)
3714 tseq = NULL;
3715 dtor = x;
3716 gimplify_stmt (&dtor, &tseq);
3717 gimple_seq_add_seq (&llist[1], tseq);
3719 break;
3721 /* If this is a reference to constant size reduction var
3722 with placeholder, we haven't emitted the initializer
3723 for it because it is undesirable if SIMD arrays are used.
3724 But if they aren't used, we need to emit the deferred
3725 initialization now. */
3726 else if (is_reference (var) && is_simd)
3727 handle_simd_reference (clause_loc, new_vard, ilist);
3728 x = lang_hooks.decls.omp_clause_default_ctor
3729 (c, unshare_expr (new_var),
3730 build_outer_var_ref (var, ctx));
3731 if (x)
3732 gimplify_and_add (x, ilist);
3733 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3735 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3736 lower_omp (&tseq, ctx);
3737 gimple_seq_add_seq (ilist, tseq);
3739 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3740 if (is_simd)
3742 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3743 lower_omp (&tseq, ctx);
3744 gimple_seq_add_seq (dlist, tseq);
3745 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3747 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3748 goto do_dtor;
3750 else
3752 x = omp_reduction_init (c, TREE_TYPE (new_var));
3753 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3754 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3756 /* reduction(-:var) sums up the partial results, so it
3757 acts identically to reduction(+:var). */
3758 if (code == MINUS_EXPR)
3759 code = PLUS_EXPR;
3761 tree new_vard = new_var;
3762 if (is_simd && is_reference (var))
3764 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3765 new_vard = TREE_OPERAND (new_var, 0);
3766 gcc_assert (DECL_P (new_vard));
3768 if (is_simd
3769 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3770 idx, lane, ivar, lvar))
3772 tree ref = build_outer_var_ref (var, ctx);
3774 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3776 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3777 ref = build_outer_var_ref (var, ctx);
3778 gimplify_assign (ref, x, &llist[1]);
3780 if (new_vard != new_var)
3782 SET_DECL_VALUE_EXPR (new_vard,
3783 build_fold_addr_expr (lvar));
3784 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3787 else
3789 if (is_reference (var) && is_simd)
3790 handle_simd_reference (clause_loc, new_vard, ilist);
3791 gimplify_assign (new_var, x, ilist);
3792 if (is_simd)
3794 tree ref = build_outer_var_ref (var, ctx);
3796 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3797 ref = build_outer_var_ref (var, ctx);
3798 gimplify_assign (ref, x, dlist);
3802 break;
3804 default:
3805 gcc_unreachable ();
3810 if (lane)
3812 tree uid = create_tmp_var (ptr_type_node, "simduid");
3813 /* Don't want uninit warnings on simduid, it is always uninitialized,
3814 but we use it not for the value, but for the DECL_UID only. */
3815 TREE_NO_WARNING (uid) = 1;
3816 gimple g
3817 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3818 gimple_call_set_lhs (g, lane);
3819 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3820 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3821 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3822 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3823 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3824 gimple_omp_for_set_clauses (ctx->stmt, c);
3825 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3826 build_int_cst (unsigned_type_node, 0),
3827 NULL_TREE);
3828 gimple_seq_add_stmt (ilist, g);
3829 for (int i = 0; i < 2; i++)
3830 if (llist[i])
3832 tree vf = create_tmp_var (unsigned_type_node, NULL);
3833 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3834 gimple_call_set_lhs (g, vf);
3835 gimple_seq *seq = i == 0 ? ilist : dlist;
3836 gimple_seq_add_stmt (seq, g);
3837 tree t = build_int_cst (unsigned_type_node, 0);
3838 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3839 gimple_seq_add_stmt (seq, g);
3840 tree body = create_artificial_label (UNKNOWN_LOCATION);
3841 tree header = create_artificial_label (UNKNOWN_LOCATION);
3842 tree end = create_artificial_label (UNKNOWN_LOCATION);
3843 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3844 gimple_seq_add_stmt (seq, gimple_build_label (body));
3845 gimple_seq_add_seq (seq, llist[i]);
3846 t = build_int_cst (unsigned_type_node, 1);
3847 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3848 gimple_seq_add_stmt (seq, g);
3849 gimple_seq_add_stmt (seq, gimple_build_label (header));
3850 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3851 gimple_seq_add_stmt (seq, g);
3852 gimple_seq_add_stmt (seq, gimple_build_label (end));
3856 /* The copyin sequence is not to be executed by the main thread, since
3857 that would result in self-copies. Perhaps not visible to scalars,
3858 but it certainly is to C++ operator=. */
3859 if (copyin_seq)
3861 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3863 x = build2 (NE_EXPR, boolean_type_node, x,
3864 build_int_cst (TREE_TYPE (x), 0));
3865 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3866 gimplify_and_add (x, ilist);
3869 /* If any copyin variable is passed by reference, we must ensure the
3870 master thread doesn't modify it before it is copied over in all
3871 threads. Similarly for variables in both firstprivate and
3872 lastprivate clauses we need to ensure the lastprivate copying
3873 happens after firstprivate copying in all threads. And similarly
3874 for UDRs if initializer expression refers to omp_orig. */
3875 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3877 /* Don't add any barrier for #pragma omp simd or
3878 #pragma omp distribute. */
3879 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3880 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3881 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3884 /* If max_vf is non-zero, then we can use only a vectorization factor
3885 up to the max_vf we chose. So stick it into the safelen clause. */
3886 if (max_vf)
3888 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3889 OMP_CLAUSE_SAFELEN);
3890 if (c == NULL_TREE
3891 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
3892 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3893 max_vf) == 1))
3895 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3896 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3897 max_vf);
3898 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3899 gimple_omp_for_set_clauses (ctx->stmt, c);
3905 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3906 both parallel and workshare constructs. PREDICATE may be NULL if it's
3907 always true. */
3909 static void
3910 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3911 omp_context *ctx)
3913 tree x, c, label = NULL, orig_clauses = clauses;
3914 bool par_clauses = false;
3915 tree simduid = NULL, lastlane = NULL;
3917 /* Early exit if there are no lastprivate or linear clauses. */
3918 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3919 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3920 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3921 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3922 break;
3923 if (clauses == NULL)
3925 /* If this was a workshare clause, see if it had been combined
3926 with its parallel. In that case, look for the clauses on the
3927 parallel statement itself. */
3928 if (is_parallel_ctx (ctx))
3929 return;
3931 ctx = ctx->outer;
3932 if (ctx == NULL || !is_parallel_ctx (ctx))
3933 return;
3935 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3936 OMP_CLAUSE_LASTPRIVATE);
3937 if (clauses == NULL)
3938 return;
3939 par_clauses = true;
3942 if (predicate)
3944 gimple stmt;
3945 tree label_true, arm1, arm2;
3947 label = create_artificial_label (UNKNOWN_LOCATION);
3948 label_true = create_artificial_label (UNKNOWN_LOCATION);
3949 arm1 = TREE_OPERAND (predicate, 0);
3950 arm2 = TREE_OPERAND (predicate, 1);
3951 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3952 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3953 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3954 label_true, label);
3955 gimple_seq_add_stmt (stmt_list, stmt);
3956 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3959 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3960 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3962 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3963 if (simduid)
3964 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3967 for (c = clauses; c ;)
3969 tree var, new_var;
3970 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3972 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3973 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3974 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3976 var = OMP_CLAUSE_DECL (c);
3977 new_var = lookup_decl (var, ctx);
3979 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3981 tree val = DECL_VALUE_EXPR (new_var);
3982 if (TREE_CODE (val) == ARRAY_REF
3983 && VAR_P (TREE_OPERAND (val, 0))
3984 && lookup_attribute ("omp simd array",
3985 DECL_ATTRIBUTES (TREE_OPERAND (val,
3986 0))))
3988 if (lastlane == NULL)
3990 lastlane = create_tmp_var (unsigned_type_node, NULL);
3991 gimple g
3992 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
3993 2, simduid,
3994 TREE_OPERAND (val, 1));
3995 gimple_call_set_lhs (g, lastlane);
3996 gimple_seq_add_stmt (stmt_list, g);
3998 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
3999 TREE_OPERAND (val, 0), lastlane,
4000 NULL_TREE, NULL_TREE);
4004 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4005 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4007 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4008 gimple_seq_add_seq (stmt_list,
4009 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4010 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4012 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4013 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4015 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4016 gimple_seq_add_seq (stmt_list,
4017 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4018 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4021 x = build_outer_var_ref (var, ctx);
4022 if (is_reference (var))
4023 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4024 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4025 gimplify_and_add (x, stmt_list);
4027 c = OMP_CLAUSE_CHAIN (c);
4028 if (c == NULL && !par_clauses)
4030 /* If this was a workshare clause, see if it had been combined
4031 with its parallel. In that case, continue looking for the
4032 clauses also on the parallel statement itself. */
4033 if (is_parallel_ctx (ctx))
4034 break;
4036 ctx = ctx->outer;
4037 if (ctx == NULL || !is_parallel_ctx (ctx))
4038 break;
4040 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4041 OMP_CLAUSE_LASTPRIVATE);
4042 par_clauses = true;
4046 if (label)
4047 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4051 /* Generate code to implement the REDUCTION clauses. */
4053 static void
4054 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4056 gimple_seq sub_seq = NULL;
4057 gimple stmt;
4058 tree x, c;
4059 int count = 0;
4061 /* SIMD reductions are handled in lower_rec_input_clauses. */
4062 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4063 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4064 return;
4066 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4067 update in that case, otherwise use a lock. */
4068 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4069 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4071 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4073 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4074 count = -1;
4075 break;
4077 count++;
4080 if (count == 0)
4081 return;
4083 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4085 tree var, ref, new_var;
4086 enum tree_code code;
4087 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4089 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4090 continue;
4092 var = OMP_CLAUSE_DECL (c);
4093 new_var = lookup_decl (var, ctx);
4094 if (is_reference (var))
4095 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4096 ref = build_outer_var_ref (var, ctx);
4097 code = OMP_CLAUSE_REDUCTION_CODE (c);
4099 /* reduction(-:var) sums up the partial results, so it acts
4100 identically to reduction(+:var). */
4101 if (code == MINUS_EXPR)
4102 code = PLUS_EXPR;
4104 if (count == 1)
4106 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4108 addr = save_expr (addr);
4109 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4110 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4111 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4112 gimplify_and_add (x, stmt_seqp);
4113 return;
4116 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4118 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4120 if (is_reference (var)
4121 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4122 TREE_TYPE (ref)))
4123 ref = build_fold_addr_expr_loc (clause_loc, ref);
4124 SET_DECL_VALUE_EXPR (placeholder, ref);
4125 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4126 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4127 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4128 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4129 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4131 else
4133 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4134 ref = build_outer_var_ref (var, ctx);
4135 gimplify_assign (ref, x, &sub_seq);
4139 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4141 gimple_seq_add_stmt (stmt_seqp, stmt);
4143 gimple_seq_add_seq (stmt_seqp, sub_seq);
4145 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4147 gimple_seq_add_stmt (stmt_seqp, stmt);
4151 /* Generate code to implement the COPYPRIVATE clauses. */
4153 static void
4154 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4155 omp_context *ctx)
4157 tree c;
4159 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4161 tree var, new_var, ref, x;
4162 bool by_ref;
4163 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4165 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4166 continue;
4168 var = OMP_CLAUSE_DECL (c);
4169 by_ref = use_pointer_for_field (var, NULL);
4171 ref = build_sender_ref (var, ctx);
4172 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4173 if (by_ref)
4175 x = build_fold_addr_expr_loc (clause_loc, new_var);
4176 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4178 gimplify_assign (ref, x, slist);
4180 ref = build_receiver_ref (var, false, ctx);
4181 if (by_ref)
4183 ref = fold_convert_loc (clause_loc,
4184 build_pointer_type (TREE_TYPE (new_var)),
4185 ref);
4186 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4188 if (is_reference (var))
4190 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4191 ref = build_simple_mem_ref_loc (clause_loc, ref);
4192 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4194 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4195 gimplify_and_add (x, rlist);
4200 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4201 and REDUCTION from the sender (aka parent) side. */
4203 static void
4204 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4205 omp_context *ctx)
4207 tree c;
4209 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4211 tree val, ref, x, var;
4212 bool by_ref, do_in = false, do_out = false;
4213 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4215 switch (OMP_CLAUSE_CODE (c))
4217 case OMP_CLAUSE_PRIVATE:
4218 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4219 break;
4220 continue;
4221 case OMP_CLAUSE_FIRSTPRIVATE:
4222 case OMP_CLAUSE_COPYIN:
4223 case OMP_CLAUSE_LASTPRIVATE:
4224 case OMP_CLAUSE_REDUCTION:
4225 case OMP_CLAUSE__LOOPTEMP_:
4226 break;
4227 default:
4228 continue;
4231 val = OMP_CLAUSE_DECL (c);
4232 var = lookup_decl_in_outer_ctx (val, ctx);
4234 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4235 && is_global_var (var))
4236 continue;
4237 if (is_variable_sized (val))
4238 continue;
4239 by_ref = use_pointer_for_field (val, NULL);
4241 switch (OMP_CLAUSE_CODE (c))
4243 case OMP_CLAUSE_PRIVATE:
4244 case OMP_CLAUSE_FIRSTPRIVATE:
4245 case OMP_CLAUSE_COPYIN:
4246 case OMP_CLAUSE__LOOPTEMP_:
4247 do_in = true;
4248 break;
4250 case OMP_CLAUSE_LASTPRIVATE:
4251 if (by_ref || is_reference (val))
4253 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4254 continue;
4255 do_in = true;
4257 else
4259 do_out = true;
4260 if (lang_hooks.decls.omp_private_outer_ref (val))
4261 do_in = true;
4263 break;
4265 case OMP_CLAUSE_REDUCTION:
4266 do_in = true;
4267 do_out = !(by_ref || is_reference (val));
4268 break;
4270 default:
4271 gcc_unreachable ();
4274 if (do_in)
4276 ref = build_sender_ref (val, ctx);
4277 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4278 gimplify_assign (ref, x, ilist);
4279 if (is_task_ctx (ctx))
4280 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4283 if (do_out)
4285 ref = build_sender_ref (val, ctx);
4286 gimplify_assign (var, ref, olist);
4291 /* Generate code to implement SHARED from the sender (aka parent)
4292 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4293 list things that got automatically shared. */
4295 static void
4296 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4298 tree var, ovar, nvar, f, x, record_type;
4300 if (ctx->record_type == NULL)
4301 return;
4303 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4304 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4306 ovar = DECL_ABSTRACT_ORIGIN (f);
4307 nvar = maybe_lookup_decl (ovar, ctx);
4308 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4309 continue;
4311 /* If CTX is a nested parallel directive. Find the immediately
4312 enclosing parallel or workshare construct that contains a
4313 mapping for OVAR. */
4314 var = lookup_decl_in_outer_ctx (ovar, ctx);
4316 if (use_pointer_for_field (ovar, ctx))
4318 x = build_sender_ref (ovar, ctx);
4319 var = build_fold_addr_expr (var);
4320 gimplify_assign (x, var, ilist);
4322 else
4324 x = build_sender_ref (ovar, ctx);
4325 gimplify_assign (x, var, ilist);
4327 if (!TREE_READONLY (var)
4328 /* We don't need to receive a new reference to a result
4329 or parm decl. In fact we may not store to it as we will
4330 invalidate any pending RSO and generate wrong gimple
4331 during inlining. */
4332 && !((TREE_CODE (var) == RESULT_DECL
4333 || TREE_CODE (var) == PARM_DECL)
4334 && DECL_BY_REFERENCE (var)))
4336 x = build_sender_ref (ovar, ctx);
4337 gimplify_assign (var, x, olist);
4344 /* A convenience function to build an empty GIMPLE_COND with just the
4345 condition. */
4347 static gimple
4348 gimple_build_cond_empty (tree cond)
4350 enum tree_code pred_code;
4351 tree lhs, rhs;
4353 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4354 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4358 /* Build the function calls to GOMP_parallel_start etc to actually
4359 generate the parallel operation. REGION is the parallel region
4360 being expanded. BB is the block where to insert the code. WS_ARGS
4361 will be set if this is a call to a combined parallel+workshare
4362 construct, it contains the list of additional arguments needed by
4363 the workshare construct. */
4365 static void
4366 expand_parallel_call (struct omp_region *region, basic_block bb,
4367 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4369 tree t, t1, t2, val, cond, c, clauses, flags;
4370 gimple_stmt_iterator gsi;
4371 gimple stmt;
4372 enum built_in_function start_ix;
4373 int start_ix2;
4374 location_t clause_loc;
4375 vec<tree, va_gc> *args;
4377 clauses = gimple_omp_parallel_clauses (entry_stmt);
4379 /* Determine what flavor of GOMP_parallel we will be
4380 emitting. */
4381 start_ix = BUILT_IN_GOMP_PARALLEL;
4382 if (is_combined_parallel (region))
4384 switch (region->inner->type)
4386 case GIMPLE_OMP_FOR:
4387 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4388 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4389 + (region->inner->sched_kind
4390 == OMP_CLAUSE_SCHEDULE_RUNTIME
4391 ? 3 : region->inner->sched_kind));
4392 start_ix = (enum built_in_function)start_ix2;
4393 break;
4394 case GIMPLE_OMP_SECTIONS:
4395 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4396 break;
4397 default:
4398 gcc_unreachable ();
4402 /* By default, the value of NUM_THREADS is zero (selected at run time)
4403 and there is no conditional. */
4404 cond = NULL_TREE;
4405 val = build_int_cst (unsigned_type_node, 0);
4406 flags = build_int_cst (unsigned_type_node, 0);
4408 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4409 if (c)
4410 cond = OMP_CLAUSE_IF_EXPR (c);
4412 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4413 if (c)
4415 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4416 clause_loc = OMP_CLAUSE_LOCATION (c);
4418 else
4419 clause_loc = gimple_location (entry_stmt);
4421 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4422 if (c)
4423 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4425 /* Ensure 'val' is of the correct type. */
4426 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4428 /* If we found the clause 'if (cond)', build either
4429 (cond != 0) or (cond ? val : 1u). */
4430 if (cond)
4432 cond = gimple_boolify (cond);
4434 if (integer_zerop (val))
4435 val = fold_build2_loc (clause_loc,
4436 EQ_EXPR, unsigned_type_node, cond,
4437 build_int_cst (TREE_TYPE (cond), 0));
4438 else
4440 basic_block cond_bb, then_bb, else_bb;
4441 edge e, e_then, e_else;
4442 tree tmp_then, tmp_else, tmp_join, tmp_var;
4444 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4445 if (gimple_in_ssa_p (cfun))
4447 tmp_then = make_ssa_name (tmp_var, NULL);
4448 tmp_else = make_ssa_name (tmp_var, NULL);
4449 tmp_join = make_ssa_name (tmp_var, NULL);
4451 else
4453 tmp_then = tmp_var;
4454 tmp_else = tmp_var;
4455 tmp_join = tmp_var;
4458 e = split_block (bb, NULL);
4459 cond_bb = e->src;
4460 bb = e->dest;
4461 remove_edge (e);
4463 then_bb = create_empty_bb (cond_bb);
4464 else_bb = create_empty_bb (then_bb);
4465 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4466 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4468 stmt = gimple_build_cond_empty (cond);
4469 gsi = gsi_start_bb (cond_bb);
4470 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4472 gsi = gsi_start_bb (then_bb);
4473 stmt = gimple_build_assign (tmp_then, val);
4474 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4476 gsi = gsi_start_bb (else_bb);
4477 stmt = gimple_build_assign
4478 (tmp_else, build_int_cst (unsigned_type_node, 1));
4479 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4481 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4482 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4483 add_bb_to_loop (then_bb, cond_bb->loop_father);
4484 add_bb_to_loop (else_bb, cond_bb->loop_father);
4485 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4486 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4488 if (gimple_in_ssa_p (cfun))
4490 gimple phi = create_phi_node (tmp_join, bb);
4491 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4492 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4495 val = tmp_join;
4498 gsi = gsi_start_bb (bb);
4499 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4500 false, GSI_CONTINUE_LINKING);
4503 gsi = gsi_last_bb (bb);
4504 t = gimple_omp_parallel_data_arg (entry_stmt);
4505 if (t == NULL)
4506 t1 = null_pointer_node;
4507 else
4508 t1 = build_fold_addr_expr (t);
4509 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4511 vec_alloc (args, 4 + vec_safe_length (ws_args));
4512 args->quick_push (t2);
4513 args->quick_push (t1);
4514 args->quick_push (val);
4515 if (ws_args)
4516 args->splice (*ws_args);
4517 args->quick_push (flags);
4519 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4520 builtin_decl_explicit (start_ix), args);
4522 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4523 false, GSI_CONTINUE_LINKING);
4526 /* Insert a function call whose name is FUNC_NAME with the information from
4527 ENTRY_STMT into the basic_block BB. */
4529 static void
4530 expand_cilk_for_call (basic_block bb, gimple entry_stmt,
4531 vec <tree, va_gc> *ws_args)
4533 tree t, t1, t2;
4534 gimple_stmt_iterator gsi;
4535 vec <tree, va_gc> *args;
4537 gcc_assert (vec_safe_length (ws_args) == 2);
4538 tree func_name = (*ws_args)[0];
4539 tree grain = (*ws_args)[1];
4541 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
4542 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
4543 gcc_assert (count != NULL_TREE);
4544 count = OMP_CLAUSE_OPERAND (count, 0);
4546 gsi = gsi_last_bb (bb);
4547 t = gimple_omp_parallel_data_arg (entry_stmt);
4548 if (t == NULL)
4549 t1 = null_pointer_node;
4550 else
4551 t1 = build_fold_addr_expr (t);
4552 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4554 vec_alloc (args, 4);
4555 args->quick_push (t2);
4556 args->quick_push (t1);
4557 args->quick_push (count);
4558 args->quick_push (grain);
4559 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
4561 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
4562 GSI_CONTINUE_LINKING);
4565 /* Build the function call to GOMP_task to actually
4566 generate the task operation. BB is the block where to insert the code. */
4568 static void
4569 expand_task_call (basic_block bb, gimple entry_stmt)
4571 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4572 gimple_stmt_iterator gsi;
4573 location_t loc = gimple_location (entry_stmt);
4575 clauses = gimple_omp_task_clauses (entry_stmt);
4577 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4578 if (c)
4579 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4580 else
4581 cond = boolean_true_node;
4583 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4584 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4585 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4586 flags = build_int_cst (unsigned_type_node,
4587 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4589 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4590 if (c)
4592 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4593 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4594 build_int_cst (unsigned_type_node, 2),
4595 build_int_cst (unsigned_type_node, 0));
4596 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4598 if (depend)
4599 depend = OMP_CLAUSE_DECL (depend);
4600 else
4601 depend = build_int_cst (ptr_type_node, 0);
4603 gsi = gsi_last_bb (bb);
4604 t = gimple_omp_task_data_arg (entry_stmt);
4605 if (t == NULL)
4606 t2 = null_pointer_node;
4607 else
4608 t2 = build_fold_addr_expr_loc (loc, t);
4609 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4610 t = gimple_omp_task_copy_fn (entry_stmt);
4611 if (t == NULL)
4612 t3 = null_pointer_node;
4613 else
4614 t3 = build_fold_addr_expr_loc (loc, t);
4616 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4617 8, t1, t2, t3,
4618 gimple_omp_task_arg_size (entry_stmt),
4619 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4620 depend);
4622 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4623 false, GSI_CONTINUE_LINKING);
4627 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4628 catch handler and return it. This prevents programs from violating the
4629 structured block semantics with throws. */
4631 static gimple_seq
4632 maybe_catch_exception (gimple_seq body)
4634 gimple g;
4635 tree decl;
4637 if (!flag_exceptions)
4638 return body;
4640 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4641 decl = lang_hooks.eh_protect_cleanup_actions ();
4642 else
4643 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4645 g = gimple_build_eh_must_not_throw (decl);
4646 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4647 GIMPLE_TRY_CATCH);
4649 return gimple_seq_alloc_with_stmt (g);
4652 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4654 static tree
4655 vec2chain (vec<tree, va_gc> *v)
4657 tree chain = NULL_TREE, t;
4658 unsigned ix;
4660 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4662 DECL_CHAIN (t) = chain;
4663 chain = t;
4666 return chain;
4670 /* Remove barriers in REGION->EXIT's block. Note that this is only
4671 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4672 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4673 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4674 removed. */
4676 static void
4677 remove_exit_barrier (struct omp_region *region)
4679 gimple_stmt_iterator gsi;
4680 basic_block exit_bb;
4681 edge_iterator ei;
4682 edge e;
4683 gimple stmt;
4684 int any_addressable_vars = -1;
4686 exit_bb = region->exit;
4688 /* If the parallel region doesn't return, we don't have REGION->EXIT
4689 block at all. */
4690 if (! exit_bb)
4691 return;
4693 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4694 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4695 statements that can appear in between are extremely limited -- no
4696 memory operations at all. Here, we allow nothing at all, so the
4697 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4698 gsi = gsi_last_bb (exit_bb);
4699 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4700 gsi_prev (&gsi);
4701 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4702 return;
4704 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4706 gsi = gsi_last_bb (e->src);
4707 if (gsi_end_p (gsi))
4708 continue;
4709 stmt = gsi_stmt (gsi);
4710 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4711 && !gimple_omp_return_nowait_p (stmt))
4713 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4714 in many cases. If there could be tasks queued, the barrier
4715 might be needed to let the tasks run before some local
4716 variable of the parallel that the task uses as shared
4717 runs out of scope. The task can be spawned either
4718 from within current function (this would be easy to check)
4719 or from some function it calls and gets passed an address
4720 of such a variable. */
4721 if (any_addressable_vars < 0)
4723 gimple parallel_stmt = last_stmt (region->entry);
4724 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4725 tree local_decls, block, decl;
4726 unsigned ix;
4728 any_addressable_vars = 0;
4729 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4730 if (TREE_ADDRESSABLE (decl))
4732 any_addressable_vars = 1;
4733 break;
4735 for (block = gimple_block (stmt);
4736 !any_addressable_vars
4737 && block
4738 && TREE_CODE (block) == BLOCK;
4739 block = BLOCK_SUPERCONTEXT (block))
4741 for (local_decls = BLOCK_VARS (block);
4742 local_decls;
4743 local_decls = DECL_CHAIN (local_decls))
4744 if (TREE_ADDRESSABLE (local_decls))
4746 any_addressable_vars = 1;
4747 break;
4749 if (block == gimple_block (parallel_stmt))
4750 break;
4753 if (!any_addressable_vars)
4754 gimple_omp_return_set_nowait (stmt);
4759 static void
4760 remove_exit_barriers (struct omp_region *region)
4762 if (region->type == GIMPLE_OMP_PARALLEL)
4763 remove_exit_barrier (region);
4765 if (region->inner)
4767 region = region->inner;
4768 remove_exit_barriers (region);
4769 while (region->next)
4771 region = region->next;
4772 remove_exit_barriers (region);
4777 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4778 calls. These can't be declared as const functions, but
4779 within one parallel body they are constant, so they can be
4780 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4781 which are declared const. Similarly for task body, except
4782 that in untied task omp_get_thread_num () can change at any task
4783 scheduling point. */
4785 static void
4786 optimize_omp_library_calls (gimple entry_stmt)
4788 basic_block bb;
4789 gimple_stmt_iterator gsi;
4790 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4791 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4792 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4793 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4794 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4795 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4796 OMP_CLAUSE_UNTIED) != NULL);
4798 FOR_EACH_BB_FN (bb, cfun)
4799 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4801 gimple call = gsi_stmt (gsi);
4802 tree decl;
4804 if (is_gimple_call (call)
4805 && (decl = gimple_call_fndecl (call))
4806 && DECL_EXTERNAL (decl)
4807 && TREE_PUBLIC (decl)
4808 && DECL_INITIAL (decl) == NULL)
4810 tree built_in;
4812 if (DECL_NAME (decl) == thr_num_id)
4814 /* In #pragma omp task untied omp_get_thread_num () can change
4815 during the execution of the task region. */
4816 if (untied_task)
4817 continue;
4818 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4820 else if (DECL_NAME (decl) == num_thr_id)
4821 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4822 else
4823 continue;
4825 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4826 || gimple_call_num_args (call) != 0)
4827 continue;
4829 if (flag_exceptions && !TREE_NOTHROW (decl))
4830 continue;
4832 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4833 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4834 TREE_TYPE (TREE_TYPE (built_in))))
4835 continue;
4837 gimple_call_set_fndecl (call, built_in);
4842 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4843 regimplified. */
4845 static tree
4846 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4848 tree t = *tp;
4850 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4851 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4852 return t;
4854 if (TREE_CODE (t) == ADDR_EXPR)
4855 recompute_tree_invariant_for_addr_expr (t);
4857 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4858 return NULL_TREE;
4861 /* Prepend TO = FROM assignment before *GSI_P. */
4863 static void
4864 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4866 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4867 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4868 true, GSI_SAME_STMT);
4869 gimple stmt = gimple_build_assign (to, from);
4870 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4871 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4872 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4874 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4875 gimple_regimplify_operands (stmt, &gsi);
4879 /* Expand the OpenMP parallel or task directive starting at REGION. */
4881 static void
4882 expand_omp_taskreg (struct omp_region *region)
4884 basic_block entry_bb, exit_bb, new_bb;
4885 struct function *child_cfun;
4886 tree child_fn, block, t;
4887 gimple_stmt_iterator gsi;
4888 gimple entry_stmt, stmt;
4889 edge e;
4890 vec<tree, va_gc> *ws_args;
4892 entry_stmt = last_stmt (region->entry);
4893 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4894 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4896 entry_bb = region->entry;
4897 exit_bb = region->exit;
4899 bool is_cilk_for
4900 = (flag_cilkplus
4901 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
4902 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
4903 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
4905 if (is_cilk_for)
4906 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
4907 and the inner statement contains the name of the built-in function
4908 and grain. */
4909 ws_args = region->inner->ws_args;
4910 else if (is_combined_parallel (region))
4911 ws_args = region->ws_args;
4912 else
4913 ws_args = NULL;
4915 if (child_cfun->cfg)
4917 /* Due to inlining, it may happen that we have already outlined
4918 the region, in which case all we need to do is make the
4919 sub-graph unreachable and emit the parallel call. */
4920 edge entry_succ_e, exit_succ_e;
4922 entry_succ_e = single_succ_edge (entry_bb);
4924 gsi = gsi_last_bb (entry_bb);
4925 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4926 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4927 gsi_remove (&gsi, true);
4929 new_bb = entry_bb;
4930 if (exit_bb)
4932 exit_succ_e = single_succ_edge (exit_bb);
4933 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4935 remove_edge_and_dominated_blocks (entry_succ_e);
4937 else
4939 unsigned srcidx, dstidx, num;
4941 /* If the parallel region needs data sent from the parent
4942 function, then the very first statement (except possible
4943 tree profile counter updates) of the parallel body
4944 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4945 &.OMP_DATA_O is passed as an argument to the child function,
4946 we need to replace it with the argument as seen by the child
4947 function.
4949 In most cases, this will end up being the identity assignment
4950 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4951 a function call that has been inlined, the original PARM_DECL
4952 .OMP_DATA_I may have been converted into a different local
4953 variable. In which case, we need to keep the assignment. */
4954 if (gimple_omp_taskreg_data_arg (entry_stmt))
4956 basic_block entry_succ_bb = single_succ (entry_bb);
4957 tree arg, narg;
4958 gimple parcopy_stmt = NULL;
4960 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4962 gimple stmt;
4964 gcc_assert (!gsi_end_p (gsi));
4965 stmt = gsi_stmt (gsi);
4966 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4967 continue;
4969 if (gimple_num_ops (stmt) == 2)
4971 tree arg = gimple_assign_rhs1 (stmt);
4973 /* We're ignore the subcode because we're
4974 effectively doing a STRIP_NOPS. */
4976 if (TREE_CODE (arg) == ADDR_EXPR
4977 && TREE_OPERAND (arg, 0)
4978 == gimple_omp_taskreg_data_arg (entry_stmt))
4980 parcopy_stmt = stmt;
4981 break;
4986 gcc_assert (parcopy_stmt != NULL);
4987 arg = DECL_ARGUMENTS (child_fn);
4989 if (!gimple_in_ssa_p (cfun))
4991 if (gimple_assign_lhs (parcopy_stmt) == arg)
4992 gsi_remove (&gsi, true);
4993 else
4995 /* ?? Is setting the subcode really necessary ?? */
4996 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
4997 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5000 else
5002 /* If we are in ssa form, we must load the value from the default
5003 definition of the argument. That should not be defined now,
5004 since the argument is not used uninitialized. */
5005 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5006 narg = make_ssa_name (arg, gimple_build_nop ());
5007 set_ssa_default_def (cfun, arg, narg);
5008 /* ?? Is setting the subcode really necessary ?? */
5009 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5010 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5011 update_stmt (parcopy_stmt);
5015 /* Declare local variables needed in CHILD_CFUN. */
5016 block = DECL_INITIAL (child_fn);
5017 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5018 /* The gimplifier could record temporaries in parallel/task block
5019 rather than in containing function's local_decls chain,
5020 which would mean cgraph missed finalizing them. Do it now. */
5021 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5022 if (TREE_CODE (t) == VAR_DECL
5023 && TREE_STATIC (t)
5024 && !DECL_EXTERNAL (t))
5025 varpool_node::finalize_decl (t);
5026 DECL_SAVED_TREE (child_fn) = NULL;
5027 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5028 gimple_set_body (child_fn, NULL);
5029 TREE_USED (block) = 1;
5031 /* Reset DECL_CONTEXT on function arguments. */
5032 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5033 DECL_CONTEXT (t) = child_fn;
5035 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5036 so that it can be moved to the child function. */
5037 gsi = gsi_last_bb (entry_bb);
5038 stmt = gsi_stmt (gsi);
5039 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5040 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5041 gsi_remove (&gsi, true);
5042 e = split_block (entry_bb, stmt);
5043 entry_bb = e->dest;
5044 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5046 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5047 if (exit_bb)
5049 gsi = gsi_last_bb (exit_bb);
5050 gcc_assert (!gsi_end_p (gsi)
5051 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5052 stmt = gimple_build_return (NULL);
5053 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5054 gsi_remove (&gsi, true);
5057 /* Move the parallel region into CHILD_CFUN. */
5059 if (gimple_in_ssa_p (cfun))
5061 init_tree_ssa (child_cfun);
5062 init_ssa_operands (child_cfun);
5063 child_cfun->gimple_df->in_ssa_p = true;
5064 block = NULL_TREE;
5066 else
5067 block = gimple_block (entry_stmt);
5069 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5070 if (exit_bb)
5071 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5072 /* When the OMP expansion process cannot guarantee an up-to-date
5073 loop tree arrange for the child function to fixup loops. */
5074 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5075 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5077 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5078 num = vec_safe_length (child_cfun->local_decls);
5079 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5081 t = (*child_cfun->local_decls)[srcidx];
5082 if (DECL_CONTEXT (t) == cfun->decl)
5083 continue;
5084 if (srcidx != dstidx)
5085 (*child_cfun->local_decls)[dstidx] = t;
5086 dstidx++;
5088 if (dstidx != num)
5089 vec_safe_truncate (child_cfun->local_decls, dstidx);
5091 /* Inform the callgraph about the new function. */
5092 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5093 cgraph_node::add_new_function (child_fn, true);
5095 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5096 fixed in a following pass. */
5097 push_cfun (child_cfun);
5098 if (optimize)
5099 optimize_omp_library_calls (entry_stmt);
5100 cgraph_edge::rebuild_edges ();
5102 /* Some EH regions might become dead, see PR34608. If
5103 pass_cleanup_cfg isn't the first pass to happen with the
5104 new child, these dead EH edges might cause problems.
5105 Clean them up now. */
5106 if (flag_exceptions)
5108 basic_block bb;
5109 bool changed = false;
5111 FOR_EACH_BB_FN (bb, cfun)
5112 changed |= gimple_purge_dead_eh_edges (bb);
5113 if (changed)
5114 cleanup_tree_cfg ();
5116 if (gimple_in_ssa_p (cfun))
5117 update_ssa (TODO_update_ssa);
5118 pop_cfun ();
5121 /* Emit a library call to launch the children threads. */
5122 if (is_cilk_for)
5123 expand_cilk_for_call (new_bb, entry_stmt, ws_args);
5124 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5125 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
5126 else
5127 expand_task_call (new_bb, entry_stmt);
5128 if (gimple_in_ssa_p (cfun))
5129 update_ssa (TODO_update_ssa_only_virtuals);
5133 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5134 of the combined collapse > 1 loop constructs, generate code like:
5135 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5136 if (cond3 is <)
5137 adj = STEP3 - 1;
5138 else
5139 adj = STEP3 + 1;
5140 count3 = (adj + N32 - N31) / STEP3;
5141 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5142 if (cond2 is <)
5143 adj = STEP2 - 1;
5144 else
5145 adj = STEP2 + 1;
5146 count2 = (adj + N22 - N21) / STEP2;
5147 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5148 if (cond1 is <)
5149 adj = STEP1 - 1;
5150 else
5151 adj = STEP1 + 1;
5152 count1 = (adj + N12 - N11) / STEP1;
5153 count = count1 * count2 * count3;
5154 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5155 count = 0;
5156 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5157 of the combined loop constructs, just initialize COUNTS array
5158 from the _looptemp_ clauses. */
5160 /* NOTE: It *could* be better to moosh all of the BBs together,
5161 creating one larger BB with all the computation and the unexpected
5162 jump at the end. I.e.
5164 bool zero3, zero2, zero1, zero;
5166 zero3 = N32 c3 N31;
5167 count3 = (N32 - N31) /[cl] STEP3;
5168 zero2 = N22 c2 N21;
5169 count2 = (N22 - N21) /[cl] STEP2;
5170 zero1 = N12 c1 N11;
5171 count1 = (N12 - N11) /[cl] STEP1;
5172 zero = zero3 || zero2 || zero1;
5173 count = count1 * count2 * count3;
5174 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5176 After all, we expect the zero=false, and thus we expect to have to
5177 evaluate all of the comparison expressions, so short-circuiting
5178 oughtn't be a win. Since the condition isn't protecting a
5179 denominator, we're not concerned about divide-by-zero, so we can
5180 fully evaluate count even if a numerator turned out to be wrong.
5182 It seems like putting this all together would create much better
5183 scheduling opportunities, and less pressure on the chip's branch
5184 predictor. */
5186 static void
5187 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5188 basic_block &entry_bb, tree *counts,
5189 basic_block &zero_iter_bb, int &first_zero_iter,
5190 basic_block &l2_dom_bb)
5192 tree t, type = TREE_TYPE (fd->loop.v);
5193 gimple stmt;
5194 edge e, ne;
5195 int i;
5197 /* Collapsed loops need work for expansion into SSA form. */
5198 gcc_assert (!gimple_in_ssa_p (cfun));
5200 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5201 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5203 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5204 isn't supposed to be handled, as the inner loop doesn't
5205 use it. */
5206 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5207 OMP_CLAUSE__LOOPTEMP_);
5208 gcc_assert (innerc);
5209 for (i = 0; i < fd->collapse; i++)
5211 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5212 OMP_CLAUSE__LOOPTEMP_);
5213 gcc_assert (innerc);
5214 if (i)
5215 counts[i] = OMP_CLAUSE_DECL (innerc);
5216 else
5217 counts[0] = NULL_TREE;
5219 return;
5222 for (i = 0; i < fd->collapse; i++)
5224 tree itype = TREE_TYPE (fd->loops[i].v);
5226 if (SSA_VAR_P (fd->loop.n2)
5227 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5228 fold_convert (itype, fd->loops[i].n1),
5229 fold_convert (itype, fd->loops[i].n2)))
5230 == NULL_TREE || !integer_onep (t)))
5232 tree n1, n2;
5233 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5234 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5235 true, GSI_SAME_STMT);
5236 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5237 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5238 true, GSI_SAME_STMT);
5239 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5240 NULL_TREE, NULL_TREE);
5241 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5242 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5243 expand_omp_regimplify_p, NULL, NULL)
5244 || walk_tree (gimple_cond_rhs_ptr (stmt),
5245 expand_omp_regimplify_p, NULL, NULL))
5247 *gsi = gsi_for_stmt (stmt);
5248 gimple_regimplify_operands (stmt, gsi);
5250 e = split_block (entry_bb, stmt);
5251 if (zero_iter_bb == NULL)
5253 first_zero_iter = i;
5254 zero_iter_bb = create_empty_bb (entry_bb);
5255 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5256 *gsi = gsi_after_labels (zero_iter_bb);
5257 stmt = gimple_build_assign (fd->loop.n2,
5258 build_zero_cst (type));
5259 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5260 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5261 entry_bb);
5263 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5264 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5265 e->flags = EDGE_TRUE_VALUE;
5266 e->probability = REG_BR_PROB_BASE - ne->probability;
5267 if (l2_dom_bb == NULL)
5268 l2_dom_bb = entry_bb;
5269 entry_bb = e->dest;
5270 *gsi = gsi_last_bb (entry_bb);
5273 if (POINTER_TYPE_P (itype))
5274 itype = signed_type_for (itype);
5275 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5276 ? -1 : 1));
5277 t = fold_build2 (PLUS_EXPR, itype,
5278 fold_convert (itype, fd->loops[i].step), t);
5279 t = fold_build2 (PLUS_EXPR, itype, t,
5280 fold_convert (itype, fd->loops[i].n2));
5281 t = fold_build2 (MINUS_EXPR, itype, t,
5282 fold_convert (itype, fd->loops[i].n1));
5283 /* ?? We could probably use CEIL_DIV_EXPR instead of
5284 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5285 generate the same code in the end because generically we
5286 don't know that the values involved must be negative for
5287 GT?? */
5288 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5289 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5290 fold_build1 (NEGATE_EXPR, itype, t),
5291 fold_build1 (NEGATE_EXPR, itype,
5292 fold_convert (itype,
5293 fd->loops[i].step)));
5294 else
5295 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5296 fold_convert (itype, fd->loops[i].step));
5297 t = fold_convert (type, t);
5298 if (TREE_CODE (t) == INTEGER_CST)
5299 counts[i] = t;
5300 else
5302 counts[i] = create_tmp_reg (type, ".count");
5303 expand_omp_build_assign (gsi, counts[i], t);
5305 if (SSA_VAR_P (fd->loop.n2))
5307 if (i == 0)
5308 t = counts[0];
5309 else
5310 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5311 expand_omp_build_assign (gsi, fd->loop.n2, t);
5317 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5318 T = V;
5319 V3 = N31 + (T % count3) * STEP3;
5320 T = T / count3;
5321 V2 = N21 + (T % count2) * STEP2;
5322 T = T / count2;
5323 V1 = N11 + T * STEP1;
5324 if this loop doesn't have an inner loop construct combined with it.
5325 If it does have an inner loop construct combined with it and the
5326 iteration count isn't known constant, store values from counts array
5327 into its _looptemp_ temporaries instead. */
5329 static void
5330 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5331 tree *counts, gimple inner_stmt, tree startvar)
5333 int i;
5334 if (gimple_omp_for_combined_p (fd->for_stmt))
5336 /* If fd->loop.n2 is constant, then no propagation of the counts
5337 is needed, they are constant. */
5338 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5339 return;
5341 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5342 ? gimple_omp_parallel_clauses (inner_stmt)
5343 : gimple_omp_for_clauses (inner_stmt);
5344 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5345 isn't supposed to be handled, as the inner loop doesn't
5346 use it. */
5347 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5348 gcc_assert (innerc);
5349 for (i = 0; i < fd->collapse; i++)
5351 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5352 OMP_CLAUSE__LOOPTEMP_);
5353 gcc_assert (innerc);
5354 if (i)
5356 tree tem = OMP_CLAUSE_DECL (innerc);
5357 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5358 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5359 false, GSI_CONTINUE_LINKING);
5360 gimple stmt = gimple_build_assign (tem, t);
5361 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5364 return;
5367 tree type = TREE_TYPE (fd->loop.v);
5368 tree tem = create_tmp_reg (type, ".tem");
5369 gimple stmt = gimple_build_assign (tem, startvar);
5370 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5372 for (i = fd->collapse - 1; i >= 0; i--)
5374 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5375 itype = vtype;
5376 if (POINTER_TYPE_P (vtype))
5377 itype = signed_type_for (vtype);
5378 if (i != 0)
5379 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5380 else
5381 t = tem;
5382 t = fold_convert (itype, t);
5383 t = fold_build2 (MULT_EXPR, itype, t,
5384 fold_convert (itype, fd->loops[i].step));
5385 if (POINTER_TYPE_P (vtype))
5386 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5387 else
5388 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5389 t = force_gimple_operand_gsi (gsi, t,
5390 DECL_P (fd->loops[i].v)
5391 && TREE_ADDRESSABLE (fd->loops[i].v),
5392 NULL_TREE, false,
5393 GSI_CONTINUE_LINKING);
5394 stmt = gimple_build_assign (fd->loops[i].v, t);
5395 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5396 if (i != 0)
5398 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5399 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5400 false, GSI_CONTINUE_LINKING);
5401 stmt = gimple_build_assign (tem, t);
5402 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5408 /* Helper function for expand_omp_for_*. Generate code like:
5409 L10:
5410 V3 += STEP3;
5411 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5412 L11:
5413 V3 = N31;
5414 V2 += STEP2;
5415 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5416 L12:
5417 V2 = N21;
5418 V1 += STEP1;
5419 goto BODY_BB; */
5421 static basic_block
5422 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5423 basic_block body_bb)
5425 basic_block last_bb, bb, collapse_bb = NULL;
5426 int i;
5427 gimple_stmt_iterator gsi;
5428 edge e;
5429 tree t;
5430 gimple stmt;
5432 last_bb = cont_bb;
5433 for (i = fd->collapse - 1; i >= 0; i--)
5435 tree vtype = TREE_TYPE (fd->loops[i].v);
5437 bb = create_empty_bb (last_bb);
5438 add_bb_to_loop (bb, last_bb->loop_father);
5439 gsi = gsi_start_bb (bb);
5441 if (i < fd->collapse - 1)
5443 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5444 e->probability = REG_BR_PROB_BASE / 8;
5446 t = fd->loops[i + 1].n1;
5447 t = force_gimple_operand_gsi (&gsi, t,
5448 DECL_P (fd->loops[i + 1].v)
5449 && TREE_ADDRESSABLE (fd->loops[i
5450 + 1].v),
5451 NULL_TREE, false,
5452 GSI_CONTINUE_LINKING);
5453 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5454 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5456 else
5457 collapse_bb = bb;
5459 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5461 if (POINTER_TYPE_P (vtype))
5462 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5463 else
5464 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5465 t = force_gimple_operand_gsi (&gsi, t,
5466 DECL_P (fd->loops[i].v)
5467 && TREE_ADDRESSABLE (fd->loops[i].v),
5468 NULL_TREE, false, GSI_CONTINUE_LINKING);
5469 stmt = gimple_build_assign (fd->loops[i].v, t);
5470 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5472 if (i > 0)
5474 t = fd->loops[i].n2;
5475 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5476 false, GSI_CONTINUE_LINKING);
5477 tree v = fd->loops[i].v;
5478 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5479 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5480 false, GSI_CONTINUE_LINKING);
5481 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5482 stmt = gimple_build_cond_empty (t);
5483 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5484 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5485 e->probability = REG_BR_PROB_BASE * 7 / 8;
5487 else
5488 make_edge (bb, body_bb, EDGE_FALLTHRU);
5489 last_bb = bb;
5492 return collapse_bb;
5496 /* A subroutine of expand_omp_for. Generate code for a parallel
5497 loop with any schedule. Given parameters:
5499 for (V = N1; V cond N2; V += STEP) BODY;
5501 where COND is "<" or ">", we generate pseudocode
5503 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5504 if (more) goto L0; else goto L3;
5506 V = istart0;
5507 iend = iend0;
5509 BODY;
5510 V += STEP;
5511 if (V cond iend) goto L1; else goto L2;
5513 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5516 If this is a combined omp parallel loop, instead of the call to
5517 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5518 If this is gimple_omp_for_combined_p loop, then instead of assigning
5519 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5520 inner GIMPLE_OMP_FOR and V += STEP; and
5521 if (V cond iend) goto L1; else goto L2; are removed.
5523 For collapsed loops, given parameters:
5524 collapse(3)
5525 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5526 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5527 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5528 BODY;
5530 we generate pseudocode
5532 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5533 if (cond3 is <)
5534 adj = STEP3 - 1;
5535 else
5536 adj = STEP3 + 1;
5537 count3 = (adj + N32 - N31) / STEP3;
5538 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5539 if (cond2 is <)
5540 adj = STEP2 - 1;
5541 else
5542 adj = STEP2 + 1;
5543 count2 = (adj + N22 - N21) / STEP2;
5544 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5545 if (cond1 is <)
5546 adj = STEP1 - 1;
5547 else
5548 adj = STEP1 + 1;
5549 count1 = (adj + N12 - N11) / STEP1;
5550 count = count1 * count2 * count3;
5551 goto Z1;
5553 count = 0;
5555 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5556 if (more) goto L0; else goto L3;
5558 V = istart0;
5559 T = V;
5560 V3 = N31 + (T % count3) * STEP3;
5561 T = T / count3;
5562 V2 = N21 + (T % count2) * STEP2;
5563 T = T / count2;
5564 V1 = N11 + T * STEP1;
5565 iend = iend0;
5567 BODY;
5568 V += 1;
5569 if (V < iend) goto L10; else goto L2;
5570 L10:
5571 V3 += STEP3;
5572 if (V3 cond3 N32) goto L1; else goto L11;
5573 L11:
5574 V3 = N31;
5575 V2 += STEP2;
5576 if (V2 cond2 N22) goto L1; else goto L12;
5577 L12:
5578 V2 = N21;
5579 V1 += STEP1;
5580 goto L1;
5582 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5587 static void
5588 expand_omp_for_generic (struct omp_region *region,
5589 struct omp_for_data *fd,
5590 enum built_in_function start_fn,
5591 enum built_in_function next_fn,
5592 gimple inner_stmt)
5594 tree type, istart0, iend0, iend;
5595 tree t, vmain, vback, bias = NULL_TREE;
5596 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5597 basic_block l2_bb = NULL, l3_bb = NULL;
5598 gimple_stmt_iterator gsi;
5599 gimple stmt;
5600 bool in_combined_parallel = is_combined_parallel (region);
5601 bool broken_loop = region->cont == NULL;
5602 edge e, ne;
5603 tree *counts = NULL;
5604 int i;
5606 gcc_assert (!broken_loop || !in_combined_parallel);
5607 gcc_assert (fd->iter_type == long_integer_type_node
5608 || !in_combined_parallel);
5610 type = TREE_TYPE (fd->loop.v);
5611 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5612 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5613 TREE_ADDRESSABLE (istart0) = 1;
5614 TREE_ADDRESSABLE (iend0) = 1;
5616 /* See if we need to bias by LLONG_MIN. */
5617 if (fd->iter_type == long_long_unsigned_type_node
5618 && TREE_CODE (type) == INTEGER_TYPE
5619 && !TYPE_UNSIGNED (type))
5621 tree n1, n2;
5623 if (fd->loop.cond_code == LT_EXPR)
5625 n1 = fd->loop.n1;
5626 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5628 else
5630 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5631 n2 = fd->loop.n1;
5633 if (TREE_CODE (n1) != INTEGER_CST
5634 || TREE_CODE (n2) != INTEGER_CST
5635 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5636 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5639 entry_bb = region->entry;
5640 cont_bb = region->cont;
5641 collapse_bb = NULL;
5642 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5643 gcc_assert (broken_loop
5644 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5645 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5646 l1_bb = single_succ (l0_bb);
5647 if (!broken_loop)
5649 l2_bb = create_empty_bb (cont_bb);
5650 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5651 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5653 else
5654 l2_bb = NULL;
5655 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5656 exit_bb = region->exit;
5658 gsi = gsi_last_bb (entry_bb);
5660 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5661 if (fd->collapse > 1)
5663 int first_zero_iter = -1;
5664 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5666 counts = XALLOCAVEC (tree, fd->collapse);
5667 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5668 zero_iter_bb, first_zero_iter,
5669 l2_dom_bb);
5671 if (zero_iter_bb)
5673 /* Some counts[i] vars might be uninitialized if
5674 some loop has zero iterations. But the body shouldn't
5675 be executed in that case, so just avoid uninit warnings. */
5676 for (i = first_zero_iter; i < fd->collapse; i++)
5677 if (SSA_VAR_P (counts[i]))
5678 TREE_NO_WARNING (counts[i]) = 1;
5679 gsi_prev (&gsi);
5680 e = split_block (entry_bb, gsi_stmt (gsi));
5681 entry_bb = e->dest;
5682 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5683 gsi = gsi_last_bb (entry_bb);
5684 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5685 get_immediate_dominator (CDI_DOMINATORS,
5686 zero_iter_bb));
5689 if (in_combined_parallel)
5691 /* In a combined parallel loop, emit a call to
5692 GOMP_loop_foo_next. */
5693 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5694 build_fold_addr_expr (istart0),
5695 build_fold_addr_expr (iend0));
5697 else
5699 tree t0, t1, t2, t3, t4;
5700 /* If this is not a combined parallel loop, emit a call to
5701 GOMP_loop_foo_start in ENTRY_BB. */
5702 t4 = build_fold_addr_expr (iend0);
5703 t3 = build_fold_addr_expr (istart0);
5704 t2 = fold_convert (fd->iter_type, fd->loop.step);
5705 t1 = fd->loop.n2;
5706 t0 = fd->loop.n1;
5707 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5709 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5710 OMP_CLAUSE__LOOPTEMP_);
5711 gcc_assert (innerc);
5712 t0 = OMP_CLAUSE_DECL (innerc);
5713 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5714 OMP_CLAUSE__LOOPTEMP_);
5715 gcc_assert (innerc);
5716 t1 = OMP_CLAUSE_DECL (innerc);
5718 if (POINTER_TYPE_P (TREE_TYPE (t0))
5719 && TYPE_PRECISION (TREE_TYPE (t0))
5720 != TYPE_PRECISION (fd->iter_type))
5722 /* Avoid casting pointers to integer of a different size. */
5723 tree itype = signed_type_for (type);
5724 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5725 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5727 else
5729 t1 = fold_convert (fd->iter_type, t1);
5730 t0 = fold_convert (fd->iter_type, t0);
5732 if (bias)
5734 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5735 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5737 if (fd->iter_type == long_integer_type_node)
5739 if (fd->chunk_size)
5741 t = fold_convert (fd->iter_type, fd->chunk_size);
5742 t = build_call_expr (builtin_decl_explicit (start_fn),
5743 6, t0, t1, t2, t, t3, t4);
5745 else
5746 t = build_call_expr (builtin_decl_explicit (start_fn),
5747 5, t0, t1, t2, t3, t4);
5749 else
5751 tree t5;
5752 tree c_bool_type;
5753 tree bfn_decl;
5755 /* The GOMP_loop_ull_*start functions have additional boolean
5756 argument, true for < loops and false for > loops.
5757 In Fortran, the C bool type can be different from
5758 boolean_type_node. */
5759 bfn_decl = builtin_decl_explicit (start_fn);
5760 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5761 t5 = build_int_cst (c_bool_type,
5762 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5763 if (fd->chunk_size)
5765 tree bfn_decl = builtin_decl_explicit (start_fn);
5766 t = fold_convert (fd->iter_type, fd->chunk_size);
5767 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5769 else
5770 t = build_call_expr (builtin_decl_explicit (start_fn),
5771 6, t5, t0, t1, t2, t3, t4);
5774 if (TREE_TYPE (t) != boolean_type_node)
5775 t = fold_build2 (NE_EXPR, boolean_type_node,
5776 t, build_int_cst (TREE_TYPE (t), 0));
5777 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5778 true, GSI_SAME_STMT);
5779 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5781 /* Remove the GIMPLE_OMP_FOR statement. */
5782 gsi_remove (&gsi, true);
5784 /* Iteration setup for sequential loop goes in L0_BB. */
5785 tree startvar = fd->loop.v;
5786 tree endvar = NULL_TREE;
5788 if (gimple_omp_for_combined_p (fd->for_stmt))
5790 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5791 && gimple_omp_for_kind (inner_stmt)
5792 == GF_OMP_FOR_KIND_SIMD);
5793 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5794 OMP_CLAUSE__LOOPTEMP_);
5795 gcc_assert (innerc);
5796 startvar = OMP_CLAUSE_DECL (innerc);
5797 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5798 OMP_CLAUSE__LOOPTEMP_);
5799 gcc_assert (innerc);
5800 endvar = OMP_CLAUSE_DECL (innerc);
5803 gsi = gsi_start_bb (l0_bb);
5804 t = istart0;
5805 if (bias)
5806 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5807 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5808 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5809 t = fold_convert (TREE_TYPE (startvar), t);
5810 t = force_gimple_operand_gsi (&gsi, t,
5811 DECL_P (startvar)
5812 && TREE_ADDRESSABLE (startvar),
5813 NULL_TREE, false, GSI_CONTINUE_LINKING);
5814 stmt = gimple_build_assign (startvar, t);
5815 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5817 t = iend0;
5818 if (bias)
5819 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5820 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5821 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5822 t = fold_convert (TREE_TYPE (startvar), t);
5823 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5824 false, GSI_CONTINUE_LINKING);
5825 if (endvar)
5827 stmt = gimple_build_assign (endvar, iend);
5828 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5829 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
5830 stmt = gimple_build_assign (fd->loop.v, iend);
5831 else
5832 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend,
5833 NULL_TREE);
5834 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5836 if (fd->collapse > 1)
5837 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5839 if (!broken_loop)
5841 /* Code to control the increment and predicate for the sequential
5842 loop goes in the CONT_BB. */
5843 gsi = gsi_last_bb (cont_bb);
5844 stmt = gsi_stmt (gsi);
5845 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5846 vmain = gimple_omp_continue_control_use (stmt);
5847 vback = gimple_omp_continue_control_def (stmt);
5849 if (!gimple_omp_for_combined_p (fd->for_stmt))
5851 if (POINTER_TYPE_P (type))
5852 t = fold_build_pointer_plus (vmain, fd->loop.step);
5853 else
5854 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5855 t = force_gimple_operand_gsi (&gsi, t,
5856 DECL_P (vback)
5857 && TREE_ADDRESSABLE (vback),
5858 NULL_TREE, true, GSI_SAME_STMT);
5859 stmt = gimple_build_assign (vback, t);
5860 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5862 t = build2 (fd->loop.cond_code, boolean_type_node,
5863 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5864 iend);
5865 stmt = gimple_build_cond_empty (t);
5866 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5869 /* Remove GIMPLE_OMP_CONTINUE. */
5870 gsi_remove (&gsi, true);
5872 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5873 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5875 /* Emit code to get the next parallel iteration in L2_BB. */
5876 gsi = gsi_start_bb (l2_bb);
5878 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5879 build_fold_addr_expr (istart0),
5880 build_fold_addr_expr (iend0));
5881 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5882 false, GSI_CONTINUE_LINKING);
5883 if (TREE_TYPE (t) != boolean_type_node)
5884 t = fold_build2 (NE_EXPR, boolean_type_node,
5885 t, build_int_cst (TREE_TYPE (t), 0));
5886 stmt = gimple_build_cond_empty (t);
5887 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5890 /* Add the loop cleanup function. */
5891 gsi = gsi_last_bb (exit_bb);
5892 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5893 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5894 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5895 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5896 else
5897 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5898 stmt = gimple_build_call (t, 0);
5899 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5900 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5901 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5902 gsi_remove (&gsi, true);
5904 /* Connect the new blocks. */
5905 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5906 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5908 if (!broken_loop)
5910 gimple_seq phis;
5912 e = find_edge (cont_bb, l3_bb);
5913 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5915 phis = phi_nodes (l3_bb);
5916 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5918 gimple phi = gsi_stmt (gsi);
5919 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5920 PHI_ARG_DEF_FROM_EDGE (phi, e));
5922 remove_edge (e);
5924 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5925 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5926 e = find_edge (cont_bb, l1_bb);
5927 if (gimple_omp_for_combined_p (fd->for_stmt))
5929 remove_edge (e);
5930 e = NULL;
5932 else if (fd->collapse > 1)
5934 remove_edge (e);
5935 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5937 else
5938 e->flags = EDGE_TRUE_VALUE;
5939 if (e)
5941 e->probability = REG_BR_PROB_BASE * 7 / 8;
5942 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5944 else
5946 e = find_edge (cont_bb, l2_bb);
5947 e->flags = EDGE_FALLTHRU;
5949 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5951 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5952 recompute_dominator (CDI_DOMINATORS, l2_bb));
5953 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5954 recompute_dominator (CDI_DOMINATORS, l3_bb));
5955 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5956 recompute_dominator (CDI_DOMINATORS, l0_bb));
5957 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5958 recompute_dominator (CDI_DOMINATORS, l1_bb));
5960 struct loop *outer_loop = alloc_loop ();
5961 outer_loop->header = l0_bb;
5962 outer_loop->latch = l2_bb;
5963 add_loop (outer_loop, l0_bb->loop_father);
5965 if (!gimple_omp_for_combined_p (fd->for_stmt))
5967 struct loop *loop = alloc_loop ();
5968 loop->header = l1_bb;
5969 /* The loop may have multiple latches. */
5970 add_loop (loop, outer_loop);
5976 /* A subroutine of expand_omp_for. Generate code for a parallel
5977 loop with static schedule and no specified chunk size. Given
5978 parameters:
5980 for (V = N1; V cond N2; V += STEP) BODY;
5982 where COND is "<" or ">", we generate pseudocode
5984 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5985 if (cond is <)
5986 adj = STEP - 1;
5987 else
5988 adj = STEP + 1;
5989 if ((__typeof (V)) -1 > 0 && cond is >)
5990 n = -(adj + N2 - N1) / -STEP;
5991 else
5992 n = (adj + N2 - N1) / STEP;
5993 q = n / nthreads;
5994 tt = n % nthreads;
5995 if (threadid < tt) goto L3; else goto L4;
5997 tt = 0;
5998 q = q + 1;
6000 s0 = q * threadid + tt;
6001 e0 = s0 + q;
6002 V = s0 * STEP + N1;
6003 if (s0 >= e0) goto L2; else goto L0;
6005 e = e0 * STEP + N1;
6007 BODY;
6008 V += STEP;
6009 if (V cond e) goto L1;
6013 static void
6014 expand_omp_for_static_nochunk (struct omp_region *region,
6015 struct omp_for_data *fd,
6016 gimple inner_stmt)
6018 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6019 tree type, itype, vmain, vback;
6020 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6021 basic_block body_bb, cont_bb, collapse_bb = NULL;
6022 basic_block fin_bb;
6023 gimple_stmt_iterator gsi;
6024 gimple stmt;
6025 edge ep;
6026 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6027 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6028 bool broken_loop = region->cont == NULL;
6029 tree *counts = NULL;
6030 tree n1, n2, step;
6032 itype = type = TREE_TYPE (fd->loop.v);
6033 if (POINTER_TYPE_P (type))
6034 itype = signed_type_for (type);
6036 entry_bb = region->entry;
6037 cont_bb = region->cont;
6038 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6039 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6040 gcc_assert (broken_loop
6041 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6042 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6043 body_bb = single_succ (seq_start_bb);
6044 if (!broken_loop)
6046 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6047 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6049 exit_bb = region->exit;
6051 /* Iteration space partitioning goes in ENTRY_BB. */
6052 gsi = gsi_last_bb (entry_bb);
6053 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6055 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6057 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6058 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6061 if (fd->collapse > 1)
6063 int first_zero_iter = -1;
6064 basic_block l2_dom_bb = NULL;
6066 counts = XALLOCAVEC (tree, fd->collapse);
6067 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6068 fin_bb, first_zero_iter,
6069 l2_dom_bb);
6070 t = NULL_TREE;
6072 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6073 t = integer_one_node;
6074 else
6075 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6076 fold_convert (type, fd->loop.n1),
6077 fold_convert (type, fd->loop.n2));
6078 if (fd->collapse == 1
6079 && TYPE_UNSIGNED (type)
6080 && (t == NULL_TREE || !integer_onep (t)))
6082 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6083 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6084 true, GSI_SAME_STMT);
6085 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6086 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6087 true, GSI_SAME_STMT);
6088 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6089 NULL_TREE, NULL_TREE);
6090 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6091 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6092 expand_omp_regimplify_p, NULL, NULL)
6093 || walk_tree (gimple_cond_rhs_ptr (stmt),
6094 expand_omp_regimplify_p, NULL, NULL))
6096 gsi = gsi_for_stmt (stmt);
6097 gimple_regimplify_operands (stmt, &gsi);
6099 ep = split_block (entry_bb, stmt);
6100 ep->flags = EDGE_TRUE_VALUE;
6101 entry_bb = ep->dest;
6102 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6103 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6104 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6105 if (gimple_in_ssa_p (cfun))
6107 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6108 for (gsi = gsi_start_phis (fin_bb);
6109 !gsi_end_p (gsi); gsi_next (&gsi))
6111 gimple phi = gsi_stmt (gsi);
6112 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6113 ep, UNKNOWN_LOCATION);
6116 gsi = gsi_last_bb (entry_bb);
6119 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6120 t = fold_convert (itype, t);
6121 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6122 true, GSI_SAME_STMT);
6124 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6125 t = fold_convert (itype, t);
6126 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6127 true, GSI_SAME_STMT);
6129 n1 = fd->loop.n1;
6130 n2 = fd->loop.n2;
6131 step = fd->loop.step;
6132 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6134 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6135 OMP_CLAUSE__LOOPTEMP_);
6136 gcc_assert (innerc);
6137 n1 = OMP_CLAUSE_DECL (innerc);
6138 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6139 OMP_CLAUSE__LOOPTEMP_);
6140 gcc_assert (innerc);
6141 n2 = OMP_CLAUSE_DECL (innerc);
6143 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6144 true, NULL_TREE, true, GSI_SAME_STMT);
6145 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6146 true, NULL_TREE, true, GSI_SAME_STMT);
6147 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6148 true, NULL_TREE, true, GSI_SAME_STMT);
6150 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6151 t = fold_build2 (PLUS_EXPR, itype, step, t);
6152 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6153 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6154 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6155 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6156 fold_build1 (NEGATE_EXPR, itype, t),
6157 fold_build1 (NEGATE_EXPR, itype, step));
6158 else
6159 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6160 t = fold_convert (itype, t);
6161 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6163 q = create_tmp_reg (itype, "q");
6164 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6165 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6166 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6168 tt = create_tmp_reg (itype, "tt");
6169 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6170 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6171 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6173 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6174 stmt = gimple_build_cond_empty (t);
6175 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6177 second_bb = split_block (entry_bb, stmt)->dest;
6178 gsi = gsi_last_bb (second_bb);
6179 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6181 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6182 GSI_SAME_STMT);
6183 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
6184 build_int_cst (itype, 1));
6185 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6187 third_bb = split_block (second_bb, stmt)->dest;
6188 gsi = gsi_last_bb (third_bb);
6189 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6191 t = build2 (MULT_EXPR, itype, q, threadid);
6192 t = build2 (PLUS_EXPR, itype, t, tt);
6193 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6195 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6196 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6198 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6199 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6201 /* Remove the GIMPLE_OMP_FOR statement. */
6202 gsi_remove (&gsi, true);
6204 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6205 gsi = gsi_start_bb (seq_start_bb);
6207 tree startvar = fd->loop.v;
6208 tree endvar = NULL_TREE;
6210 if (gimple_omp_for_combined_p (fd->for_stmt))
6212 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6213 ? gimple_omp_parallel_clauses (inner_stmt)
6214 : gimple_omp_for_clauses (inner_stmt);
6215 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6216 gcc_assert (innerc);
6217 startvar = OMP_CLAUSE_DECL (innerc);
6218 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6219 OMP_CLAUSE__LOOPTEMP_);
6220 gcc_assert (innerc);
6221 endvar = OMP_CLAUSE_DECL (innerc);
6223 t = fold_convert (itype, s0);
6224 t = fold_build2 (MULT_EXPR, itype, t, step);
6225 if (POINTER_TYPE_P (type))
6226 t = fold_build_pointer_plus (n1, t);
6227 else
6228 t = fold_build2 (PLUS_EXPR, type, t, n1);
6229 t = fold_convert (TREE_TYPE (startvar), t);
6230 t = force_gimple_operand_gsi (&gsi, t,
6231 DECL_P (startvar)
6232 && TREE_ADDRESSABLE (startvar),
6233 NULL_TREE, false, GSI_CONTINUE_LINKING);
6234 stmt = gimple_build_assign (startvar, t);
6235 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6237 t = fold_convert (itype, e0);
6238 t = fold_build2 (MULT_EXPR, itype, t, step);
6239 if (POINTER_TYPE_P (type))
6240 t = fold_build_pointer_plus (n1, t);
6241 else
6242 t = fold_build2 (PLUS_EXPR, type, t, n1);
6243 t = fold_convert (TREE_TYPE (startvar), t);
6244 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6245 false, GSI_CONTINUE_LINKING);
6246 if (endvar)
6248 stmt = gimple_build_assign (endvar, e);
6249 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6250 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6251 stmt = gimple_build_assign (fd->loop.v, e);
6252 else
6253 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6254 NULL_TREE);
6255 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6257 if (fd->collapse > 1)
6258 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6260 if (!broken_loop)
6262 /* The code controlling the sequential loop replaces the
6263 GIMPLE_OMP_CONTINUE. */
6264 gsi = gsi_last_bb (cont_bb);
6265 stmt = gsi_stmt (gsi);
6266 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6267 vmain = gimple_omp_continue_control_use (stmt);
6268 vback = gimple_omp_continue_control_def (stmt);
6270 if (!gimple_omp_for_combined_p (fd->for_stmt))
6272 if (POINTER_TYPE_P (type))
6273 t = fold_build_pointer_plus (vmain, step);
6274 else
6275 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6276 t = force_gimple_operand_gsi (&gsi, t,
6277 DECL_P (vback)
6278 && TREE_ADDRESSABLE (vback),
6279 NULL_TREE, true, GSI_SAME_STMT);
6280 stmt = gimple_build_assign (vback, t);
6281 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6283 t = build2 (fd->loop.cond_code, boolean_type_node,
6284 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6285 ? t : vback, e);
6286 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6289 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6290 gsi_remove (&gsi, true);
6292 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6293 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6296 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6297 gsi = gsi_last_bb (exit_bb);
6298 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6300 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6301 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6303 gsi_remove (&gsi, true);
6305 /* Connect all the blocks. */
6306 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6307 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6308 ep = find_edge (entry_bb, second_bb);
6309 ep->flags = EDGE_TRUE_VALUE;
6310 ep->probability = REG_BR_PROB_BASE / 4;
6311 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6312 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6314 if (!broken_loop)
6316 ep = find_edge (cont_bb, body_bb);
6317 if (gimple_omp_for_combined_p (fd->for_stmt))
6319 remove_edge (ep);
6320 ep = NULL;
6322 else if (fd->collapse > 1)
6324 remove_edge (ep);
6325 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6327 else
6328 ep->flags = EDGE_TRUE_VALUE;
6329 find_edge (cont_bb, fin_bb)->flags
6330 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6333 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6334 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6335 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6337 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6338 recompute_dominator (CDI_DOMINATORS, body_bb));
6339 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6340 recompute_dominator (CDI_DOMINATORS, fin_bb));
6342 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6344 struct loop *loop = alloc_loop ();
6345 loop->header = body_bb;
6346 if (collapse_bb == NULL)
6347 loop->latch = cont_bb;
6348 add_loop (loop, body_bb->loop_father);
6353 /* A subroutine of expand_omp_for. Generate code for a parallel
6354 loop with static schedule and a specified chunk size. Given
6355 parameters:
6357 for (V = N1; V cond N2; V += STEP) BODY;
6359 where COND is "<" or ">", we generate pseudocode
6361 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6362 if (cond is <)
6363 adj = STEP - 1;
6364 else
6365 adj = STEP + 1;
6366 if ((__typeof (V)) -1 > 0 && cond is >)
6367 n = -(adj + N2 - N1) / -STEP;
6368 else
6369 n = (adj + N2 - N1) / STEP;
6370 trip = 0;
6371 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6372 here so that V is defined
6373 if the loop is not entered
6375 s0 = (trip * nthreads + threadid) * CHUNK;
6376 e0 = min(s0 + CHUNK, n);
6377 if (s0 < n) goto L1; else goto L4;
6379 V = s0 * STEP + N1;
6380 e = e0 * STEP + N1;
6382 BODY;
6383 V += STEP;
6384 if (V cond e) goto L2; else goto L3;
6386 trip += 1;
6387 goto L0;
6391 static void
6392 expand_omp_for_static_chunk (struct omp_region *region,
6393 struct omp_for_data *fd, gimple inner_stmt)
6395 tree n, s0, e0, e, t;
6396 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6397 tree type, itype, vmain, vback, vextra;
6398 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6399 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6400 gimple_stmt_iterator gsi;
6401 gimple stmt;
6402 edge se;
6403 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6404 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6405 bool broken_loop = region->cont == NULL;
6406 tree *counts = NULL;
6407 tree n1, n2, step;
6409 itype = type = TREE_TYPE (fd->loop.v);
6410 if (POINTER_TYPE_P (type))
6411 itype = signed_type_for (type);
6413 entry_bb = region->entry;
6414 se = split_block (entry_bb, last_stmt (entry_bb));
6415 entry_bb = se->src;
6416 iter_part_bb = se->dest;
6417 cont_bb = region->cont;
6418 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6419 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6420 gcc_assert (broken_loop
6421 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6422 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6423 body_bb = single_succ (seq_start_bb);
6424 if (!broken_loop)
6426 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6427 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6428 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6430 exit_bb = region->exit;
6432 /* Trip and adjustment setup goes in ENTRY_BB. */
6433 gsi = gsi_last_bb (entry_bb);
6434 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6436 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6438 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6439 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6442 if (fd->collapse > 1)
6444 int first_zero_iter = -1;
6445 basic_block l2_dom_bb = NULL;
6447 counts = XALLOCAVEC (tree, fd->collapse);
6448 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6449 fin_bb, first_zero_iter,
6450 l2_dom_bb);
6451 t = NULL_TREE;
6453 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6454 t = integer_one_node;
6455 else
6456 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6457 fold_convert (type, fd->loop.n1),
6458 fold_convert (type, fd->loop.n2));
6459 if (fd->collapse == 1
6460 && TYPE_UNSIGNED (type)
6461 && (t == NULL_TREE || !integer_onep (t)))
6463 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6464 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6465 true, GSI_SAME_STMT);
6466 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6467 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6468 true, GSI_SAME_STMT);
6469 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6470 NULL_TREE, NULL_TREE);
6471 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6472 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6473 expand_omp_regimplify_p, NULL, NULL)
6474 || walk_tree (gimple_cond_rhs_ptr (stmt),
6475 expand_omp_regimplify_p, NULL, NULL))
6477 gsi = gsi_for_stmt (stmt);
6478 gimple_regimplify_operands (stmt, &gsi);
6480 se = split_block (entry_bb, stmt);
6481 se->flags = EDGE_TRUE_VALUE;
6482 entry_bb = se->dest;
6483 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6484 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6485 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6486 if (gimple_in_ssa_p (cfun))
6488 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6489 for (gsi = gsi_start_phis (fin_bb);
6490 !gsi_end_p (gsi); gsi_next (&gsi))
6492 gimple phi = gsi_stmt (gsi);
6493 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6494 se, UNKNOWN_LOCATION);
6497 gsi = gsi_last_bb (entry_bb);
6500 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6501 t = fold_convert (itype, t);
6502 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6503 true, GSI_SAME_STMT);
6505 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6506 t = fold_convert (itype, t);
6507 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6508 true, GSI_SAME_STMT);
6510 n1 = fd->loop.n1;
6511 n2 = fd->loop.n2;
6512 step = fd->loop.step;
6513 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6515 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6516 OMP_CLAUSE__LOOPTEMP_);
6517 gcc_assert (innerc);
6518 n1 = OMP_CLAUSE_DECL (innerc);
6519 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6520 OMP_CLAUSE__LOOPTEMP_);
6521 gcc_assert (innerc);
6522 n2 = OMP_CLAUSE_DECL (innerc);
6524 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6525 true, NULL_TREE, true, GSI_SAME_STMT);
6526 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6527 true, NULL_TREE, true, GSI_SAME_STMT);
6528 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6529 true, NULL_TREE, true, GSI_SAME_STMT);
6530 fd->chunk_size
6531 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
6532 true, NULL_TREE, true, GSI_SAME_STMT);
6534 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6535 t = fold_build2 (PLUS_EXPR, itype, step, t);
6536 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6537 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6538 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6539 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6540 fold_build1 (NEGATE_EXPR, itype, t),
6541 fold_build1 (NEGATE_EXPR, itype, step));
6542 else
6543 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6544 t = fold_convert (itype, t);
6545 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6546 true, GSI_SAME_STMT);
6548 trip_var = create_tmp_reg (itype, ".trip");
6549 if (gimple_in_ssa_p (cfun))
6551 trip_init = make_ssa_name (trip_var, NULL);
6552 trip_main = make_ssa_name (trip_var, NULL);
6553 trip_back = make_ssa_name (trip_var, NULL);
6555 else
6557 trip_init = trip_var;
6558 trip_main = trip_var;
6559 trip_back = trip_var;
6562 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6563 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6565 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6566 t = fold_build2 (MULT_EXPR, itype, t, step);
6567 if (POINTER_TYPE_P (type))
6568 t = fold_build_pointer_plus (n1, t);
6569 else
6570 t = fold_build2 (PLUS_EXPR, type, t, n1);
6571 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6572 true, GSI_SAME_STMT);
6574 /* Remove the GIMPLE_OMP_FOR. */
6575 gsi_remove (&gsi, true);
6577 /* Iteration space partitioning goes in ITER_PART_BB. */
6578 gsi = gsi_last_bb (iter_part_bb);
6580 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6581 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6582 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6583 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6584 false, GSI_CONTINUE_LINKING);
6586 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6587 t = fold_build2 (MIN_EXPR, itype, t, n);
6588 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6589 false, GSI_CONTINUE_LINKING);
6591 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6592 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6594 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6595 gsi = gsi_start_bb (seq_start_bb);
6597 tree startvar = fd->loop.v;
6598 tree endvar = NULL_TREE;
6600 if (gimple_omp_for_combined_p (fd->for_stmt))
6602 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6603 ? gimple_omp_parallel_clauses (inner_stmt)
6604 : gimple_omp_for_clauses (inner_stmt);
6605 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6606 gcc_assert (innerc);
6607 startvar = OMP_CLAUSE_DECL (innerc);
6608 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6609 OMP_CLAUSE__LOOPTEMP_);
6610 gcc_assert (innerc);
6611 endvar = OMP_CLAUSE_DECL (innerc);
6614 t = fold_convert (itype, s0);
6615 t = fold_build2 (MULT_EXPR, itype, t, step);
6616 if (POINTER_TYPE_P (type))
6617 t = fold_build_pointer_plus (n1, t);
6618 else
6619 t = fold_build2 (PLUS_EXPR, type, t, n1);
6620 t = fold_convert (TREE_TYPE (startvar), t);
6621 t = force_gimple_operand_gsi (&gsi, t,
6622 DECL_P (startvar)
6623 && TREE_ADDRESSABLE (startvar),
6624 NULL_TREE, false, GSI_CONTINUE_LINKING);
6625 stmt = gimple_build_assign (startvar, t);
6626 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6628 t = fold_convert (itype, e0);
6629 t = fold_build2 (MULT_EXPR, itype, t, step);
6630 if (POINTER_TYPE_P (type))
6631 t = fold_build_pointer_plus (n1, t);
6632 else
6633 t = fold_build2 (PLUS_EXPR, type, t, n1);
6634 t = fold_convert (TREE_TYPE (startvar), t);
6635 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6636 false, GSI_CONTINUE_LINKING);
6637 if (endvar)
6639 stmt = gimple_build_assign (endvar, e);
6640 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6641 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6642 stmt = gimple_build_assign (fd->loop.v, e);
6643 else
6644 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6645 NULL_TREE);
6646 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6648 if (fd->collapse > 1)
6649 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6651 if (!broken_loop)
6653 /* The code controlling the sequential loop goes in CONT_BB,
6654 replacing the GIMPLE_OMP_CONTINUE. */
6655 gsi = gsi_last_bb (cont_bb);
6656 stmt = gsi_stmt (gsi);
6657 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6658 vmain = gimple_omp_continue_control_use (stmt);
6659 vback = gimple_omp_continue_control_def (stmt);
6661 if (!gimple_omp_for_combined_p (fd->for_stmt))
6663 if (POINTER_TYPE_P (type))
6664 t = fold_build_pointer_plus (vmain, step);
6665 else
6666 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6667 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
6668 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6669 true, GSI_SAME_STMT);
6670 stmt = gimple_build_assign (vback, t);
6671 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6673 t = build2 (fd->loop.cond_code, boolean_type_node,
6674 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6675 ? t : vback, e);
6676 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6679 /* Remove GIMPLE_OMP_CONTINUE. */
6680 gsi_remove (&gsi, true);
6682 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6683 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6685 /* Trip update code goes into TRIP_UPDATE_BB. */
6686 gsi = gsi_start_bb (trip_update_bb);
6688 t = build_int_cst (itype, 1);
6689 t = build2 (PLUS_EXPR, itype, trip_main, t);
6690 stmt = gimple_build_assign (trip_back, t);
6691 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6694 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6695 gsi = gsi_last_bb (exit_bb);
6696 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6698 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6699 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6701 gsi_remove (&gsi, true);
6703 /* Connect the new blocks. */
6704 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6705 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6707 if (!broken_loop)
6709 se = find_edge (cont_bb, body_bb);
6710 if (gimple_omp_for_combined_p (fd->for_stmt))
6712 remove_edge (se);
6713 se = NULL;
6715 else if (fd->collapse > 1)
6717 remove_edge (se);
6718 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6720 else
6721 se->flags = EDGE_TRUE_VALUE;
6722 find_edge (cont_bb, trip_update_bb)->flags
6723 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6725 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6728 if (gimple_in_ssa_p (cfun))
6730 gimple_stmt_iterator psi;
6731 gimple phi;
6732 edge re, ene;
6733 edge_var_map *vm;
6734 size_t i;
6736 gcc_assert (fd->collapse == 1 && !broken_loop);
6738 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6739 remove arguments of the phi nodes in fin_bb. We need to create
6740 appropriate phi nodes in iter_part_bb instead. */
6741 se = single_pred_edge (fin_bb);
6742 re = single_succ_edge (trip_update_bb);
6743 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
6744 ene = single_succ_edge (entry_bb);
6746 psi = gsi_start_phis (fin_bb);
6747 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6748 gsi_next (&psi), ++i)
6750 gimple nphi;
6751 source_location locus;
6753 phi = gsi_stmt (psi);
6754 t = gimple_phi_result (phi);
6755 gcc_assert (t == redirect_edge_var_map_result (vm));
6756 nphi = create_phi_node (t, iter_part_bb);
6758 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6759 locus = gimple_phi_arg_location_from_edge (phi, se);
6761 /* A special case -- fd->loop.v is not yet computed in
6762 iter_part_bb, we need to use vextra instead. */
6763 if (t == fd->loop.v)
6764 t = vextra;
6765 add_phi_arg (nphi, t, ene, locus);
6766 locus = redirect_edge_var_map_location (vm);
6767 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6769 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6770 redirect_edge_var_map_clear (re);
6771 while (1)
6773 psi = gsi_start_phis (fin_bb);
6774 if (gsi_end_p (psi))
6775 break;
6776 remove_phi_node (&psi, false);
6779 /* Make phi node for trip. */
6780 phi = create_phi_node (trip_main, iter_part_bb);
6781 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6782 UNKNOWN_LOCATION);
6783 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6784 UNKNOWN_LOCATION);
6787 if (!broken_loop)
6788 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6789 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6790 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6791 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6792 recompute_dominator (CDI_DOMINATORS, fin_bb));
6793 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6794 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6795 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6796 recompute_dominator (CDI_DOMINATORS, body_bb));
6798 if (!broken_loop)
6800 struct loop *trip_loop = alloc_loop ();
6801 trip_loop->header = iter_part_bb;
6802 trip_loop->latch = trip_update_bb;
6803 add_loop (trip_loop, iter_part_bb->loop_father);
6805 if (!gimple_omp_for_combined_p (fd->for_stmt))
6807 struct loop *loop = alloc_loop ();
6808 loop->header = body_bb;
6809 if (collapse_bb == NULL)
6810 loop->latch = cont_bb;
6811 add_loop (loop, trip_loop);
6816 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
6817 Given parameters:
6818 for (V = N1; V cond N2; V += STEP) BODY;
6820 where COND is "<" or ">" or "!=", we generate pseudocode
6822 for (ind_var = low; ind_var < high; ind_var++)
6824 V = n1 + (ind_var * STEP)
6826 <BODY>
6829 In the above pseudocode, low and high are function parameters of the
6830 child function. In the function below, we are inserting a temp.
6831 variable that will be making a call to two OMP functions that will not be
6832 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
6833 with _Cilk_for). These functions are replaced with low and high
6834 by the function that handles taskreg. */
6837 static void
6838 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
6840 bool broken_loop = region->cont == NULL;
6841 basic_block entry_bb = region->entry;
6842 basic_block cont_bb = region->cont;
6844 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6845 gcc_assert (broken_loop
6846 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6847 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6848 basic_block l1_bb, l2_bb;
6850 if (!broken_loop)
6852 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6853 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6854 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6855 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6857 else
6859 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6860 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6861 l2_bb = single_succ (l1_bb);
6863 basic_block exit_bb = region->exit;
6864 basic_block l2_dom_bb = NULL;
6866 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
6868 /* Below statements until the "tree high_val = ..." are pseudo statements
6869 used to pass information to be used by expand_omp_taskreg.
6870 low_val and high_val will be replaced by the __low and __high
6871 parameter from the child function.
6873 The call_exprs part is a place-holder, it is mainly used
6874 to distinctly identify to the top-level part that this is
6875 where we should put low and high (reasoning given in header
6876 comment). */
6878 tree child_fndecl
6879 = gimple_omp_parallel_child_fn (last_stmt (region->outer->entry));
6880 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
6881 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
6883 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
6884 high_val = t;
6885 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
6886 low_val = t;
6888 gcc_assert (low_val && high_val);
6890 tree type = TREE_TYPE (low_val);
6891 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
6892 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6894 /* Not needed in SSA form right now. */
6895 gcc_assert (!gimple_in_ssa_p (cfun));
6896 if (l2_dom_bb == NULL)
6897 l2_dom_bb = l1_bb;
6899 tree n1 = low_val;
6900 tree n2 = high_val;
6902 gimple stmt = gimple_build_assign (ind_var, n1);
6904 /* Replace the GIMPLE_OMP_FOR statement. */
6905 gsi_replace (&gsi, stmt, true);
6907 if (!broken_loop)
6909 /* Code to control the increment goes in the CONT_BB. */
6910 gsi = gsi_last_bb (cont_bb);
6911 stmt = gsi_stmt (gsi);
6912 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6913 stmt = gimple_build_assign_with_ops (PLUS_EXPR, ind_var, ind_var,
6914 build_one_cst (type));
6916 /* Replace GIMPLE_OMP_CONTINUE. */
6917 gsi_replace (&gsi, stmt, true);
6920 /* Emit the condition in L1_BB. */
6921 gsi = gsi_after_labels (l1_bb);
6922 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
6923 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
6924 fd->loop.step);
6925 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
6926 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6927 fd->loop.n1, fold_convert (sizetype, t));
6928 else
6929 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6930 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
6931 t = fold_convert (TREE_TYPE (fd->loop.v), t);
6932 expand_omp_build_assign (&gsi, fd->loop.v, t);
6934 /* The condition is always '<' since the runtime will fill in the low
6935 and high values. */
6936 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
6937 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6939 /* Remove GIMPLE_OMP_RETURN. */
6940 gsi = gsi_last_bb (exit_bb);
6941 gsi_remove (&gsi, true);
6943 /* Connect the new blocks. */
6944 remove_edge (FALLTHRU_EDGE (entry_bb));
6946 edge e, ne;
6947 if (!broken_loop)
6949 remove_edge (BRANCH_EDGE (entry_bb));
6950 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6952 e = BRANCH_EDGE (l1_bb);
6953 ne = FALLTHRU_EDGE (l1_bb);
6954 e->flags = EDGE_TRUE_VALUE;
6956 else
6958 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6960 ne = single_succ_edge (l1_bb);
6961 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6964 ne->flags = EDGE_FALSE_VALUE;
6965 e->probability = REG_BR_PROB_BASE * 7 / 8;
6966 ne->probability = REG_BR_PROB_BASE / 8;
6968 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6969 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6970 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6972 if (!broken_loop)
6974 struct loop *loop = alloc_loop ();
6975 loop->header = l1_bb;
6976 loop->latch = cont_bb;
6977 add_loop (loop, l1_bb->loop_father);
6978 loop->safelen = INT_MAX;
6981 /* Pick the correct library function based on the precision of the
6982 induction variable type. */
6983 tree lib_fun = NULL_TREE;
6984 if (TYPE_PRECISION (type) == 32)
6985 lib_fun = cilk_for_32_fndecl;
6986 else if (TYPE_PRECISION (type) == 64)
6987 lib_fun = cilk_for_64_fndecl;
6988 else
6989 gcc_unreachable ();
6991 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
6993 /* WS_ARGS contains the library function flavor to call:
6994 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
6995 user-defined grain value. If the user does not define one, then zero
6996 is passed in by the parser. */
6997 vec_alloc (region->ws_args, 2);
6998 region->ws_args->quick_push (lib_fun);
6999 region->ws_args->quick_push (fd->chunk_size);
7002 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7003 loop. Given parameters:
7005 for (V = N1; V cond N2; V += STEP) BODY;
7007 where COND is "<" or ">", we generate pseudocode
7009 V = N1;
7010 goto L1;
7012 BODY;
7013 V += STEP;
7015 if (V cond N2) goto L0; else goto L2;
7018 For collapsed loops, given parameters:
7019 collapse(3)
7020 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7021 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7022 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7023 BODY;
7025 we generate pseudocode
7027 if (cond3 is <)
7028 adj = STEP3 - 1;
7029 else
7030 adj = STEP3 + 1;
7031 count3 = (adj + N32 - N31) / STEP3;
7032 if (cond2 is <)
7033 adj = STEP2 - 1;
7034 else
7035 adj = STEP2 + 1;
7036 count2 = (adj + N22 - N21) / STEP2;
7037 if (cond1 is <)
7038 adj = STEP1 - 1;
7039 else
7040 adj = STEP1 + 1;
7041 count1 = (adj + N12 - N11) / STEP1;
7042 count = count1 * count2 * count3;
7043 V = 0;
7044 V1 = N11;
7045 V2 = N21;
7046 V3 = N31;
7047 goto L1;
7049 BODY;
7050 V += 1;
7051 V3 += STEP3;
7052 V2 += (V3 cond3 N32) ? 0 : STEP2;
7053 V3 = (V3 cond3 N32) ? V3 : N31;
7054 V1 += (V2 cond2 N22) ? 0 : STEP1;
7055 V2 = (V2 cond2 N22) ? V2 : N21;
7057 if (V < count) goto L0; else goto L2;
7062 static void
7063 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7065 tree type, t;
7066 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7067 gimple_stmt_iterator gsi;
7068 gimple stmt;
7069 bool broken_loop = region->cont == NULL;
7070 edge e, ne;
7071 tree *counts = NULL;
7072 int i;
7073 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7074 OMP_CLAUSE_SAFELEN);
7075 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7076 OMP_CLAUSE__SIMDUID_);
7077 tree n1, n2;
7079 type = TREE_TYPE (fd->loop.v);
7080 entry_bb = region->entry;
7081 cont_bb = region->cont;
7082 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7083 gcc_assert (broken_loop
7084 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7085 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7086 if (!broken_loop)
7088 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7089 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7090 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7091 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7093 else
7095 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7096 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7097 l2_bb = single_succ (l1_bb);
7099 exit_bb = region->exit;
7100 l2_dom_bb = NULL;
7102 gsi = gsi_last_bb (entry_bb);
7104 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7105 /* Not needed in SSA form right now. */
7106 gcc_assert (!gimple_in_ssa_p (cfun));
7107 if (fd->collapse > 1)
7109 int first_zero_iter = -1;
7110 basic_block zero_iter_bb = l2_bb;
7112 counts = XALLOCAVEC (tree, fd->collapse);
7113 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7114 zero_iter_bb, first_zero_iter,
7115 l2_dom_bb);
7117 if (l2_dom_bb == NULL)
7118 l2_dom_bb = l1_bb;
7120 n1 = fd->loop.n1;
7121 n2 = fd->loop.n2;
7122 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7124 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7125 OMP_CLAUSE__LOOPTEMP_);
7126 gcc_assert (innerc);
7127 n1 = OMP_CLAUSE_DECL (innerc);
7128 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7129 OMP_CLAUSE__LOOPTEMP_);
7130 gcc_assert (innerc);
7131 n2 = OMP_CLAUSE_DECL (innerc);
7132 expand_omp_build_assign (&gsi, fd->loop.v,
7133 fold_convert (type, n1));
7134 if (fd->collapse > 1)
7136 gsi_prev (&gsi);
7137 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7138 gsi_next (&gsi);
7141 else
7143 expand_omp_build_assign (&gsi, fd->loop.v,
7144 fold_convert (type, fd->loop.n1));
7145 if (fd->collapse > 1)
7146 for (i = 0; i < fd->collapse; i++)
7148 tree itype = TREE_TYPE (fd->loops[i].v);
7149 if (POINTER_TYPE_P (itype))
7150 itype = signed_type_for (itype);
7151 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7152 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7156 /* Remove the GIMPLE_OMP_FOR statement. */
7157 gsi_remove (&gsi, true);
7159 if (!broken_loop)
7161 /* Code to control the increment goes in the CONT_BB. */
7162 gsi = gsi_last_bb (cont_bb);
7163 stmt = gsi_stmt (gsi);
7164 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7166 if (POINTER_TYPE_P (type))
7167 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7168 else
7169 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7170 expand_omp_build_assign (&gsi, fd->loop.v, t);
7172 if (fd->collapse > 1)
7174 i = fd->collapse - 1;
7175 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7177 t = fold_convert (sizetype, fd->loops[i].step);
7178 t = fold_build_pointer_plus (fd->loops[i].v, t);
7180 else
7182 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7183 fd->loops[i].step);
7184 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7185 fd->loops[i].v, t);
7187 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7189 for (i = fd->collapse - 1; i > 0; i--)
7191 tree itype = TREE_TYPE (fd->loops[i].v);
7192 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7193 if (POINTER_TYPE_P (itype2))
7194 itype2 = signed_type_for (itype2);
7195 t = build3 (COND_EXPR, itype2,
7196 build2 (fd->loops[i].cond_code, boolean_type_node,
7197 fd->loops[i].v,
7198 fold_convert (itype, fd->loops[i].n2)),
7199 build_int_cst (itype2, 0),
7200 fold_convert (itype2, fd->loops[i - 1].step));
7201 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7202 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7203 else
7204 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7205 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7207 t = build3 (COND_EXPR, itype,
7208 build2 (fd->loops[i].cond_code, boolean_type_node,
7209 fd->loops[i].v,
7210 fold_convert (itype, fd->loops[i].n2)),
7211 fd->loops[i].v,
7212 fold_convert (itype, fd->loops[i].n1));
7213 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7217 /* Remove GIMPLE_OMP_CONTINUE. */
7218 gsi_remove (&gsi, true);
7221 /* Emit the condition in L1_BB. */
7222 gsi = gsi_start_bb (l1_bb);
7224 t = fold_convert (type, n2);
7225 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7226 false, GSI_CONTINUE_LINKING);
7227 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7228 stmt = gimple_build_cond_empty (t);
7229 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7230 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
7231 NULL, NULL)
7232 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
7233 NULL, NULL))
7235 gsi = gsi_for_stmt (stmt);
7236 gimple_regimplify_operands (stmt, &gsi);
7239 /* Remove GIMPLE_OMP_RETURN. */
7240 gsi = gsi_last_bb (exit_bb);
7241 gsi_remove (&gsi, true);
7243 /* Connect the new blocks. */
7244 remove_edge (FALLTHRU_EDGE (entry_bb));
7246 if (!broken_loop)
7248 remove_edge (BRANCH_EDGE (entry_bb));
7249 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7251 e = BRANCH_EDGE (l1_bb);
7252 ne = FALLTHRU_EDGE (l1_bb);
7253 e->flags = EDGE_TRUE_VALUE;
7255 else
7257 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7259 ne = single_succ_edge (l1_bb);
7260 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7263 ne->flags = EDGE_FALSE_VALUE;
7264 e->probability = REG_BR_PROB_BASE * 7 / 8;
7265 ne->probability = REG_BR_PROB_BASE / 8;
7267 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7268 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7269 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7271 if (!broken_loop)
7273 struct loop *loop = alloc_loop ();
7274 loop->header = l1_bb;
7275 loop->latch = cont_bb;
7276 add_loop (loop, l1_bb->loop_father);
7277 if (safelen == NULL_TREE)
7278 loop->safelen = INT_MAX;
7279 else
7281 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7282 if (TREE_CODE (safelen) != INTEGER_CST)
7283 loop->safelen = 0;
7284 else if (!tree_fits_uhwi_p (safelen)
7285 || tree_to_uhwi (safelen) > INT_MAX)
7286 loop->safelen = INT_MAX;
7287 else
7288 loop->safelen = tree_to_uhwi (safelen);
7289 if (loop->safelen == 1)
7290 loop->safelen = 0;
7292 if (simduid)
7294 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7295 cfun->has_simduid_loops = true;
7297 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7298 the loop. */
7299 if ((flag_tree_loop_vectorize
7300 || (!global_options_set.x_flag_tree_loop_vectorize
7301 && !global_options_set.x_flag_tree_vectorize))
7302 && flag_tree_loop_optimize
7303 && loop->safelen > 1)
7305 loop->force_vectorize = true;
7306 cfun->has_force_vectorize_loops = true;
7312 /* Expand the OpenMP loop defined by REGION. */
7314 static void
7315 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7317 struct omp_for_data fd;
7318 struct omp_for_data_loop *loops;
7320 loops
7321 = (struct omp_for_data_loop *)
7322 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7323 * sizeof (struct omp_for_data_loop));
7324 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
7325 region->sched_kind = fd.sched_kind;
7327 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7328 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7329 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7330 if (region->cont)
7332 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7333 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7334 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7336 else
7337 /* If there isn't a continue then this is a degerate case where
7338 the introduction of abnormal edges during lowering will prevent
7339 original loops from being detected. Fix that up. */
7340 loops_state_set (LOOPS_NEED_FIXUP);
7342 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7343 expand_omp_simd (region, &fd);
7344 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7345 expand_cilk_for (region, &fd);
7346 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7347 && !fd.have_ordered)
7349 if (fd.chunk_size == NULL)
7350 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7351 else
7352 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7354 else
7356 int fn_index, start_ix, next_ix;
7358 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7359 == GF_OMP_FOR_KIND_FOR);
7360 if (fd.chunk_size == NULL
7361 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7362 fd.chunk_size = integer_zero_node;
7363 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7364 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7365 ? 3 : fd.sched_kind;
7366 fn_index += fd.have_ordered * 4;
7367 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7368 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7369 if (fd.iter_type == long_long_unsigned_type_node)
7371 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7372 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7373 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7374 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7376 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7377 (enum built_in_function) next_ix, inner_stmt);
7380 if (gimple_in_ssa_p (cfun))
7381 update_ssa (TODO_update_ssa_only_virtuals);
7385 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7387 v = GOMP_sections_start (n);
7389 switch (v)
7391 case 0:
7392 goto L2;
7393 case 1:
7394 section 1;
7395 goto L1;
7396 case 2:
7398 case n:
7400 default:
7401 abort ();
7404 v = GOMP_sections_next ();
7405 goto L0;
7407 reduction;
7409 If this is a combined parallel sections, replace the call to
7410 GOMP_sections_start with call to GOMP_sections_next. */
7412 static void
7413 expand_omp_sections (struct omp_region *region)
7415 tree t, u, vin = NULL, vmain, vnext, l2;
7416 unsigned len;
7417 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7418 gimple_stmt_iterator si, switch_si;
7419 gimple sections_stmt, stmt, cont;
7420 edge_iterator ei;
7421 edge e;
7422 struct omp_region *inner;
7423 unsigned i, casei;
7424 bool exit_reachable = region->cont != NULL;
7426 gcc_assert (region->exit != NULL);
7427 entry_bb = region->entry;
7428 l0_bb = single_succ (entry_bb);
7429 l1_bb = region->cont;
7430 l2_bb = region->exit;
7431 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7432 l2 = gimple_block_label (l2_bb);
7433 else
7435 /* This can happen if there are reductions. */
7436 len = EDGE_COUNT (l0_bb->succs);
7437 gcc_assert (len > 0);
7438 e = EDGE_SUCC (l0_bb, len - 1);
7439 si = gsi_last_bb (e->dest);
7440 l2 = NULL_TREE;
7441 if (gsi_end_p (si)
7442 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7443 l2 = gimple_block_label (e->dest);
7444 else
7445 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7447 si = gsi_last_bb (e->dest);
7448 if (gsi_end_p (si)
7449 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7451 l2 = gimple_block_label (e->dest);
7452 break;
7456 if (exit_reachable)
7457 default_bb = create_empty_bb (l1_bb->prev_bb);
7458 else
7459 default_bb = create_empty_bb (l0_bb);
7461 /* We will build a switch() with enough cases for all the
7462 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7463 and a default case to abort if something goes wrong. */
7464 len = EDGE_COUNT (l0_bb->succs);
7466 /* Use vec::quick_push on label_vec throughout, since we know the size
7467 in advance. */
7468 auto_vec<tree> label_vec (len);
7470 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7471 GIMPLE_OMP_SECTIONS statement. */
7472 si = gsi_last_bb (entry_bb);
7473 sections_stmt = gsi_stmt (si);
7474 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7475 vin = gimple_omp_sections_control (sections_stmt);
7476 if (!is_combined_parallel (region))
7478 /* If we are not inside a combined parallel+sections region,
7479 call GOMP_sections_start. */
7480 t = build_int_cst (unsigned_type_node, len - 1);
7481 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7482 stmt = gimple_build_call (u, 1, t);
7484 else
7486 /* Otherwise, call GOMP_sections_next. */
7487 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7488 stmt = gimple_build_call (u, 0);
7490 gimple_call_set_lhs (stmt, vin);
7491 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7492 gsi_remove (&si, true);
7494 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7495 L0_BB. */
7496 switch_si = gsi_last_bb (l0_bb);
7497 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7498 if (exit_reachable)
7500 cont = last_stmt (l1_bb);
7501 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7502 vmain = gimple_omp_continue_control_use (cont);
7503 vnext = gimple_omp_continue_control_def (cont);
7505 else
7507 vmain = vin;
7508 vnext = NULL_TREE;
7511 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7512 label_vec.quick_push (t);
7513 i = 1;
7515 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7516 for (inner = region->inner, casei = 1;
7517 inner;
7518 inner = inner->next, i++, casei++)
7520 basic_block s_entry_bb, s_exit_bb;
7522 /* Skip optional reduction region. */
7523 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7525 --i;
7526 --casei;
7527 continue;
7530 s_entry_bb = inner->entry;
7531 s_exit_bb = inner->exit;
7533 t = gimple_block_label (s_entry_bb);
7534 u = build_int_cst (unsigned_type_node, casei);
7535 u = build_case_label (u, NULL, t);
7536 label_vec.quick_push (u);
7538 si = gsi_last_bb (s_entry_bb);
7539 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7540 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7541 gsi_remove (&si, true);
7542 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7544 if (s_exit_bb == NULL)
7545 continue;
7547 si = gsi_last_bb (s_exit_bb);
7548 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7549 gsi_remove (&si, true);
7551 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7554 /* Error handling code goes in DEFAULT_BB. */
7555 t = gimple_block_label (default_bb);
7556 u = build_case_label (NULL, NULL, t);
7557 make_edge (l0_bb, default_bb, 0);
7558 add_bb_to_loop (default_bb, current_loops->tree_root);
7560 stmt = gimple_build_switch (vmain, u, label_vec);
7561 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7562 gsi_remove (&switch_si, true);
7564 si = gsi_start_bb (default_bb);
7565 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7566 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7568 if (exit_reachable)
7570 tree bfn_decl;
7572 /* Code to get the next section goes in L1_BB. */
7573 si = gsi_last_bb (l1_bb);
7574 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7576 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7577 stmt = gimple_build_call (bfn_decl, 0);
7578 gimple_call_set_lhs (stmt, vnext);
7579 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7580 gsi_remove (&si, true);
7582 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7585 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7586 si = gsi_last_bb (l2_bb);
7587 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7588 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7589 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7590 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7591 else
7592 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7593 stmt = gimple_build_call (t, 0);
7594 if (gimple_omp_return_lhs (gsi_stmt (si)))
7595 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7596 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7597 gsi_remove (&si, true);
7599 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7603 /* Expand code for an OpenMP single directive. We've already expanded
7604 much of the code, here we simply place the GOMP_barrier call. */
7606 static void
7607 expand_omp_single (struct omp_region *region)
7609 basic_block entry_bb, exit_bb;
7610 gimple_stmt_iterator si;
7612 entry_bb = region->entry;
7613 exit_bb = region->exit;
7615 si = gsi_last_bb (entry_bb);
7616 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7617 gsi_remove (&si, true);
7618 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7620 si = gsi_last_bb (exit_bb);
7621 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7623 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7624 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7626 gsi_remove (&si, true);
7627 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7631 /* Generic expansion for OpenMP synchronization directives: master,
7632 ordered and critical. All we need to do here is remove the entry
7633 and exit markers for REGION. */
7635 static void
7636 expand_omp_synch (struct omp_region *region)
7638 basic_block entry_bb, exit_bb;
7639 gimple_stmt_iterator si;
7641 entry_bb = region->entry;
7642 exit_bb = region->exit;
7644 si = gsi_last_bb (entry_bb);
7645 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7646 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7647 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7648 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7649 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7650 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7651 gsi_remove (&si, true);
7652 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7654 if (exit_bb)
7656 si = gsi_last_bb (exit_bb);
7657 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7658 gsi_remove (&si, true);
7659 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7663 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7664 operation as a normal volatile load. */
7666 static bool
7667 expand_omp_atomic_load (basic_block load_bb, tree addr,
7668 tree loaded_val, int index)
7670 enum built_in_function tmpbase;
7671 gimple_stmt_iterator gsi;
7672 basic_block store_bb;
7673 location_t loc;
7674 gimple stmt;
7675 tree decl, call, type, itype;
7677 gsi = gsi_last_bb (load_bb);
7678 stmt = gsi_stmt (gsi);
7679 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7680 loc = gimple_location (stmt);
7682 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7683 is smaller than word size, then expand_atomic_load assumes that the load
7684 is atomic. We could avoid the builtin entirely in this case. */
7686 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7687 decl = builtin_decl_explicit (tmpbase);
7688 if (decl == NULL_TREE)
7689 return false;
7691 type = TREE_TYPE (loaded_val);
7692 itype = TREE_TYPE (TREE_TYPE (decl));
7694 call = build_call_expr_loc (loc, decl, 2, addr,
7695 build_int_cst (NULL,
7696 gimple_omp_atomic_seq_cst_p (stmt)
7697 ? MEMMODEL_SEQ_CST
7698 : MEMMODEL_RELAXED));
7699 if (!useless_type_conversion_p (type, itype))
7700 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7701 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7703 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7704 gsi_remove (&gsi, true);
7706 store_bb = single_succ (load_bb);
7707 gsi = gsi_last_bb (store_bb);
7708 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7709 gsi_remove (&gsi, true);
7711 if (gimple_in_ssa_p (cfun))
7712 update_ssa (TODO_update_ssa_no_phi);
7714 return true;
7717 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7718 operation as a normal volatile store. */
7720 static bool
7721 expand_omp_atomic_store (basic_block load_bb, tree addr,
7722 tree loaded_val, tree stored_val, int index)
7724 enum built_in_function tmpbase;
7725 gimple_stmt_iterator gsi;
7726 basic_block store_bb = single_succ (load_bb);
7727 location_t loc;
7728 gimple stmt;
7729 tree decl, call, type, itype;
7730 enum machine_mode imode;
7731 bool exchange;
7733 gsi = gsi_last_bb (load_bb);
7734 stmt = gsi_stmt (gsi);
7735 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7737 /* If the load value is needed, then this isn't a store but an exchange. */
7738 exchange = gimple_omp_atomic_need_value_p (stmt);
7740 gsi = gsi_last_bb (store_bb);
7741 stmt = gsi_stmt (gsi);
7742 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7743 loc = gimple_location (stmt);
7745 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7746 is smaller than word size, then expand_atomic_store assumes that the store
7747 is atomic. We could avoid the builtin entirely in this case. */
7749 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7750 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7751 decl = builtin_decl_explicit (tmpbase);
7752 if (decl == NULL_TREE)
7753 return false;
7755 type = TREE_TYPE (stored_val);
7757 /* Dig out the type of the function's second argument. */
7758 itype = TREE_TYPE (decl);
7759 itype = TYPE_ARG_TYPES (itype);
7760 itype = TREE_CHAIN (itype);
7761 itype = TREE_VALUE (itype);
7762 imode = TYPE_MODE (itype);
7764 if (exchange && !can_atomic_exchange_p (imode, true))
7765 return false;
7767 if (!useless_type_conversion_p (itype, type))
7768 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7769 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7770 build_int_cst (NULL,
7771 gimple_omp_atomic_seq_cst_p (stmt)
7772 ? MEMMODEL_SEQ_CST
7773 : MEMMODEL_RELAXED));
7774 if (exchange)
7776 if (!useless_type_conversion_p (type, itype))
7777 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7778 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7781 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7782 gsi_remove (&gsi, true);
7784 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7785 gsi = gsi_last_bb (load_bb);
7786 gsi_remove (&gsi, true);
7788 if (gimple_in_ssa_p (cfun))
7789 update_ssa (TODO_update_ssa_no_phi);
7791 return true;
7794 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7795 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7796 size of the data type, and thus usable to find the index of the builtin
7797 decl. Returns false if the expression is not of the proper form. */
7799 static bool
7800 expand_omp_atomic_fetch_op (basic_block load_bb,
7801 tree addr, tree loaded_val,
7802 tree stored_val, int index)
7804 enum built_in_function oldbase, newbase, tmpbase;
7805 tree decl, itype, call;
7806 tree lhs, rhs;
7807 basic_block store_bb = single_succ (load_bb);
7808 gimple_stmt_iterator gsi;
7809 gimple stmt;
7810 location_t loc;
7811 enum tree_code code;
7812 bool need_old, need_new;
7813 enum machine_mode imode;
7814 bool seq_cst;
7816 /* We expect to find the following sequences:
7818 load_bb:
7819 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7821 store_bb:
7822 val = tmp OP something; (or: something OP tmp)
7823 GIMPLE_OMP_STORE (val)
7825 ???FIXME: Allow a more flexible sequence.
7826 Perhaps use data flow to pick the statements.
7830 gsi = gsi_after_labels (store_bb);
7831 stmt = gsi_stmt (gsi);
7832 loc = gimple_location (stmt);
7833 if (!is_gimple_assign (stmt))
7834 return false;
7835 gsi_next (&gsi);
7836 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7837 return false;
7838 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7839 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7840 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7841 gcc_checking_assert (!need_old || !need_new);
7843 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7844 return false;
7846 /* Check for one of the supported fetch-op operations. */
7847 code = gimple_assign_rhs_code (stmt);
7848 switch (code)
7850 case PLUS_EXPR:
7851 case POINTER_PLUS_EXPR:
7852 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7853 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7854 break;
7855 case MINUS_EXPR:
7856 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7857 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7858 break;
7859 case BIT_AND_EXPR:
7860 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7861 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7862 break;
7863 case BIT_IOR_EXPR:
7864 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7865 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7866 break;
7867 case BIT_XOR_EXPR:
7868 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7869 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7870 break;
7871 default:
7872 return false;
7875 /* Make sure the expression is of the proper form. */
7876 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7877 rhs = gimple_assign_rhs2 (stmt);
7878 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7879 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7880 rhs = gimple_assign_rhs1 (stmt);
7881 else
7882 return false;
7884 tmpbase = ((enum built_in_function)
7885 ((need_new ? newbase : oldbase) + index + 1));
7886 decl = builtin_decl_explicit (tmpbase);
7887 if (decl == NULL_TREE)
7888 return false;
7889 itype = TREE_TYPE (TREE_TYPE (decl));
7890 imode = TYPE_MODE (itype);
7892 /* We could test all of the various optabs involved, but the fact of the
7893 matter is that (with the exception of i486 vs i586 and xadd) all targets
7894 that support any atomic operaton optab also implements compare-and-swap.
7895 Let optabs.c take care of expanding any compare-and-swap loop. */
7896 if (!can_compare_and_swap_p (imode, true))
7897 return false;
7899 gsi = gsi_last_bb (load_bb);
7900 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7902 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7903 It only requires that the operation happen atomically. Thus we can
7904 use the RELAXED memory model. */
7905 call = build_call_expr_loc (loc, decl, 3, addr,
7906 fold_convert_loc (loc, itype, rhs),
7907 build_int_cst (NULL,
7908 seq_cst ? MEMMODEL_SEQ_CST
7909 : MEMMODEL_RELAXED));
7911 if (need_old || need_new)
7913 lhs = need_old ? loaded_val : stored_val;
7914 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7915 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7917 else
7918 call = fold_convert_loc (loc, void_type_node, call);
7919 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7920 gsi_remove (&gsi, true);
7922 gsi = gsi_last_bb (store_bb);
7923 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7924 gsi_remove (&gsi, true);
7925 gsi = gsi_last_bb (store_bb);
7926 gsi_remove (&gsi, true);
7928 if (gimple_in_ssa_p (cfun))
7929 update_ssa (TODO_update_ssa_no_phi);
7931 return true;
7934 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7936 oldval = *addr;
7937 repeat:
7938 newval = rhs; // with oldval replacing *addr in rhs
7939 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7940 if (oldval != newval)
7941 goto repeat;
7943 INDEX is log2 of the size of the data type, and thus usable to find the
7944 index of the builtin decl. */
7946 static bool
7947 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7948 tree addr, tree loaded_val, tree stored_val,
7949 int index)
7951 tree loadedi, storedi, initial, new_storedi, old_vali;
7952 tree type, itype, cmpxchg, iaddr;
7953 gimple_stmt_iterator si;
7954 basic_block loop_header = single_succ (load_bb);
7955 gimple phi, stmt;
7956 edge e;
7957 enum built_in_function fncode;
7959 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7960 order to use the RELAXED memory model effectively. */
7961 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7962 + index + 1);
7963 cmpxchg = builtin_decl_explicit (fncode);
7964 if (cmpxchg == NULL_TREE)
7965 return false;
7966 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7967 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7969 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7970 return false;
7972 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7973 si = gsi_last_bb (load_bb);
7974 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7976 /* For floating-point values, we'll need to view-convert them to integers
7977 so that we can perform the atomic compare and swap. Simplify the
7978 following code by always setting up the "i"ntegral variables. */
7979 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7981 tree iaddr_val;
7983 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7984 true), NULL);
7985 iaddr_val
7986 = force_gimple_operand_gsi (&si,
7987 fold_convert (TREE_TYPE (iaddr), addr),
7988 false, NULL_TREE, true, GSI_SAME_STMT);
7989 stmt = gimple_build_assign (iaddr, iaddr_val);
7990 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7991 loadedi = create_tmp_var (itype, NULL);
7992 if (gimple_in_ssa_p (cfun))
7993 loadedi = make_ssa_name (loadedi, NULL);
7995 else
7997 iaddr = addr;
7998 loadedi = loaded_val;
8001 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8002 tree loaddecl = builtin_decl_explicit (fncode);
8003 if (loaddecl)
8004 initial
8005 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8006 build_call_expr (loaddecl, 2, iaddr,
8007 build_int_cst (NULL_TREE,
8008 MEMMODEL_RELAXED)));
8009 else
8010 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8011 build_int_cst (TREE_TYPE (iaddr), 0));
8013 initial
8014 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8015 GSI_SAME_STMT);
8017 /* Move the value to the LOADEDI temporary. */
8018 if (gimple_in_ssa_p (cfun))
8020 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8021 phi = create_phi_node (loadedi, loop_header);
8022 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8023 initial);
8025 else
8026 gsi_insert_before (&si,
8027 gimple_build_assign (loadedi, initial),
8028 GSI_SAME_STMT);
8029 if (loadedi != loaded_val)
8031 gimple_stmt_iterator gsi2;
8032 tree x;
8034 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8035 gsi2 = gsi_start_bb (loop_header);
8036 if (gimple_in_ssa_p (cfun))
8038 gimple stmt;
8039 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8040 true, GSI_SAME_STMT);
8041 stmt = gimple_build_assign (loaded_val, x);
8042 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8044 else
8046 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8047 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8048 true, GSI_SAME_STMT);
8051 gsi_remove (&si, true);
8053 si = gsi_last_bb (store_bb);
8054 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8056 if (iaddr == addr)
8057 storedi = stored_val;
8058 else
8059 storedi =
8060 force_gimple_operand_gsi (&si,
8061 build1 (VIEW_CONVERT_EXPR, itype,
8062 stored_val), true, NULL_TREE, true,
8063 GSI_SAME_STMT);
8065 /* Build the compare&swap statement. */
8066 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8067 new_storedi = force_gimple_operand_gsi (&si,
8068 fold_convert (TREE_TYPE (loadedi),
8069 new_storedi),
8070 true, NULL_TREE,
8071 true, GSI_SAME_STMT);
8073 if (gimple_in_ssa_p (cfun))
8074 old_vali = loadedi;
8075 else
8077 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
8078 stmt = gimple_build_assign (old_vali, loadedi);
8079 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8081 stmt = gimple_build_assign (loadedi, new_storedi);
8082 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8085 /* Note that we always perform the comparison as an integer, even for
8086 floating point. This allows the atomic operation to properly
8087 succeed even with NaNs and -0.0. */
8088 stmt = gimple_build_cond_empty
8089 (build2 (NE_EXPR, boolean_type_node,
8090 new_storedi, old_vali));
8091 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8093 /* Update cfg. */
8094 e = single_succ_edge (store_bb);
8095 e->flags &= ~EDGE_FALLTHRU;
8096 e->flags |= EDGE_FALSE_VALUE;
8098 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8100 /* Copy the new value to loadedi (we already did that before the condition
8101 if we are not in SSA). */
8102 if (gimple_in_ssa_p (cfun))
8104 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8105 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8108 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8109 gsi_remove (&si, true);
8111 struct loop *loop = alloc_loop ();
8112 loop->header = loop_header;
8113 loop->latch = store_bb;
8114 add_loop (loop, loop_header->loop_father);
8116 if (gimple_in_ssa_p (cfun))
8117 update_ssa (TODO_update_ssa_no_phi);
8119 return true;
8122 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8124 GOMP_atomic_start ();
8125 *addr = rhs;
8126 GOMP_atomic_end ();
8128 The result is not globally atomic, but works so long as all parallel
8129 references are within #pragma omp atomic directives. According to
8130 responses received from omp@openmp.org, appears to be within spec.
8131 Which makes sense, since that's how several other compilers handle
8132 this situation as well.
8133 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8134 expanding. STORED_VAL is the operand of the matching
8135 GIMPLE_OMP_ATOMIC_STORE.
8137 We replace
8138 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8139 loaded_val = *addr;
8141 and replace
8142 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8143 *addr = stored_val;
8146 static bool
8147 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8148 tree addr, tree loaded_val, tree stored_val)
8150 gimple_stmt_iterator si;
8151 gimple stmt;
8152 tree t;
8154 si = gsi_last_bb (load_bb);
8155 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8157 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8158 t = build_call_expr (t, 0);
8159 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8161 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8162 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8163 gsi_remove (&si, true);
8165 si = gsi_last_bb (store_bb);
8166 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8168 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8169 stored_val);
8170 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8172 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8173 t = build_call_expr (t, 0);
8174 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8175 gsi_remove (&si, true);
8177 if (gimple_in_ssa_p (cfun))
8178 update_ssa (TODO_update_ssa_no_phi);
8179 return true;
8182 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8183 using expand_omp_atomic_fetch_op. If it failed, we try to
8184 call expand_omp_atomic_pipeline, and if it fails too, the
8185 ultimate fallback is wrapping the operation in a mutex
8186 (expand_omp_atomic_mutex). REGION is the atomic region built
8187 by build_omp_regions_1(). */
8189 static void
8190 expand_omp_atomic (struct omp_region *region)
8192 basic_block load_bb = region->entry, store_bb = region->exit;
8193 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
8194 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8195 tree addr = gimple_omp_atomic_load_rhs (load);
8196 tree stored_val = gimple_omp_atomic_store_val (store);
8197 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8198 HOST_WIDE_INT index;
8200 /* Make sure the type is one of the supported sizes. */
8201 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8202 index = exact_log2 (index);
8203 if (index >= 0 && index <= 4)
8205 unsigned int align = TYPE_ALIGN_UNIT (type);
8207 /* __sync builtins require strict data alignment. */
8208 if (exact_log2 (align) >= index)
8210 /* Atomic load. */
8211 if (loaded_val == stored_val
8212 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8213 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8214 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8215 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8216 return;
8218 /* Atomic store. */
8219 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8220 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8221 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8222 && store_bb == single_succ (load_bb)
8223 && first_stmt (store_bb) == store
8224 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8225 stored_val, index))
8226 return;
8228 /* When possible, use specialized atomic update functions. */
8229 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8230 && store_bb == single_succ (load_bb)
8231 && expand_omp_atomic_fetch_op (load_bb, addr,
8232 loaded_val, stored_val, index))
8233 return;
8235 /* If we don't have specialized __sync builtins, try and implement
8236 as a compare and swap loop. */
8237 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8238 loaded_val, stored_val, index))
8239 return;
8243 /* The ultimate fallback is wrapping the operation in a mutex. */
8244 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8248 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
8250 static void
8251 expand_omp_target (struct omp_region *region)
8253 basic_block entry_bb, exit_bb, new_bb;
8254 struct function *child_cfun = NULL;
8255 tree child_fn = NULL_TREE, block, t;
8256 gimple_stmt_iterator gsi;
8257 gimple entry_stmt, stmt;
8258 edge e;
8260 entry_stmt = last_stmt (region->entry);
8261 new_bb = region->entry;
8262 int kind = gimple_omp_target_kind (entry_stmt);
8263 if (kind == GF_OMP_TARGET_KIND_REGION)
8265 child_fn = gimple_omp_target_child_fn (entry_stmt);
8266 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8269 entry_bb = region->entry;
8270 exit_bb = region->exit;
8272 if (kind == GF_OMP_TARGET_KIND_REGION)
8274 unsigned srcidx, dstidx, num;
8276 /* If the target region needs data sent from the parent
8277 function, then the very first statement (except possible
8278 tree profile counter updates) of the parallel body
8279 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8280 &.OMP_DATA_O is passed as an argument to the child function,
8281 we need to replace it with the argument as seen by the child
8282 function.
8284 In most cases, this will end up being the identity assignment
8285 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8286 a function call that has been inlined, the original PARM_DECL
8287 .OMP_DATA_I may have been converted into a different local
8288 variable. In which case, we need to keep the assignment. */
8289 if (gimple_omp_target_data_arg (entry_stmt))
8291 basic_block entry_succ_bb = single_succ (entry_bb);
8292 gimple_stmt_iterator gsi;
8293 tree arg;
8294 gimple tgtcopy_stmt = NULL;
8295 tree sender
8296 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
8298 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8300 gcc_assert (!gsi_end_p (gsi));
8301 stmt = gsi_stmt (gsi);
8302 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8303 continue;
8305 if (gimple_num_ops (stmt) == 2)
8307 tree arg = gimple_assign_rhs1 (stmt);
8309 /* We're ignoring the subcode because we're
8310 effectively doing a STRIP_NOPS. */
8312 if (TREE_CODE (arg) == ADDR_EXPR
8313 && TREE_OPERAND (arg, 0) == sender)
8315 tgtcopy_stmt = stmt;
8316 break;
8321 gcc_assert (tgtcopy_stmt != NULL);
8322 arg = DECL_ARGUMENTS (child_fn);
8324 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8325 gsi_remove (&gsi, true);
8328 /* Declare local variables needed in CHILD_CFUN. */
8329 block = DECL_INITIAL (child_fn);
8330 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8331 /* The gimplifier could record temporaries in target block
8332 rather than in containing function's local_decls chain,
8333 which would mean cgraph missed finalizing them. Do it now. */
8334 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8335 if (TREE_CODE (t) == VAR_DECL
8336 && TREE_STATIC (t)
8337 && !DECL_EXTERNAL (t))
8338 varpool_node::finalize_decl (t);
8339 DECL_SAVED_TREE (child_fn) = NULL;
8340 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8341 gimple_set_body (child_fn, NULL);
8342 TREE_USED (block) = 1;
8344 /* Reset DECL_CONTEXT on function arguments. */
8345 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8346 DECL_CONTEXT (t) = child_fn;
8348 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8349 so that it can be moved to the child function. */
8350 gsi = gsi_last_bb (entry_bb);
8351 stmt = gsi_stmt (gsi);
8352 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
8353 && gimple_omp_target_kind (stmt)
8354 == GF_OMP_TARGET_KIND_REGION);
8355 gsi_remove (&gsi, true);
8356 e = split_block (entry_bb, stmt);
8357 entry_bb = e->dest;
8358 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8360 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8361 if (exit_bb)
8363 gsi = gsi_last_bb (exit_bb);
8364 gcc_assert (!gsi_end_p (gsi)
8365 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8366 stmt = gimple_build_return (NULL);
8367 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8368 gsi_remove (&gsi, true);
8371 /* Move the target region into CHILD_CFUN. */
8373 block = gimple_block (entry_stmt);
8375 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8376 if (exit_bb)
8377 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8378 /* When the OMP expansion process cannot guarantee an up-to-date
8379 loop tree arrange for the child function to fixup loops. */
8380 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8381 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8383 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8384 num = vec_safe_length (child_cfun->local_decls);
8385 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8387 t = (*child_cfun->local_decls)[srcidx];
8388 if (DECL_CONTEXT (t) == cfun->decl)
8389 continue;
8390 if (srcidx != dstidx)
8391 (*child_cfun->local_decls)[dstidx] = t;
8392 dstidx++;
8394 if (dstidx != num)
8395 vec_safe_truncate (child_cfun->local_decls, dstidx);
8397 /* Inform the callgraph about the new function. */
8398 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8399 cgraph_node::add_new_function (child_fn, true);
8401 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8402 fixed in a following pass. */
8403 push_cfun (child_cfun);
8404 cgraph_edge::rebuild_edges ();
8406 /* Some EH regions might become dead, see PR34608. If
8407 pass_cleanup_cfg isn't the first pass to happen with the
8408 new child, these dead EH edges might cause problems.
8409 Clean them up now. */
8410 if (flag_exceptions)
8412 basic_block bb;
8413 bool changed = false;
8415 FOR_EACH_BB_FN (bb, cfun)
8416 changed |= gimple_purge_dead_eh_edges (bb);
8417 if (changed)
8418 cleanup_tree_cfg ();
8420 pop_cfun ();
8423 /* Emit a library call to launch the target region, or do data
8424 transfers. */
8425 tree t1, t2, t3, t4, device, cond, c, clauses;
8426 enum built_in_function start_ix;
8427 location_t clause_loc;
8429 clauses = gimple_omp_target_clauses (entry_stmt);
8431 if (kind == GF_OMP_TARGET_KIND_REGION)
8432 start_ix = BUILT_IN_GOMP_TARGET;
8433 else if (kind == GF_OMP_TARGET_KIND_DATA)
8434 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8435 else
8436 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8438 /* By default, the value of DEVICE is -1 (let runtime library choose)
8439 and there is no conditional. */
8440 cond = NULL_TREE;
8441 device = build_int_cst (integer_type_node, -1);
8443 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8444 if (c)
8445 cond = OMP_CLAUSE_IF_EXPR (c);
8447 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8448 if (c)
8450 device = OMP_CLAUSE_DEVICE_ID (c);
8451 clause_loc = OMP_CLAUSE_LOCATION (c);
8453 else
8454 clause_loc = gimple_location (entry_stmt);
8456 /* Ensure 'device' is of the correct type. */
8457 device = fold_convert_loc (clause_loc, integer_type_node, device);
8459 /* If we found the clause 'if (cond)', build
8460 (cond ? device : -2). */
8461 if (cond)
8463 cond = gimple_boolify (cond);
8465 basic_block cond_bb, then_bb, else_bb;
8466 edge e;
8467 tree tmp_var;
8469 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8470 if (kind != GF_OMP_TARGET_KIND_REGION)
8472 gsi = gsi_last_bb (new_bb);
8473 gsi_prev (&gsi);
8474 e = split_block (new_bb, gsi_stmt (gsi));
8476 else
8477 e = split_block (new_bb, NULL);
8478 cond_bb = e->src;
8479 new_bb = e->dest;
8480 remove_edge (e);
8482 then_bb = create_empty_bb (cond_bb);
8483 else_bb = create_empty_bb (then_bb);
8484 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8485 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8487 stmt = gimple_build_cond_empty (cond);
8488 gsi = gsi_last_bb (cond_bb);
8489 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8491 gsi = gsi_start_bb (then_bb);
8492 stmt = gimple_build_assign (tmp_var, device);
8493 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8495 gsi = gsi_start_bb (else_bb);
8496 stmt = gimple_build_assign (tmp_var,
8497 build_int_cst (integer_type_node, -2));
8498 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8500 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8501 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8502 add_bb_to_loop (then_bb, cond_bb->loop_father);
8503 add_bb_to_loop (else_bb, cond_bb->loop_father);
8504 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8505 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8507 device = tmp_var;
8510 gsi = gsi_last_bb (new_bb);
8511 t = gimple_omp_target_data_arg (entry_stmt);
8512 if (t == NULL)
8514 t1 = size_zero_node;
8515 t2 = build_zero_cst (ptr_type_node);
8516 t3 = t2;
8517 t4 = t2;
8519 else
8521 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8522 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8523 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8524 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8525 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8528 gimple g;
8529 /* FIXME: This will be address of
8530 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8531 symbol, as soon as the linker plugin is able to create it for us. */
8532 tree openmp_target = build_zero_cst (ptr_type_node);
8533 if (kind == GF_OMP_TARGET_KIND_REGION)
8535 tree fnaddr = build_fold_addr_expr (child_fn);
8536 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8537 device, fnaddr, openmp_target, t1, t2, t3, t4);
8539 else
8540 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8541 device, openmp_target, t1, t2, t3, t4);
8542 gimple_set_location (g, gimple_location (entry_stmt));
8543 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8544 if (kind != GF_OMP_TARGET_KIND_REGION)
8546 g = gsi_stmt (gsi);
8547 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8548 gsi_remove (&gsi, true);
8550 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8552 gsi = gsi_last_bb (region->exit);
8553 g = gsi_stmt (gsi);
8554 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8555 gsi_remove (&gsi, true);
8560 /* Expand the parallel region tree rooted at REGION. Expansion
8561 proceeds in depth-first order. Innermost regions are expanded
8562 first. This way, parallel regions that require a new function to
8563 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8564 internal dependencies in their body. */
8566 static void
8567 expand_omp (struct omp_region *region)
8569 while (region)
8571 location_t saved_location;
8572 gimple inner_stmt = NULL;
8574 /* First, determine whether this is a combined parallel+workshare
8575 region. */
8576 if (region->type == GIMPLE_OMP_PARALLEL)
8577 determine_parallel_type (region);
8579 if (region->type == GIMPLE_OMP_FOR
8580 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8581 inner_stmt = last_stmt (region->inner->entry);
8583 if (region->inner)
8584 expand_omp (region->inner);
8586 saved_location = input_location;
8587 if (gimple_has_location (last_stmt (region->entry)))
8588 input_location = gimple_location (last_stmt (region->entry));
8590 switch (region->type)
8592 case GIMPLE_OMP_PARALLEL:
8593 case GIMPLE_OMP_TASK:
8594 expand_omp_taskreg (region);
8595 break;
8597 case GIMPLE_OMP_FOR:
8598 expand_omp_for (region, inner_stmt);
8599 break;
8601 case GIMPLE_OMP_SECTIONS:
8602 expand_omp_sections (region);
8603 break;
8605 case GIMPLE_OMP_SECTION:
8606 /* Individual omp sections are handled together with their
8607 parent GIMPLE_OMP_SECTIONS region. */
8608 break;
8610 case GIMPLE_OMP_SINGLE:
8611 expand_omp_single (region);
8612 break;
8614 case GIMPLE_OMP_MASTER:
8615 case GIMPLE_OMP_TASKGROUP:
8616 case GIMPLE_OMP_ORDERED:
8617 case GIMPLE_OMP_CRITICAL:
8618 case GIMPLE_OMP_TEAMS:
8619 expand_omp_synch (region);
8620 break;
8622 case GIMPLE_OMP_ATOMIC_LOAD:
8623 expand_omp_atomic (region);
8624 break;
8626 case GIMPLE_OMP_TARGET:
8627 expand_omp_target (region);
8628 break;
8630 default:
8631 gcc_unreachable ();
8634 input_location = saved_location;
8635 region = region->next;
8640 /* Helper for build_omp_regions. Scan the dominator tree starting at
8641 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8642 true, the function ends once a single tree is built (otherwise, whole
8643 forest of OMP constructs may be built). */
8645 static void
8646 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8647 bool single_tree)
8649 gimple_stmt_iterator gsi;
8650 gimple stmt;
8651 basic_block son;
8653 gsi = gsi_last_bb (bb);
8654 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8656 struct omp_region *region;
8657 enum gimple_code code;
8659 stmt = gsi_stmt (gsi);
8660 code = gimple_code (stmt);
8661 if (code == GIMPLE_OMP_RETURN)
8663 /* STMT is the return point out of region PARENT. Mark it
8664 as the exit point and make PARENT the immediately
8665 enclosing region. */
8666 gcc_assert (parent);
8667 region = parent;
8668 region->exit = bb;
8669 parent = parent->outer;
8671 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8673 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8674 GIMPLE_OMP_RETURN, but matches with
8675 GIMPLE_OMP_ATOMIC_LOAD. */
8676 gcc_assert (parent);
8677 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8678 region = parent;
8679 region->exit = bb;
8680 parent = parent->outer;
8683 else if (code == GIMPLE_OMP_CONTINUE)
8685 gcc_assert (parent);
8686 parent->cont = bb;
8688 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8690 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8691 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8694 else if (code == GIMPLE_OMP_TARGET
8695 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8696 new_omp_region (bb, code, parent);
8697 else
8699 /* Otherwise, this directive becomes the parent for a new
8700 region. */
8701 region = new_omp_region (bb, code, parent);
8702 parent = region;
8706 if (single_tree && !parent)
8707 return;
8709 for (son = first_dom_son (CDI_DOMINATORS, bb);
8710 son;
8711 son = next_dom_son (CDI_DOMINATORS, son))
8712 build_omp_regions_1 (son, parent, single_tree);
8715 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8716 root_omp_region. */
8718 static void
8719 build_omp_regions_root (basic_block root)
8721 gcc_assert (root_omp_region == NULL);
8722 build_omp_regions_1 (root, NULL, true);
8723 gcc_assert (root_omp_region != NULL);
8726 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8728 void
8729 omp_expand_local (basic_block head)
8731 build_omp_regions_root (head);
8732 if (dump_file && (dump_flags & TDF_DETAILS))
8734 fprintf (dump_file, "\nOMP region tree\n\n");
8735 dump_omp_region (dump_file, root_omp_region, 0);
8736 fprintf (dump_file, "\n");
8739 remove_exit_barriers (root_omp_region);
8740 expand_omp (root_omp_region);
8742 free_omp_regions ();
8745 /* Scan the CFG and build a tree of OMP regions. Return the root of
8746 the OMP region tree. */
8748 static void
8749 build_omp_regions (void)
8751 gcc_assert (root_omp_region == NULL);
8752 calculate_dominance_info (CDI_DOMINATORS);
8753 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8756 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8758 static unsigned int
8759 execute_expand_omp (void)
8761 build_omp_regions ();
8763 if (!root_omp_region)
8764 return 0;
8766 if (dump_file)
8768 fprintf (dump_file, "\nOMP region tree\n\n");
8769 dump_omp_region (dump_file, root_omp_region, 0);
8770 fprintf (dump_file, "\n");
8773 remove_exit_barriers (root_omp_region);
8775 expand_omp (root_omp_region);
8777 cleanup_tree_cfg ();
8779 free_omp_regions ();
8781 return 0;
8784 /* OMP expansion -- the default pass, run before creation of SSA form. */
8786 namespace {
8788 const pass_data pass_data_expand_omp =
8790 GIMPLE_PASS, /* type */
8791 "ompexp", /* name */
8792 OPTGROUP_NONE, /* optinfo_flags */
8793 TV_NONE, /* tv_id */
8794 PROP_gimple_any, /* properties_required */
8795 0, /* properties_provided */
8796 0, /* properties_destroyed */
8797 0, /* todo_flags_start */
8798 0, /* todo_flags_finish */
8801 class pass_expand_omp : public gimple_opt_pass
8803 public:
8804 pass_expand_omp (gcc::context *ctxt)
8805 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8808 /* opt_pass methods: */
8809 virtual bool gate (function *)
8811 return ((flag_openmp != 0 || flag_openmp_simd != 0
8812 || flag_cilkplus != 0) && !seen_error ());
8815 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8817 }; // class pass_expand_omp
8819 } // anon namespace
8821 gimple_opt_pass *
8822 make_pass_expand_omp (gcc::context *ctxt)
8824 return new pass_expand_omp (ctxt);
8827 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8829 /* If ctx is a worksharing context inside of a cancellable parallel
8830 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8831 and conditional branch to parallel's cancel_label to handle
8832 cancellation in the implicit barrier. */
8834 static void
8835 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8837 gimple omp_return = gimple_seq_last_stmt (*body);
8838 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8839 if (gimple_omp_return_nowait_p (omp_return))
8840 return;
8841 if (ctx->outer
8842 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8843 && ctx->outer->cancellable)
8845 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8846 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8847 tree lhs = create_tmp_var (c_bool_type, NULL);
8848 gimple_omp_return_set_lhs (omp_return, lhs);
8849 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8850 gimple g = gimple_build_cond (NE_EXPR, lhs,
8851 fold_convert (c_bool_type,
8852 boolean_false_node),
8853 ctx->outer->cancel_label, fallthru_label);
8854 gimple_seq_add_stmt (body, g);
8855 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8859 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8860 CTX is the enclosing OMP context for the current statement. */
8862 static void
8863 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8865 tree block, control;
8866 gimple_stmt_iterator tgsi;
8867 gimple stmt, new_stmt, bind, t;
8868 gimple_seq ilist, dlist, olist, new_body;
8870 stmt = gsi_stmt (*gsi_p);
8872 push_gimplify_context ();
8874 dlist = NULL;
8875 ilist = NULL;
8876 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8877 &ilist, &dlist, ctx, NULL);
8879 new_body = gimple_omp_body (stmt);
8880 gimple_omp_set_body (stmt, NULL);
8881 tgsi = gsi_start (new_body);
8882 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8884 omp_context *sctx;
8885 gimple sec_start;
8887 sec_start = gsi_stmt (tgsi);
8888 sctx = maybe_lookup_ctx (sec_start);
8889 gcc_assert (sctx);
8891 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8892 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8893 GSI_CONTINUE_LINKING);
8894 gimple_omp_set_body (sec_start, NULL);
8896 if (gsi_one_before_end_p (tgsi))
8898 gimple_seq l = NULL;
8899 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8900 &l, ctx);
8901 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8902 gimple_omp_section_set_last (sec_start);
8905 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8906 GSI_CONTINUE_LINKING);
8909 block = make_node (BLOCK);
8910 bind = gimple_build_bind (NULL, new_body, block);
8912 olist = NULL;
8913 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8915 block = make_node (BLOCK);
8916 new_stmt = gimple_build_bind (NULL, NULL, block);
8917 gsi_replace (gsi_p, new_stmt, true);
8919 pop_gimplify_context (new_stmt);
8920 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8921 BLOCK_VARS (block) = gimple_bind_vars (bind);
8922 if (BLOCK_VARS (block))
8923 TREE_USED (block) = 1;
8925 new_body = NULL;
8926 gimple_seq_add_seq (&new_body, ilist);
8927 gimple_seq_add_stmt (&new_body, stmt);
8928 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8929 gimple_seq_add_stmt (&new_body, bind);
8931 control = create_tmp_var (unsigned_type_node, ".section");
8932 t = gimple_build_omp_continue (control, control);
8933 gimple_omp_sections_set_control (stmt, control);
8934 gimple_seq_add_stmt (&new_body, t);
8936 gimple_seq_add_seq (&new_body, olist);
8937 if (ctx->cancellable)
8938 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8939 gimple_seq_add_seq (&new_body, dlist);
8941 new_body = maybe_catch_exception (new_body);
8943 t = gimple_build_omp_return
8944 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8945 OMP_CLAUSE_NOWAIT));
8946 gimple_seq_add_stmt (&new_body, t);
8947 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8949 gimple_bind_set_body (new_stmt, new_body);
8953 /* A subroutine of lower_omp_single. Expand the simple form of
8954 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8956 if (GOMP_single_start ())
8957 BODY;
8958 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8960 FIXME. It may be better to delay expanding the logic of this until
8961 pass_expand_omp. The expanded logic may make the job more difficult
8962 to a synchronization analysis pass. */
8964 static void
8965 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8967 location_t loc = gimple_location (single_stmt);
8968 tree tlabel = create_artificial_label (loc);
8969 tree flabel = create_artificial_label (loc);
8970 gimple call, cond;
8971 tree lhs, decl;
8973 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8974 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8975 call = gimple_build_call (decl, 0);
8976 gimple_call_set_lhs (call, lhs);
8977 gimple_seq_add_stmt (pre_p, call);
8979 cond = gimple_build_cond (EQ_EXPR, lhs,
8980 fold_convert_loc (loc, TREE_TYPE (lhs),
8981 boolean_true_node),
8982 tlabel, flabel);
8983 gimple_seq_add_stmt (pre_p, cond);
8984 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8985 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8986 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8990 /* A subroutine of lower_omp_single. Expand the simple form of
8991 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8993 #pragma omp single copyprivate (a, b, c)
8995 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8998 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
9000 BODY;
9001 copyout.a = a;
9002 copyout.b = b;
9003 copyout.c = c;
9004 GOMP_single_copy_end (&copyout);
9006 else
9008 a = copyout_p->a;
9009 b = copyout_p->b;
9010 c = copyout_p->c;
9012 GOMP_barrier ();
9015 FIXME. It may be better to delay expanding the logic of this until
9016 pass_expand_omp. The expanded logic may make the job more difficult
9017 to a synchronization analysis pass. */
9019 static void
9020 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
9022 tree ptr_type, t, l0, l1, l2, bfn_decl;
9023 gimple_seq copyin_seq;
9024 location_t loc = gimple_location (single_stmt);
9026 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
9028 ptr_type = build_pointer_type (ctx->record_type);
9029 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
9031 l0 = create_artificial_label (loc);
9032 l1 = create_artificial_label (loc);
9033 l2 = create_artificial_label (loc);
9035 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
9036 t = build_call_expr_loc (loc, bfn_decl, 0);
9037 t = fold_convert_loc (loc, ptr_type, t);
9038 gimplify_assign (ctx->receiver_decl, t, pre_p);
9040 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
9041 build_int_cst (ptr_type, 0));
9042 t = build3 (COND_EXPR, void_type_node, t,
9043 build_and_jump (&l0), build_and_jump (&l1));
9044 gimplify_and_add (t, pre_p);
9046 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
9048 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9050 copyin_seq = NULL;
9051 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
9052 &copyin_seq, ctx);
9054 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9055 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
9056 t = build_call_expr_loc (loc, bfn_decl, 1, t);
9057 gimplify_and_add (t, pre_p);
9059 t = build_and_jump (&l2);
9060 gimplify_and_add (t, pre_p);
9062 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
9064 gimple_seq_add_seq (pre_p, copyin_seq);
9066 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
9070 /* Expand code for an OpenMP single directive. */
9072 static void
9073 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9075 tree block;
9076 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
9077 gimple_seq bind_body, bind_body_tail = NULL, dlist;
9079 push_gimplify_context ();
9081 block = make_node (BLOCK);
9082 bind = gimple_build_bind (NULL, NULL, block);
9083 gsi_replace (gsi_p, bind, true);
9084 bind_body = NULL;
9085 dlist = NULL;
9086 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
9087 &bind_body, &dlist, ctx, NULL);
9088 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
9090 gimple_seq_add_stmt (&bind_body, single_stmt);
9092 if (ctx->record_type)
9093 lower_omp_single_copy (single_stmt, &bind_body, ctx);
9094 else
9095 lower_omp_single_simple (single_stmt, &bind_body);
9097 gimple_omp_set_body (single_stmt, NULL);
9099 gimple_seq_add_seq (&bind_body, dlist);
9101 bind_body = maybe_catch_exception (bind_body);
9103 t = gimple_build_omp_return
9104 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
9105 OMP_CLAUSE_NOWAIT));
9106 gimple_seq_add_stmt (&bind_body_tail, t);
9107 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
9108 if (ctx->record_type)
9110 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9111 tree clobber = build_constructor (ctx->record_type, NULL);
9112 TREE_THIS_VOLATILE (clobber) = 1;
9113 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9114 clobber), GSI_SAME_STMT);
9116 gimple_seq_add_seq (&bind_body, bind_body_tail);
9117 gimple_bind_set_body (bind, bind_body);
9119 pop_gimplify_context (bind);
9121 gimple_bind_append_vars (bind, ctx->block_vars);
9122 BLOCK_VARS (block) = ctx->block_vars;
9123 if (BLOCK_VARS (block))
9124 TREE_USED (block) = 1;
9128 /* Expand code for an OpenMP master directive. */
9130 static void
9131 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9133 tree block, lab = NULL, x, bfn_decl;
9134 gimple stmt = gsi_stmt (*gsi_p), bind;
9135 location_t loc = gimple_location (stmt);
9136 gimple_seq tseq;
9138 push_gimplify_context ();
9140 block = make_node (BLOCK);
9141 bind = gimple_build_bind (NULL, NULL, block);
9142 gsi_replace (gsi_p, bind, true);
9143 gimple_bind_add_stmt (bind, stmt);
9145 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9146 x = build_call_expr_loc (loc, bfn_decl, 0);
9147 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
9148 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9149 tseq = NULL;
9150 gimplify_and_add (x, &tseq);
9151 gimple_bind_add_seq (bind, tseq);
9153 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9154 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9155 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9156 gimple_omp_set_body (stmt, NULL);
9158 gimple_bind_add_stmt (bind, gimple_build_label (lab));
9160 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9162 pop_gimplify_context (bind);
9164 gimple_bind_append_vars (bind, ctx->block_vars);
9165 BLOCK_VARS (block) = ctx->block_vars;
9169 /* Expand code for an OpenMP taskgroup directive. */
9171 static void
9172 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9174 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9175 tree block = make_node (BLOCK);
9177 bind = gimple_build_bind (NULL, NULL, block);
9178 gsi_replace (gsi_p, bind, true);
9179 gimple_bind_add_stmt (bind, stmt);
9181 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9183 gimple_bind_add_stmt (bind, x);
9185 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9186 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9187 gimple_omp_set_body (stmt, NULL);
9189 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9191 gimple_bind_append_vars (bind, ctx->block_vars);
9192 BLOCK_VARS (block) = ctx->block_vars;
9196 /* Expand code for an OpenMP ordered directive. */
9198 static void
9199 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9201 tree block;
9202 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9204 push_gimplify_context ();
9206 block = make_node (BLOCK);
9207 bind = gimple_build_bind (NULL, NULL, block);
9208 gsi_replace (gsi_p, bind, true);
9209 gimple_bind_add_stmt (bind, stmt);
9211 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
9213 gimple_bind_add_stmt (bind, x);
9215 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9216 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9217 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9218 gimple_omp_set_body (stmt, NULL);
9220 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
9221 gimple_bind_add_stmt (bind, x);
9223 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9225 pop_gimplify_context (bind);
9227 gimple_bind_append_vars (bind, ctx->block_vars);
9228 BLOCK_VARS (block) = gimple_bind_vars (bind);
9232 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9233 substitution of a couple of function calls. But in the NAMED case,
9234 requires that languages coordinate a symbol name. It is therefore
9235 best put here in common code. */
9237 static GTY((param1_is (tree), param2_is (tree)))
9238 splay_tree critical_name_mutexes;
9240 static void
9241 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9243 tree block;
9244 tree name, lock, unlock;
9245 gimple stmt = gsi_stmt (*gsi_p), bind;
9246 location_t loc = gimple_location (stmt);
9247 gimple_seq tbody;
9249 name = gimple_omp_critical_name (stmt);
9250 if (name)
9252 tree decl;
9253 splay_tree_node n;
9255 if (!critical_name_mutexes)
9256 critical_name_mutexes
9257 = splay_tree_new_ggc (splay_tree_compare_pointers,
9258 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
9259 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
9261 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
9262 if (n == NULL)
9264 char *new_str;
9266 decl = create_tmp_var_raw (ptr_type_node, NULL);
9268 new_str = ACONCAT ((".gomp_critical_user_",
9269 IDENTIFIER_POINTER (name), NULL));
9270 DECL_NAME (decl) = get_identifier (new_str);
9271 TREE_PUBLIC (decl) = 1;
9272 TREE_STATIC (decl) = 1;
9273 DECL_COMMON (decl) = 1;
9274 DECL_ARTIFICIAL (decl) = 1;
9275 DECL_IGNORED_P (decl) = 1;
9276 varpool_node::finalize_decl (decl);
9278 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
9279 (splay_tree_value) decl);
9281 else
9282 decl = (tree) n->value;
9284 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
9285 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
9287 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
9288 unlock = build_call_expr_loc (loc, unlock, 1,
9289 build_fold_addr_expr_loc (loc, decl));
9291 else
9293 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
9294 lock = build_call_expr_loc (loc, lock, 0);
9296 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
9297 unlock = build_call_expr_loc (loc, unlock, 0);
9300 push_gimplify_context ();
9302 block = make_node (BLOCK);
9303 bind = gimple_build_bind (NULL, NULL, block);
9304 gsi_replace (gsi_p, bind, true);
9305 gimple_bind_add_stmt (bind, stmt);
9307 tbody = gimple_bind_body (bind);
9308 gimplify_and_add (lock, &tbody);
9309 gimple_bind_set_body (bind, tbody);
9311 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9312 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9313 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9314 gimple_omp_set_body (stmt, NULL);
9316 tbody = gimple_bind_body (bind);
9317 gimplify_and_add (unlock, &tbody);
9318 gimple_bind_set_body (bind, tbody);
9320 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9322 pop_gimplify_context (bind);
9323 gimple_bind_append_vars (bind, ctx->block_vars);
9324 BLOCK_VARS (block) = gimple_bind_vars (bind);
9328 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9329 for a lastprivate clause. Given a loop control predicate of (V
9330 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9331 is appended to *DLIST, iterator initialization is appended to
9332 *BODY_P. */
9334 static void
9335 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
9336 gimple_seq *dlist, struct omp_context *ctx)
9338 tree clauses, cond, vinit;
9339 enum tree_code cond_code;
9340 gimple_seq stmts;
9342 cond_code = fd->loop.cond_code;
9343 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
9345 /* When possible, use a strict equality expression. This can let VRP
9346 type optimizations deduce the value and remove a copy. */
9347 if (tree_fits_shwi_p (fd->loop.step))
9349 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
9350 if (step == 1 || step == -1)
9351 cond_code = EQ_EXPR;
9354 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
9356 clauses = gimple_omp_for_clauses (fd->for_stmt);
9357 stmts = NULL;
9358 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
9359 if (!gimple_seq_empty_p (stmts))
9361 gimple_seq_add_seq (&stmts, *dlist);
9362 *dlist = stmts;
9364 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9365 vinit = fd->loop.n1;
9366 if (cond_code == EQ_EXPR
9367 && tree_fits_shwi_p (fd->loop.n2)
9368 && ! integer_zerop (fd->loop.n2))
9369 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
9370 else
9371 vinit = unshare_expr (vinit);
9373 /* Initialize the iterator variable, so that threads that don't execute
9374 any iterations don't execute the lastprivate clauses by accident. */
9375 gimplify_assign (fd->loop.v, vinit, body_p);
9380 /* Lower code for an OpenMP loop directive. */
9382 static void
9383 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9385 tree *rhs_p, block;
9386 struct omp_for_data fd, *fdp = NULL;
9387 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
9388 gimple_seq omp_for_body, body, dlist;
9389 size_t i;
9391 push_gimplify_context ();
9393 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
9395 block = make_node (BLOCK);
9396 new_stmt = gimple_build_bind (NULL, NULL, block);
9397 /* Replace at gsi right away, so that 'stmt' is no member
9398 of a sequence anymore as we're going to add to to a different
9399 one below. */
9400 gsi_replace (gsi_p, new_stmt, true);
9402 /* Move declaration of temporaries in the loop body before we make
9403 it go away. */
9404 omp_for_body = gimple_omp_body (stmt);
9405 if (!gimple_seq_empty_p (omp_for_body)
9406 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9408 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
9409 tree vars = gimple_bind_vars (inner_bind);
9410 gimple_bind_append_vars (new_stmt, vars);
9411 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9412 keep them on the inner_bind and it's block. */
9413 gimple_bind_set_vars (inner_bind, NULL_TREE);
9414 if (gimple_bind_block (inner_bind))
9415 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9418 if (gimple_omp_for_combined_into_p (stmt))
9420 extract_omp_for_data (stmt, &fd, NULL);
9421 fdp = &fd;
9423 /* We need two temporaries with fd.loop.v type (istart/iend)
9424 and then (fd.collapse - 1) temporaries with the same
9425 type for count2 ... countN-1 vars if not constant. */
9426 size_t count = 2;
9427 tree type = fd.iter_type;
9428 if (fd.collapse > 1
9429 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9430 count += fd.collapse - 1;
9431 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9432 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9433 tree clauses = *pc;
9434 if (parallel_for)
9435 outerc
9436 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9437 OMP_CLAUSE__LOOPTEMP_);
9438 for (i = 0; i < count; i++)
9440 tree temp;
9441 if (parallel_for)
9443 gcc_assert (outerc);
9444 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9445 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9446 OMP_CLAUSE__LOOPTEMP_);
9448 else
9450 temp = create_tmp_var (type, NULL);
9451 insert_decl_map (&ctx->outer->cb, temp, temp);
9453 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9454 OMP_CLAUSE_DECL (*pc) = temp;
9455 pc = &OMP_CLAUSE_CHAIN (*pc);
9457 *pc = clauses;
9460 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9461 dlist = NULL;
9462 body = NULL;
9463 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9464 fdp);
9465 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9467 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9469 /* Lower the header expressions. At this point, we can assume that
9470 the header is of the form:
9472 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9474 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9475 using the .omp_data_s mapping, if needed. */
9476 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9478 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9479 if (!is_gimple_min_invariant (*rhs_p))
9480 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9482 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9483 if (!is_gimple_min_invariant (*rhs_p))
9484 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9486 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9487 if (!is_gimple_min_invariant (*rhs_p))
9488 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9491 /* Once lowered, extract the bounds and clauses. */
9492 extract_omp_for_data (stmt, &fd, NULL);
9494 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9496 gimple_seq_add_stmt (&body, stmt);
9497 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9499 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9500 fd.loop.v));
9502 /* After the loop, add exit clauses. */
9503 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9505 if (ctx->cancellable)
9506 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9508 gimple_seq_add_seq (&body, dlist);
9510 body = maybe_catch_exception (body);
9512 /* Region exit marker goes at the end of the loop body. */
9513 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9514 maybe_add_implicit_barrier_cancel (ctx, &body);
9515 pop_gimplify_context (new_stmt);
9517 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9518 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9519 if (BLOCK_VARS (block))
9520 TREE_USED (block) = 1;
9522 gimple_bind_set_body (new_stmt, body);
9523 gimple_omp_set_body (stmt, NULL);
9524 gimple_omp_for_set_pre_body (stmt, NULL);
9527 /* Callback for walk_stmts. Check if the current statement only contains
9528 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9530 static tree
9531 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9532 bool *handled_ops_p,
9533 struct walk_stmt_info *wi)
9535 int *info = (int *) wi->info;
9536 gimple stmt = gsi_stmt (*gsi_p);
9538 *handled_ops_p = true;
9539 switch (gimple_code (stmt))
9541 WALK_SUBSTMTS;
9543 case GIMPLE_OMP_FOR:
9544 case GIMPLE_OMP_SECTIONS:
9545 *info = *info == 0 ? 1 : -1;
9546 break;
9547 default:
9548 *info = -1;
9549 break;
9551 return NULL;
9554 struct omp_taskcopy_context
9556 /* This field must be at the beginning, as we do "inheritance": Some
9557 callback functions for tree-inline.c (e.g., omp_copy_decl)
9558 receive a copy_body_data pointer that is up-casted to an
9559 omp_context pointer. */
9560 copy_body_data cb;
9561 omp_context *ctx;
9564 static tree
9565 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9567 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9569 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9570 return create_tmp_var (TREE_TYPE (var), NULL);
9572 return var;
9575 static tree
9576 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9578 tree name, new_fields = NULL, type, f;
9580 type = lang_hooks.types.make_type (RECORD_TYPE);
9581 name = DECL_NAME (TYPE_NAME (orig_type));
9582 name = build_decl (gimple_location (tcctx->ctx->stmt),
9583 TYPE_DECL, name, type);
9584 TYPE_NAME (type) = name;
9586 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9588 tree new_f = copy_node (f);
9589 DECL_CONTEXT (new_f) = type;
9590 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9591 TREE_CHAIN (new_f) = new_fields;
9592 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9593 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9594 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9595 &tcctx->cb, NULL);
9596 new_fields = new_f;
9597 tcctx->cb.decl_map->put (f, new_f);
9599 TYPE_FIELDS (type) = nreverse (new_fields);
9600 layout_type (type);
9601 return type;
9604 /* Create task copyfn. */
9606 static void
9607 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9609 struct function *child_cfun;
9610 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9611 tree record_type, srecord_type, bind, list;
9612 bool record_needs_remap = false, srecord_needs_remap = false;
9613 splay_tree_node n;
9614 struct omp_taskcopy_context tcctx;
9615 location_t loc = gimple_location (task_stmt);
9617 child_fn = gimple_omp_task_copy_fn (task_stmt);
9618 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9619 gcc_assert (child_cfun->cfg == NULL);
9620 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9622 /* Reset DECL_CONTEXT on function arguments. */
9623 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9624 DECL_CONTEXT (t) = child_fn;
9626 /* Populate the function. */
9627 push_gimplify_context ();
9628 push_cfun (child_cfun);
9630 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9631 TREE_SIDE_EFFECTS (bind) = 1;
9632 list = NULL;
9633 DECL_SAVED_TREE (child_fn) = bind;
9634 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9636 /* Remap src and dst argument types if needed. */
9637 record_type = ctx->record_type;
9638 srecord_type = ctx->srecord_type;
9639 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9640 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9642 record_needs_remap = true;
9643 break;
9645 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9646 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9648 srecord_needs_remap = true;
9649 break;
9652 if (record_needs_remap || srecord_needs_remap)
9654 memset (&tcctx, '\0', sizeof (tcctx));
9655 tcctx.cb.src_fn = ctx->cb.src_fn;
9656 tcctx.cb.dst_fn = child_fn;
9657 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
9658 gcc_checking_assert (tcctx.cb.src_node);
9659 tcctx.cb.dst_node = tcctx.cb.src_node;
9660 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9661 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9662 tcctx.cb.eh_lp_nr = 0;
9663 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9664 tcctx.cb.decl_map = new hash_map<tree, tree>;
9665 tcctx.ctx = ctx;
9667 if (record_needs_remap)
9668 record_type = task_copyfn_remap_type (&tcctx, record_type);
9669 if (srecord_needs_remap)
9670 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9672 else
9673 tcctx.cb.decl_map = NULL;
9675 arg = DECL_ARGUMENTS (child_fn);
9676 TREE_TYPE (arg) = build_pointer_type (record_type);
9677 sarg = DECL_CHAIN (arg);
9678 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9680 /* First pass: initialize temporaries used in record_type and srecord_type
9681 sizes and field offsets. */
9682 if (tcctx.cb.decl_map)
9683 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9684 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9686 tree *p;
9688 decl = OMP_CLAUSE_DECL (c);
9689 p = tcctx.cb.decl_map->get (decl);
9690 if (p == NULL)
9691 continue;
9692 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9693 sf = (tree) n->value;
9694 sf = *tcctx.cb.decl_map->get (sf);
9695 src = build_simple_mem_ref_loc (loc, sarg);
9696 src = omp_build_component_ref (src, sf);
9697 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9698 append_to_statement_list (t, &list);
9701 /* Second pass: copy shared var pointers and copy construct non-VLA
9702 firstprivate vars. */
9703 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9704 switch (OMP_CLAUSE_CODE (c))
9706 case OMP_CLAUSE_SHARED:
9707 decl = OMP_CLAUSE_DECL (c);
9708 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9709 if (n == NULL)
9710 break;
9711 f = (tree) n->value;
9712 if (tcctx.cb.decl_map)
9713 f = *tcctx.cb.decl_map->get (f);
9714 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9715 sf = (tree) n->value;
9716 if (tcctx.cb.decl_map)
9717 sf = *tcctx.cb.decl_map->get (sf);
9718 src = build_simple_mem_ref_loc (loc, sarg);
9719 src = omp_build_component_ref (src, sf);
9720 dst = build_simple_mem_ref_loc (loc, arg);
9721 dst = omp_build_component_ref (dst, f);
9722 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9723 append_to_statement_list (t, &list);
9724 break;
9725 case OMP_CLAUSE_FIRSTPRIVATE:
9726 decl = OMP_CLAUSE_DECL (c);
9727 if (is_variable_sized (decl))
9728 break;
9729 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9730 if (n == NULL)
9731 break;
9732 f = (tree) n->value;
9733 if (tcctx.cb.decl_map)
9734 f = *tcctx.cb.decl_map->get (f);
9735 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9736 if (n != NULL)
9738 sf = (tree) n->value;
9739 if (tcctx.cb.decl_map)
9740 sf = *tcctx.cb.decl_map->get (sf);
9741 src = build_simple_mem_ref_loc (loc, sarg);
9742 src = omp_build_component_ref (src, sf);
9743 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9744 src = build_simple_mem_ref_loc (loc, src);
9746 else
9747 src = decl;
9748 dst = build_simple_mem_ref_loc (loc, arg);
9749 dst = omp_build_component_ref (dst, f);
9750 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9751 append_to_statement_list (t, &list);
9752 break;
9753 case OMP_CLAUSE_PRIVATE:
9754 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9755 break;
9756 decl = OMP_CLAUSE_DECL (c);
9757 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9758 f = (tree) n->value;
9759 if (tcctx.cb.decl_map)
9760 f = *tcctx.cb.decl_map->get (f);
9761 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9762 if (n != NULL)
9764 sf = (tree) n->value;
9765 if (tcctx.cb.decl_map)
9766 sf = *tcctx.cb.decl_map->get (sf);
9767 src = build_simple_mem_ref_loc (loc, sarg);
9768 src = omp_build_component_ref (src, sf);
9769 if (use_pointer_for_field (decl, NULL))
9770 src = build_simple_mem_ref_loc (loc, src);
9772 else
9773 src = decl;
9774 dst = build_simple_mem_ref_loc (loc, arg);
9775 dst = omp_build_component_ref (dst, f);
9776 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9777 append_to_statement_list (t, &list);
9778 break;
9779 default:
9780 break;
9783 /* Last pass: handle VLA firstprivates. */
9784 if (tcctx.cb.decl_map)
9785 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9786 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9788 tree ind, ptr, df;
9790 decl = OMP_CLAUSE_DECL (c);
9791 if (!is_variable_sized (decl))
9792 continue;
9793 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9794 if (n == NULL)
9795 continue;
9796 f = (tree) n->value;
9797 f = *tcctx.cb.decl_map->get (f);
9798 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9799 ind = DECL_VALUE_EXPR (decl);
9800 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9801 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9802 n = splay_tree_lookup (ctx->sfield_map,
9803 (splay_tree_key) TREE_OPERAND (ind, 0));
9804 sf = (tree) n->value;
9805 sf = *tcctx.cb.decl_map->get (sf);
9806 src = build_simple_mem_ref_loc (loc, sarg);
9807 src = omp_build_component_ref (src, sf);
9808 src = build_simple_mem_ref_loc (loc, src);
9809 dst = build_simple_mem_ref_loc (loc, arg);
9810 dst = omp_build_component_ref (dst, f);
9811 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9812 append_to_statement_list (t, &list);
9813 n = splay_tree_lookup (ctx->field_map,
9814 (splay_tree_key) TREE_OPERAND (ind, 0));
9815 df = (tree) n->value;
9816 df = *tcctx.cb.decl_map->get (df);
9817 ptr = build_simple_mem_ref_loc (loc, arg);
9818 ptr = omp_build_component_ref (ptr, df);
9819 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9820 build_fold_addr_expr_loc (loc, dst));
9821 append_to_statement_list (t, &list);
9824 t = build1 (RETURN_EXPR, void_type_node, NULL);
9825 append_to_statement_list (t, &list);
9827 if (tcctx.cb.decl_map)
9828 delete tcctx.cb.decl_map;
9829 pop_gimplify_context (NULL);
9830 BIND_EXPR_BODY (bind) = list;
9831 pop_cfun ();
9834 static void
9835 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9837 tree c, clauses;
9838 gimple g;
9839 size_t n_in = 0, n_out = 0, idx = 2, i;
9841 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9842 OMP_CLAUSE_DEPEND);
9843 gcc_assert (clauses);
9844 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9845 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9846 switch (OMP_CLAUSE_DEPEND_KIND (c))
9848 case OMP_CLAUSE_DEPEND_IN:
9849 n_in++;
9850 break;
9851 case OMP_CLAUSE_DEPEND_OUT:
9852 case OMP_CLAUSE_DEPEND_INOUT:
9853 n_out++;
9854 break;
9855 default:
9856 gcc_unreachable ();
9858 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9859 tree array = create_tmp_var (type, NULL);
9860 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9861 NULL_TREE);
9862 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9863 gimple_seq_add_stmt (iseq, g);
9864 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9865 NULL_TREE);
9866 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9867 gimple_seq_add_stmt (iseq, g);
9868 for (i = 0; i < 2; i++)
9870 if ((i ? n_in : n_out) == 0)
9871 continue;
9872 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9873 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9874 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9876 tree t = OMP_CLAUSE_DECL (c);
9877 t = fold_convert (ptr_type_node, t);
9878 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9879 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9880 NULL_TREE, NULL_TREE);
9881 g = gimple_build_assign (r, t);
9882 gimple_seq_add_stmt (iseq, g);
9885 tree *p = gimple_omp_task_clauses_ptr (stmt);
9886 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9887 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9888 OMP_CLAUSE_CHAIN (c) = *p;
9889 *p = c;
9890 tree clobber = build_constructor (type, NULL);
9891 TREE_THIS_VOLATILE (clobber) = 1;
9892 g = gimple_build_assign (array, clobber);
9893 gimple_seq_add_stmt (oseq, g);
9896 /* Lower the OpenMP parallel or task directive in the current statement
9897 in GSI_P. CTX holds context information for the directive. */
9899 static void
9900 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9902 tree clauses;
9903 tree child_fn, t;
9904 gimple stmt = gsi_stmt (*gsi_p);
9905 gimple par_bind, bind, dep_bind = NULL;
9906 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9907 location_t loc = gimple_location (stmt);
9909 clauses = gimple_omp_taskreg_clauses (stmt);
9910 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9911 par_body = gimple_bind_body (par_bind);
9912 child_fn = ctx->cb.dst_fn;
9913 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9914 && !gimple_omp_parallel_combined_p (stmt))
9916 struct walk_stmt_info wi;
9917 int ws_num = 0;
9919 memset (&wi, 0, sizeof (wi));
9920 wi.info = &ws_num;
9921 wi.val_only = true;
9922 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9923 if (ws_num == 1)
9924 gimple_omp_parallel_set_combined_p (stmt, true);
9926 gimple_seq dep_ilist = NULL;
9927 gimple_seq dep_olist = NULL;
9928 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9929 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9931 push_gimplify_context ();
9932 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9933 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9936 if (ctx->srecord_type)
9937 create_task_copyfn (stmt, ctx);
9939 push_gimplify_context ();
9941 par_olist = NULL;
9942 par_ilist = NULL;
9943 par_rlist = NULL;
9944 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9945 lower_omp (&par_body, ctx);
9946 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9947 lower_reduction_clauses (clauses, &par_rlist, ctx);
9949 /* Declare all the variables created by mapping and the variables
9950 declared in the scope of the parallel body. */
9951 record_vars_into (ctx->block_vars, child_fn);
9952 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9954 if (ctx->record_type)
9956 ctx->sender_decl
9957 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9958 : ctx->record_type, ".omp_data_o");
9959 DECL_NAMELESS (ctx->sender_decl) = 1;
9960 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9961 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9964 olist = NULL;
9965 ilist = NULL;
9966 lower_send_clauses (clauses, &ilist, &olist, ctx);
9967 lower_send_shared_vars (&ilist, &olist, ctx);
9969 if (ctx->record_type)
9971 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9972 TREE_THIS_VOLATILE (clobber) = 1;
9973 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9974 clobber));
9977 /* Once all the expansions are done, sequence all the different
9978 fragments inside gimple_omp_body. */
9980 new_body = NULL;
9982 if (ctx->record_type)
9984 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9985 /* fixup_child_record_type might have changed receiver_decl's type. */
9986 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9987 gimple_seq_add_stmt (&new_body,
9988 gimple_build_assign (ctx->receiver_decl, t));
9991 gimple_seq_add_seq (&new_body, par_ilist);
9992 gimple_seq_add_seq (&new_body, par_body);
9993 gimple_seq_add_seq (&new_body, par_rlist);
9994 if (ctx->cancellable)
9995 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9996 gimple_seq_add_seq (&new_body, par_olist);
9997 new_body = maybe_catch_exception (new_body);
9998 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9999 gimple_omp_set_body (stmt, new_body);
10001 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
10002 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
10003 gimple_bind_add_seq (bind, ilist);
10004 gimple_bind_add_stmt (bind, stmt);
10005 gimple_bind_add_seq (bind, olist);
10007 pop_gimplify_context (NULL);
10009 if (dep_bind)
10011 gimple_bind_add_seq (dep_bind, dep_ilist);
10012 gimple_bind_add_stmt (dep_bind, bind);
10013 gimple_bind_add_seq (dep_bind, dep_olist);
10014 pop_gimplify_context (dep_bind);
10018 /* Lower the OpenMP target directive in the current statement
10019 in GSI_P. CTX holds context information for the directive. */
10021 static void
10022 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10024 tree clauses;
10025 tree child_fn, t, c;
10026 gimple stmt = gsi_stmt (*gsi_p);
10027 gimple tgt_bind = NULL, bind;
10028 gimple_seq tgt_body = NULL, olist, ilist, new_body;
10029 location_t loc = gimple_location (stmt);
10030 int kind = gimple_omp_target_kind (stmt);
10031 unsigned int map_cnt = 0;
10033 clauses = gimple_omp_target_clauses (stmt);
10034 if (kind == GF_OMP_TARGET_KIND_REGION)
10036 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
10037 tgt_body = gimple_bind_body (tgt_bind);
10039 else if (kind == GF_OMP_TARGET_KIND_DATA)
10040 tgt_body = gimple_omp_body (stmt);
10041 child_fn = ctx->cb.dst_fn;
10043 push_gimplify_context ();
10045 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10046 switch (OMP_CLAUSE_CODE (c))
10048 tree var, x;
10050 default:
10051 break;
10052 case OMP_CLAUSE_MAP:
10053 case OMP_CLAUSE_TO:
10054 case OMP_CLAUSE_FROM:
10055 var = OMP_CLAUSE_DECL (c);
10056 if (!DECL_P (var))
10058 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10059 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10060 map_cnt++;
10061 continue;
10064 if (DECL_SIZE (var)
10065 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
10067 tree var2 = DECL_VALUE_EXPR (var);
10068 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
10069 var2 = TREE_OPERAND (var2, 0);
10070 gcc_assert (DECL_P (var2));
10071 var = var2;
10074 if (!maybe_lookup_field (var, ctx))
10075 continue;
10077 if (kind == GF_OMP_TARGET_KIND_REGION)
10079 x = build_receiver_ref (var, true, ctx);
10080 tree new_var = lookup_decl (var, ctx);
10081 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10082 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10083 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10084 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
10085 x = build_simple_mem_ref (x);
10086 SET_DECL_VALUE_EXPR (new_var, x);
10087 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
10089 map_cnt++;
10092 if (kind == GF_OMP_TARGET_KIND_REGION)
10094 target_nesting_level++;
10095 lower_omp (&tgt_body, ctx);
10096 target_nesting_level--;
10098 else if (kind == GF_OMP_TARGET_KIND_DATA)
10099 lower_omp (&tgt_body, ctx);
10101 if (kind == GF_OMP_TARGET_KIND_REGION)
10103 /* Declare all the variables created by mapping and the variables
10104 declared in the scope of the target body. */
10105 record_vars_into (ctx->block_vars, child_fn);
10106 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
10109 olist = NULL;
10110 ilist = NULL;
10111 if (ctx->record_type)
10113 ctx->sender_decl
10114 = create_tmp_var (ctx->record_type, ".omp_data_arr");
10115 DECL_NAMELESS (ctx->sender_decl) = 1;
10116 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10117 t = make_tree_vec (3);
10118 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
10119 TREE_VEC_ELT (t, 1)
10120 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
10121 ".omp_data_sizes");
10122 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
10123 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
10124 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
10125 TREE_VEC_ELT (t, 2)
10126 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
10127 map_cnt),
10128 ".omp_data_kinds");
10129 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
10130 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
10131 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
10132 gimple_omp_target_set_data_arg (stmt, t);
10134 vec<constructor_elt, va_gc> *vsize;
10135 vec<constructor_elt, va_gc> *vkind;
10136 vec_alloc (vsize, map_cnt);
10137 vec_alloc (vkind, map_cnt);
10138 unsigned int map_idx = 0;
10140 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10141 switch (OMP_CLAUSE_CODE (c))
10143 tree ovar, nc;
10145 default:
10146 break;
10147 case OMP_CLAUSE_MAP:
10148 case OMP_CLAUSE_TO:
10149 case OMP_CLAUSE_FROM:
10150 nc = c;
10151 ovar = OMP_CLAUSE_DECL (c);
10152 if (!DECL_P (ovar))
10154 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10155 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10157 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
10158 == get_base_address (ovar));
10159 nc = OMP_CLAUSE_CHAIN (c);
10160 ovar = OMP_CLAUSE_DECL (nc);
10162 else
10164 tree x = build_sender_ref (ovar, ctx);
10165 tree v
10166 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
10167 gimplify_assign (x, v, &ilist);
10168 nc = NULL_TREE;
10171 else
10173 if (DECL_SIZE (ovar)
10174 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
10176 tree ovar2 = DECL_VALUE_EXPR (ovar);
10177 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
10178 ovar2 = TREE_OPERAND (ovar2, 0);
10179 gcc_assert (DECL_P (ovar2));
10180 ovar = ovar2;
10182 if (!maybe_lookup_field (ovar, ctx))
10183 continue;
10186 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
10187 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
10188 talign = DECL_ALIGN_UNIT (ovar);
10189 if (nc)
10191 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
10192 tree x = build_sender_ref (ovar, ctx);
10193 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10194 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10195 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10196 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
10198 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10199 tree avar
10200 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
10201 mark_addressable (avar);
10202 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
10203 talign = DECL_ALIGN_UNIT (avar);
10204 avar = build_fold_addr_expr (avar);
10205 gimplify_assign (x, avar, &ilist);
10207 else if (is_gimple_reg (var))
10209 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10210 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
10211 mark_addressable (avar);
10212 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
10213 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
10214 gimplify_assign (avar, var, &ilist);
10215 avar = build_fold_addr_expr (avar);
10216 gimplify_assign (x, avar, &ilist);
10217 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
10218 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
10219 && !TYPE_READONLY (TREE_TYPE (var)))
10221 x = build_sender_ref (ovar, ctx);
10222 x = build_simple_mem_ref (x);
10223 gimplify_assign (var, x, &olist);
10226 else
10228 var = build_fold_addr_expr (var);
10229 gimplify_assign (x, var, &ilist);
10232 tree s = OMP_CLAUSE_SIZE (c);
10233 if (s == NULL_TREE)
10234 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
10235 s = fold_convert (size_type_node, s);
10236 tree purpose = size_int (map_idx++);
10237 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
10238 if (TREE_CODE (s) != INTEGER_CST)
10239 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
10241 unsigned char tkind = 0;
10242 switch (OMP_CLAUSE_CODE (c))
10244 case OMP_CLAUSE_MAP:
10245 tkind = OMP_CLAUSE_MAP_KIND (c);
10246 break;
10247 case OMP_CLAUSE_TO:
10248 tkind = OMP_CLAUSE_MAP_TO;
10249 break;
10250 case OMP_CLAUSE_FROM:
10251 tkind = OMP_CLAUSE_MAP_FROM;
10252 break;
10253 default:
10254 gcc_unreachable ();
10256 talign = ceil_log2 (talign);
10257 tkind |= talign << 3;
10258 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
10259 build_int_cst (unsigned_char_type_node,
10260 tkind));
10261 if (nc && nc != c)
10262 c = nc;
10265 gcc_assert (map_idx == map_cnt);
10267 DECL_INITIAL (TREE_VEC_ELT (t, 1))
10268 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
10269 DECL_INITIAL (TREE_VEC_ELT (t, 2))
10270 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
10271 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
10273 gimple_seq initlist = NULL;
10274 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
10275 TREE_VEC_ELT (t, 1)),
10276 &initlist, true, NULL_TREE);
10277 gimple_seq_add_seq (&ilist, initlist);
10279 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
10280 NULL);
10281 TREE_THIS_VOLATILE (clobber) = 1;
10282 gimple_seq_add_stmt (&olist,
10283 gimple_build_assign (TREE_VEC_ELT (t, 1),
10284 clobber));
10287 tree clobber = build_constructor (ctx->record_type, NULL);
10288 TREE_THIS_VOLATILE (clobber) = 1;
10289 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10290 clobber));
10293 /* Once all the expansions are done, sequence all the different
10294 fragments inside gimple_omp_body. */
10296 new_body = NULL;
10298 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
10300 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10301 /* fixup_child_record_type might have changed receiver_decl's type. */
10302 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10303 gimple_seq_add_stmt (&new_body,
10304 gimple_build_assign (ctx->receiver_decl, t));
10307 if (kind == GF_OMP_TARGET_KIND_REGION)
10309 gimple_seq_add_seq (&new_body, tgt_body);
10310 new_body = maybe_catch_exception (new_body);
10312 else if (kind == GF_OMP_TARGET_KIND_DATA)
10313 new_body = tgt_body;
10314 if (kind != GF_OMP_TARGET_KIND_UPDATE)
10316 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10317 gimple_omp_set_body (stmt, new_body);
10320 bind = gimple_build_bind (NULL, NULL,
10321 tgt_bind ? gimple_bind_block (tgt_bind)
10322 : NULL_TREE);
10323 gsi_replace (gsi_p, bind, true);
10324 gimple_bind_add_seq (bind, ilist);
10325 gimple_bind_add_stmt (bind, stmt);
10326 gimple_bind_add_seq (bind, olist);
10328 pop_gimplify_context (NULL);
10331 /* Expand code for an OpenMP teams directive. */
10333 static void
10334 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10336 gimple teams_stmt = gsi_stmt (*gsi_p);
10337 push_gimplify_context ();
10339 tree block = make_node (BLOCK);
10340 gimple bind = gimple_build_bind (NULL, NULL, block);
10341 gsi_replace (gsi_p, bind, true);
10342 gimple_seq bind_body = NULL;
10343 gimple_seq dlist = NULL;
10344 gimple_seq olist = NULL;
10346 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10347 OMP_CLAUSE_NUM_TEAMS);
10348 if (num_teams == NULL_TREE)
10349 num_teams = build_int_cst (unsigned_type_node, 0);
10350 else
10352 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
10353 num_teams = fold_convert (unsigned_type_node, num_teams);
10354 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
10356 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10357 OMP_CLAUSE_THREAD_LIMIT);
10358 if (thread_limit == NULL_TREE)
10359 thread_limit = build_int_cst (unsigned_type_node, 0);
10360 else
10362 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10363 thread_limit = fold_convert (unsigned_type_node, thread_limit);
10364 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
10365 fb_rvalue);
10368 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
10369 &bind_body, &dlist, ctx, NULL);
10370 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
10371 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
10372 gimple_seq_add_stmt (&bind_body, teams_stmt);
10374 location_t loc = gimple_location (teams_stmt);
10375 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
10376 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10377 gimple_set_location (call, loc);
10378 gimple_seq_add_stmt (&bind_body, call);
10380 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10381 gimple_omp_set_body (teams_stmt, NULL);
10382 gimple_seq_add_seq (&bind_body, olist);
10383 gimple_seq_add_seq (&bind_body, dlist);
10384 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10385 gimple_bind_set_body (bind, bind_body);
10387 pop_gimplify_context (bind);
10389 gimple_bind_append_vars (bind, ctx->block_vars);
10390 BLOCK_VARS (block) = ctx->block_vars;
10391 if (BLOCK_VARS (block))
10392 TREE_USED (block) = 1;
10396 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10397 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10398 of OpenMP context, but with task_shared_vars set. */
10400 static tree
10401 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10402 void *data)
10404 tree t = *tp;
10406 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10407 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
10408 return t;
10410 if (task_shared_vars
10411 && DECL_P (t)
10412 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10413 return t;
10415 /* If a global variable has been privatized, TREE_CONSTANT on
10416 ADDR_EXPR might be wrong. */
10417 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10418 recompute_tree_invariant_for_addr_expr (t);
10420 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10421 return NULL_TREE;
10424 static void
10425 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10427 gimple stmt = gsi_stmt (*gsi_p);
10428 struct walk_stmt_info wi;
10430 if (gimple_has_location (stmt))
10431 input_location = gimple_location (stmt);
10433 if (task_shared_vars)
10434 memset (&wi, '\0', sizeof (wi));
10436 /* If we have issued syntax errors, avoid doing any heavy lifting.
10437 Just replace the OpenMP directives with a NOP to avoid
10438 confusing RTL expansion. */
10439 if (seen_error () && is_gimple_omp (stmt))
10441 gsi_replace (gsi_p, gimple_build_nop (), true);
10442 return;
10445 switch (gimple_code (stmt))
10447 case GIMPLE_COND:
10448 if ((ctx || task_shared_vars)
10449 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
10450 ctx ? NULL : &wi, NULL)
10451 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
10452 ctx ? NULL : &wi, NULL)))
10453 gimple_regimplify_operands (stmt, gsi_p);
10454 break;
10455 case GIMPLE_CATCH:
10456 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
10457 break;
10458 case GIMPLE_EH_FILTER:
10459 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10460 break;
10461 case GIMPLE_TRY:
10462 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10463 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10464 break;
10465 case GIMPLE_TRANSACTION:
10466 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
10467 break;
10468 case GIMPLE_BIND:
10469 lower_omp (gimple_bind_body_ptr (stmt), ctx);
10470 break;
10471 case GIMPLE_OMP_PARALLEL:
10472 case GIMPLE_OMP_TASK:
10473 ctx = maybe_lookup_ctx (stmt);
10474 gcc_assert (ctx);
10475 if (ctx->cancellable)
10476 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10477 lower_omp_taskreg (gsi_p, ctx);
10478 break;
10479 case GIMPLE_OMP_FOR:
10480 ctx = maybe_lookup_ctx (stmt);
10481 gcc_assert (ctx);
10482 if (ctx->cancellable)
10483 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10484 lower_omp_for (gsi_p, ctx);
10485 break;
10486 case GIMPLE_OMP_SECTIONS:
10487 ctx = maybe_lookup_ctx (stmt);
10488 gcc_assert (ctx);
10489 if (ctx->cancellable)
10490 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10491 lower_omp_sections (gsi_p, ctx);
10492 break;
10493 case GIMPLE_OMP_SINGLE:
10494 ctx = maybe_lookup_ctx (stmt);
10495 gcc_assert (ctx);
10496 lower_omp_single (gsi_p, ctx);
10497 break;
10498 case GIMPLE_OMP_MASTER:
10499 ctx = maybe_lookup_ctx (stmt);
10500 gcc_assert (ctx);
10501 lower_omp_master (gsi_p, ctx);
10502 break;
10503 case GIMPLE_OMP_TASKGROUP:
10504 ctx = maybe_lookup_ctx (stmt);
10505 gcc_assert (ctx);
10506 lower_omp_taskgroup (gsi_p, ctx);
10507 break;
10508 case GIMPLE_OMP_ORDERED:
10509 ctx = maybe_lookup_ctx (stmt);
10510 gcc_assert (ctx);
10511 lower_omp_ordered (gsi_p, ctx);
10512 break;
10513 case GIMPLE_OMP_CRITICAL:
10514 ctx = maybe_lookup_ctx (stmt);
10515 gcc_assert (ctx);
10516 lower_omp_critical (gsi_p, ctx);
10517 break;
10518 case GIMPLE_OMP_ATOMIC_LOAD:
10519 if ((ctx || task_shared_vars)
10520 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
10521 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10522 gimple_regimplify_operands (stmt, gsi_p);
10523 break;
10524 case GIMPLE_OMP_TARGET:
10525 ctx = maybe_lookup_ctx (stmt);
10526 gcc_assert (ctx);
10527 lower_omp_target (gsi_p, ctx);
10528 break;
10529 case GIMPLE_OMP_TEAMS:
10530 ctx = maybe_lookup_ctx (stmt);
10531 gcc_assert (ctx);
10532 lower_omp_teams (gsi_p, ctx);
10533 break;
10534 case GIMPLE_CALL:
10535 tree fndecl;
10536 fndecl = gimple_call_fndecl (stmt);
10537 if (fndecl
10538 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10539 switch (DECL_FUNCTION_CODE (fndecl))
10541 case BUILT_IN_GOMP_BARRIER:
10542 if (ctx == NULL)
10543 break;
10544 /* FALLTHRU */
10545 case BUILT_IN_GOMP_CANCEL:
10546 case BUILT_IN_GOMP_CANCELLATION_POINT:
10547 omp_context *cctx;
10548 cctx = ctx;
10549 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10550 cctx = cctx->outer;
10551 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10552 if (!cctx->cancellable)
10554 if (DECL_FUNCTION_CODE (fndecl)
10555 == BUILT_IN_GOMP_CANCELLATION_POINT)
10557 stmt = gimple_build_nop ();
10558 gsi_replace (gsi_p, stmt, false);
10560 break;
10562 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10564 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10565 gimple_call_set_fndecl (stmt, fndecl);
10566 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10568 tree lhs;
10569 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
10570 gimple_call_set_lhs (stmt, lhs);
10571 tree fallthru_label;
10572 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10573 gimple g;
10574 g = gimple_build_label (fallthru_label);
10575 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10576 g = gimple_build_cond (NE_EXPR, lhs,
10577 fold_convert (TREE_TYPE (lhs),
10578 boolean_false_node),
10579 cctx->cancel_label, fallthru_label);
10580 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10581 break;
10582 default:
10583 break;
10585 /* FALLTHRU */
10586 default:
10587 if ((ctx || task_shared_vars)
10588 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10589 ctx ? NULL : &wi))
10591 /* Just remove clobbers, this should happen only if we have
10592 "privatized" local addressable variables in SIMD regions,
10593 the clobber isn't needed in that case and gimplifying address
10594 of the ARRAY_REF into a pointer and creating MEM_REF based
10595 clobber would create worse code than we get with the clobber
10596 dropped. */
10597 if (gimple_clobber_p (stmt))
10599 gsi_replace (gsi_p, gimple_build_nop (), true);
10600 break;
10602 gimple_regimplify_operands (stmt, gsi_p);
10604 break;
10608 static void
10609 lower_omp (gimple_seq *body, omp_context *ctx)
10611 location_t saved_location = input_location;
10612 gimple_stmt_iterator gsi;
10613 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10614 lower_omp_1 (&gsi, ctx);
10615 /* During gimplification, we have not always invoked fold_stmt
10616 (gimplify.c:maybe_fold_stmt); call it now. */
10617 if (target_nesting_level)
10618 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10619 fold_stmt (&gsi);
10620 input_location = saved_location;
10623 /* Main entry point. */
10625 static unsigned int
10626 execute_lower_omp (void)
10628 gimple_seq body;
10629 int i;
10630 omp_context *ctx;
10632 /* This pass always runs, to provide PROP_gimple_lomp.
10633 But there is nothing to do unless -fopenmp is given. */
10634 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10635 return 0;
10637 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10638 delete_omp_context);
10640 body = gimple_body (current_function_decl);
10641 scan_omp (&body, NULL);
10642 gcc_assert (taskreg_nesting_level == 0);
10643 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
10644 finish_taskreg_scan (ctx);
10645 taskreg_contexts.release ();
10647 if (all_contexts->root)
10649 if (task_shared_vars)
10650 push_gimplify_context ();
10651 lower_omp (&body, NULL);
10652 if (task_shared_vars)
10653 pop_gimplify_context (NULL);
10656 if (all_contexts)
10658 splay_tree_delete (all_contexts);
10659 all_contexts = NULL;
10661 BITMAP_FREE (task_shared_vars);
10662 return 0;
10665 namespace {
10667 const pass_data pass_data_lower_omp =
10669 GIMPLE_PASS, /* type */
10670 "omplower", /* name */
10671 OPTGROUP_NONE, /* optinfo_flags */
10672 TV_NONE, /* tv_id */
10673 PROP_gimple_any, /* properties_required */
10674 PROP_gimple_lomp, /* properties_provided */
10675 0, /* properties_destroyed */
10676 0, /* todo_flags_start */
10677 0, /* todo_flags_finish */
10680 class pass_lower_omp : public gimple_opt_pass
10682 public:
10683 pass_lower_omp (gcc::context *ctxt)
10684 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10687 /* opt_pass methods: */
10688 virtual unsigned int execute (function *) { return execute_lower_omp (); }
10690 }; // class pass_lower_omp
10692 } // anon namespace
10694 gimple_opt_pass *
10695 make_pass_lower_omp (gcc::context *ctxt)
10697 return new pass_lower_omp (ctxt);
10700 /* The following is a utility to diagnose OpenMP structured block violations.
10701 It is not part of the "omplower" pass, as that's invoked too late. It
10702 should be invoked by the respective front ends after gimplification. */
10704 static splay_tree all_labels;
10706 /* Check for mismatched contexts and generate an error if needed. Return
10707 true if an error is detected. */
10709 static bool
10710 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10711 gimple branch_ctx, gimple label_ctx)
10713 if (label_ctx == branch_ctx)
10714 return false;
10718 Previously we kept track of the label's entire context in diagnose_sb_[12]
10719 so we could traverse it and issue a correct "exit" or "enter" error
10720 message upon a structured block violation.
10722 We built the context by building a list with tree_cons'ing, but there is
10723 no easy counterpart in gimple tuples. It seems like far too much work
10724 for issuing exit/enter error messages. If someone really misses the
10725 distinct error message... patches welcome.
10728 #if 0
10729 /* Try to avoid confusing the user by producing and error message
10730 with correct "exit" or "enter" verbiage. We prefer "exit"
10731 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10732 if (branch_ctx == NULL)
10733 exit_p = false;
10734 else
10736 while (label_ctx)
10738 if (TREE_VALUE (label_ctx) == branch_ctx)
10740 exit_p = false;
10741 break;
10743 label_ctx = TREE_CHAIN (label_ctx);
10747 if (exit_p)
10748 error ("invalid exit from OpenMP structured block");
10749 else
10750 error ("invalid entry to OpenMP structured block");
10751 #endif
10753 bool cilkplus_block = false;
10754 if (flag_cilkplus)
10756 if ((branch_ctx
10757 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10758 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10759 || (label_ctx
10760 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10761 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10762 cilkplus_block = true;
10765 /* If it's obvious we have an invalid entry, be specific about the error. */
10766 if (branch_ctx == NULL)
10768 if (cilkplus_block)
10769 error ("invalid entry to Cilk Plus structured block");
10770 else
10771 error ("invalid entry to OpenMP structured block");
10773 else
10775 /* Otherwise, be vague and lazy, but efficient. */
10776 if (cilkplus_block)
10777 error ("invalid branch to/from a Cilk Plus structured block");
10778 else
10779 error ("invalid branch to/from an OpenMP structured block");
10782 gsi_replace (gsi_p, gimple_build_nop (), false);
10783 return true;
10786 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10787 where each label is found. */
10789 static tree
10790 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10791 struct walk_stmt_info *wi)
10793 gimple context = (gimple) wi->info;
10794 gimple inner_context;
10795 gimple stmt = gsi_stmt (*gsi_p);
10797 *handled_ops_p = true;
10799 switch (gimple_code (stmt))
10801 WALK_SUBSTMTS;
10803 case GIMPLE_OMP_PARALLEL:
10804 case GIMPLE_OMP_TASK:
10805 case GIMPLE_OMP_SECTIONS:
10806 case GIMPLE_OMP_SINGLE:
10807 case GIMPLE_OMP_SECTION:
10808 case GIMPLE_OMP_MASTER:
10809 case GIMPLE_OMP_ORDERED:
10810 case GIMPLE_OMP_CRITICAL:
10811 case GIMPLE_OMP_TARGET:
10812 case GIMPLE_OMP_TEAMS:
10813 case GIMPLE_OMP_TASKGROUP:
10814 /* The minimal context here is just the current OMP construct. */
10815 inner_context = stmt;
10816 wi->info = inner_context;
10817 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10818 wi->info = context;
10819 break;
10821 case GIMPLE_OMP_FOR:
10822 inner_context = stmt;
10823 wi->info = inner_context;
10824 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10825 walk them. */
10826 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10827 diagnose_sb_1, NULL, wi);
10828 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10829 wi->info = context;
10830 break;
10832 case GIMPLE_LABEL:
10833 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10834 (splay_tree_value) context);
10835 break;
10837 default:
10838 break;
10841 return NULL_TREE;
10844 /* Pass 2: Check each branch and see if its context differs from that of
10845 the destination label's context. */
10847 static tree
10848 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10849 struct walk_stmt_info *wi)
10851 gimple context = (gimple) wi->info;
10852 splay_tree_node n;
10853 gimple stmt = gsi_stmt (*gsi_p);
10855 *handled_ops_p = true;
10857 switch (gimple_code (stmt))
10859 WALK_SUBSTMTS;
10861 case GIMPLE_OMP_PARALLEL:
10862 case GIMPLE_OMP_TASK:
10863 case GIMPLE_OMP_SECTIONS:
10864 case GIMPLE_OMP_SINGLE:
10865 case GIMPLE_OMP_SECTION:
10866 case GIMPLE_OMP_MASTER:
10867 case GIMPLE_OMP_ORDERED:
10868 case GIMPLE_OMP_CRITICAL:
10869 case GIMPLE_OMP_TARGET:
10870 case GIMPLE_OMP_TEAMS:
10871 case GIMPLE_OMP_TASKGROUP:
10872 wi->info = stmt;
10873 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10874 wi->info = context;
10875 break;
10877 case GIMPLE_OMP_FOR:
10878 wi->info = stmt;
10879 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10880 walk them. */
10881 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10882 diagnose_sb_2, NULL, wi);
10883 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10884 wi->info = context;
10885 break;
10887 case GIMPLE_COND:
10889 tree lab = gimple_cond_true_label (stmt);
10890 if (lab)
10892 n = splay_tree_lookup (all_labels,
10893 (splay_tree_key) lab);
10894 diagnose_sb_0 (gsi_p, context,
10895 n ? (gimple) n->value : NULL);
10897 lab = gimple_cond_false_label (stmt);
10898 if (lab)
10900 n = splay_tree_lookup (all_labels,
10901 (splay_tree_key) lab);
10902 diagnose_sb_0 (gsi_p, context,
10903 n ? (gimple) n->value : NULL);
10906 break;
10908 case GIMPLE_GOTO:
10910 tree lab = gimple_goto_dest (stmt);
10911 if (TREE_CODE (lab) != LABEL_DECL)
10912 break;
10914 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10915 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10917 break;
10919 case GIMPLE_SWITCH:
10921 unsigned int i;
10922 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10924 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10925 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10926 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10927 break;
10930 break;
10932 case GIMPLE_RETURN:
10933 diagnose_sb_0 (gsi_p, context, NULL);
10934 break;
10936 default:
10937 break;
10940 return NULL_TREE;
10943 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10944 codes. */
10945 bool
10946 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
10947 int *region_idx)
10949 gimple last = last_stmt (bb);
10950 enum gimple_code code = gimple_code (last);
10951 struct omp_region *cur_region = *region;
10952 bool fallthru = false;
10954 switch (code)
10956 case GIMPLE_OMP_PARALLEL:
10957 case GIMPLE_OMP_TASK:
10958 case GIMPLE_OMP_FOR:
10959 case GIMPLE_OMP_SINGLE:
10960 case GIMPLE_OMP_TEAMS:
10961 case GIMPLE_OMP_MASTER:
10962 case GIMPLE_OMP_TASKGROUP:
10963 case GIMPLE_OMP_ORDERED:
10964 case GIMPLE_OMP_CRITICAL:
10965 case GIMPLE_OMP_SECTION:
10966 cur_region = new_omp_region (bb, code, cur_region);
10967 fallthru = true;
10968 break;
10970 case GIMPLE_OMP_TARGET:
10971 cur_region = new_omp_region (bb, code, cur_region);
10972 fallthru = true;
10973 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10974 cur_region = cur_region->outer;
10975 break;
10977 case GIMPLE_OMP_SECTIONS:
10978 cur_region = new_omp_region (bb, code, cur_region);
10979 fallthru = true;
10980 break;
10982 case GIMPLE_OMP_SECTIONS_SWITCH:
10983 fallthru = false;
10984 break;
10986 case GIMPLE_OMP_ATOMIC_LOAD:
10987 case GIMPLE_OMP_ATOMIC_STORE:
10988 fallthru = true;
10989 break;
10991 case GIMPLE_OMP_RETURN:
10992 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10993 somewhere other than the next block. This will be
10994 created later. */
10995 cur_region->exit = bb;
10996 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
10997 cur_region = cur_region->outer;
10998 break;
11000 case GIMPLE_OMP_CONTINUE:
11001 cur_region->cont = bb;
11002 switch (cur_region->type)
11004 case GIMPLE_OMP_FOR:
11005 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11006 succs edges as abnormal to prevent splitting
11007 them. */
11008 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
11009 /* Make the loopback edge. */
11010 make_edge (bb, single_succ (cur_region->entry),
11011 EDGE_ABNORMAL);
11013 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11014 corresponds to the case that the body of the loop
11015 is not executed at all. */
11016 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
11017 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
11018 fallthru = false;
11019 break;
11021 case GIMPLE_OMP_SECTIONS:
11022 /* Wire up the edges into and out of the nested sections. */
11024 basic_block switch_bb = single_succ (cur_region->entry);
11026 struct omp_region *i;
11027 for (i = cur_region->inner; i ; i = i->next)
11029 gcc_assert (i->type == GIMPLE_OMP_SECTION);
11030 make_edge (switch_bb, i->entry, 0);
11031 make_edge (i->exit, bb, EDGE_FALLTHRU);
11034 /* Make the loopback edge to the block with
11035 GIMPLE_OMP_SECTIONS_SWITCH. */
11036 make_edge (bb, switch_bb, 0);
11038 /* Make the edge from the switch to exit. */
11039 make_edge (switch_bb, bb->next_bb, 0);
11040 fallthru = false;
11042 break;
11044 default:
11045 gcc_unreachable ();
11047 break;
11049 default:
11050 gcc_unreachable ();
11053 if (*region != cur_region)
11055 *region = cur_region;
11056 if (cur_region)
11057 *region_idx = cur_region->entry->index;
11058 else
11059 *region_idx = 0;
11062 return fallthru;
11065 static unsigned int
11066 diagnose_omp_structured_block_errors (void)
11068 struct walk_stmt_info wi;
11069 gimple_seq body = gimple_body (current_function_decl);
11071 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
11073 memset (&wi, 0, sizeof (wi));
11074 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
11076 memset (&wi, 0, sizeof (wi));
11077 wi.want_locations = true;
11078 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
11080 gimple_set_body (current_function_decl, body);
11082 splay_tree_delete (all_labels);
11083 all_labels = NULL;
11085 return 0;
11088 namespace {
11090 const pass_data pass_data_diagnose_omp_blocks =
11092 GIMPLE_PASS, /* type */
11093 "*diagnose_omp_blocks", /* name */
11094 OPTGROUP_NONE, /* optinfo_flags */
11095 TV_NONE, /* tv_id */
11096 PROP_gimple_any, /* properties_required */
11097 0, /* properties_provided */
11098 0, /* properties_destroyed */
11099 0, /* todo_flags_start */
11100 0, /* todo_flags_finish */
11103 class pass_diagnose_omp_blocks : public gimple_opt_pass
11105 public:
11106 pass_diagnose_omp_blocks (gcc::context *ctxt)
11107 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
11110 /* opt_pass methods: */
11111 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
11112 virtual unsigned int execute (function *)
11114 return diagnose_omp_structured_block_errors ();
11117 }; // class pass_diagnose_omp_blocks
11119 } // anon namespace
11121 gimple_opt_pass *
11122 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
11124 return new pass_diagnose_omp_blocks (ctxt);
11127 /* SIMD clone supporting code. */
11129 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11130 of arguments to reserve space for. */
11132 static struct cgraph_simd_clone *
11133 simd_clone_struct_alloc (int nargs)
11135 struct cgraph_simd_clone *clone_info;
11136 size_t len = (sizeof (struct cgraph_simd_clone)
11137 + nargs * sizeof (struct cgraph_simd_clone_arg));
11138 clone_info = (struct cgraph_simd_clone *)
11139 ggc_internal_cleared_alloc (len);
11140 return clone_info;
11143 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11145 static inline void
11146 simd_clone_struct_copy (struct cgraph_simd_clone *to,
11147 struct cgraph_simd_clone *from)
11149 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
11150 + ((from->nargs - from->inbranch)
11151 * sizeof (struct cgraph_simd_clone_arg))));
11154 /* Return vector of parameter types of function FNDECL. This uses
11155 TYPE_ARG_TYPES if available, otherwise falls back to types of
11156 DECL_ARGUMENTS types. */
11158 vec<tree>
11159 simd_clone_vector_of_formal_parm_types (tree fndecl)
11161 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
11162 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
11163 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
11164 unsigned int i;
11165 tree arg;
11166 FOR_EACH_VEC_ELT (args, i, arg)
11167 args[i] = TREE_TYPE (args[i]);
11168 return args;
11171 /* Given a simd function in NODE, extract the simd specific
11172 information from the OMP clauses passed in CLAUSES, and return
11173 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11174 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11175 otherwise set to FALSE. */
11177 static struct cgraph_simd_clone *
11178 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
11179 bool *inbranch_specified)
11181 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
11182 tree t;
11183 int n;
11184 *inbranch_specified = false;
11186 n = args.length ();
11187 if (n > 0 && args.last () == void_type_node)
11188 n--;
11190 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11191 be cloned have a distinctive artificial label in addition to "omp
11192 declare simd". */
11193 bool cilk_clone
11194 = (flag_cilkplus
11195 && lookup_attribute ("cilk simd function",
11196 DECL_ATTRIBUTES (node->decl)));
11198 /* Allocate one more than needed just in case this is an in-branch
11199 clone which will require a mask argument. */
11200 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
11201 clone_info->nargs = n;
11202 clone_info->cilk_elemental = cilk_clone;
11204 if (!clauses)
11206 args.release ();
11207 return clone_info;
11209 clauses = TREE_VALUE (clauses);
11210 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
11211 return clone_info;
11213 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
11215 switch (OMP_CLAUSE_CODE (t))
11217 case OMP_CLAUSE_INBRANCH:
11218 clone_info->inbranch = 1;
11219 *inbranch_specified = true;
11220 break;
11221 case OMP_CLAUSE_NOTINBRANCH:
11222 clone_info->inbranch = 0;
11223 *inbranch_specified = true;
11224 break;
11225 case OMP_CLAUSE_SIMDLEN:
11226 clone_info->simdlen
11227 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
11228 break;
11229 case OMP_CLAUSE_LINEAR:
11231 tree decl = OMP_CLAUSE_DECL (t);
11232 tree step = OMP_CLAUSE_LINEAR_STEP (t);
11233 int argno = TREE_INT_CST_LOW (decl);
11234 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
11236 clone_info->args[argno].arg_type
11237 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
11238 clone_info->args[argno].linear_step = tree_to_shwi (step);
11239 gcc_assert (clone_info->args[argno].linear_step >= 0
11240 && clone_info->args[argno].linear_step < n);
11242 else
11244 if (POINTER_TYPE_P (args[argno]))
11245 step = fold_convert (ssizetype, step);
11246 if (!tree_fits_shwi_p (step))
11248 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11249 "ignoring large linear step");
11250 args.release ();
11251 return NULL;
11253 else if (integer_zerop (step))
11255 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11256 "ignoring zero linear step");
11257 args.release ();
11258 return NULL;
11260 else
11262 clone_info->args[argno].arg_type
11263 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
11264 clone_info->args[argno].linear_step = tree_to_shwi (step);
11267 break;
11269 case OMP_CLAUSE_UNIFORM:
11271 tree decl = OMP_CLAUSE_DECL (t);
11272 int argno = tree_to_uhwi (decl);
11273 clone_info->args[argno].arg_type
11274 = SIMD_CLONE_ARG_TYPE_UNIFORM;
11275 break;
11277 case OMP_CLAUSE_ALIGNED:
11279 tree decl = OMP_CLAUSE_DECL (t);
11280 int argno = tree_to_uhwi (decl);
11281 clone_info->args[argno].alignment
11282 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
11283 break;
11285 default:
11286 break;
11289 args.release ();
11290 return clone_info;
11293 /* Given a SIMD clone in NODE, calculate the characteristic data
11294 type and return the coresponding type. The characteristic data
11295 type is computed as described in the Intel Vector ABI. */
11297 static tree
11298 simd_clone_compute_base_data_type (struct cgraph_node *node,
11299 struct cgraph_simd_clone *clone_info)
11301 tree type = integer_type_node;
11302 tree fndecl = node->decl;
11304 /* a) For non-void function, the characteristic data type is the
11305 return type. */
11306 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
11307 type = TREE_TYPE (TREE_TYPE (fndecl));
11309 /* b) If the function has any non-uniform, non-linear parameters,
11310 then the characteristic data type is the type of the first
11311 such parameter. */
11312 else
11314 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
11315 for (unsigned int i = 0; i < clone_info->nargs; ++i)
11316 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
11318 type = map[i];
11319 break;
11321 map.release ();
11324 /* c) If the characteristic data type determined by a) or b) above
11325 is struct, union, or class type which is pass-by-value (except
11326 for the type that maps to the built-in complex data type), the
11327 characteristic data type is int. */
11328 if (RECORD_OR_UNION_TYPE_P (type)
11329 && !aggregate_value_p (type, NULL)
11330 && TREE_CODE (type) != COMPLEX_TYPE)
11331 return integer_type_node;
11333 /* d) If none of the above three classes is applicable, the
11334 characteristic data type is int. */
11336 return type;
11338 /* e) For Intel Xeon Phi native and offload compilation, if the
11339 resulting characteristic data type is 8-bit or 16-bit integer
11340 data type, the characteristic data type is int. */
11341 /* Well, we don't handle Xeon Phi yet. */
11344 static tree
11345 simd_clone_mangle (struct cgraph_node *node,
11346 struct cgraph_simd_clone *clone_info)
11348 char vecsize_mangle = clone_info->vecsize_mangle;
11349 char mask = clone_info->inbranch ? 'M' : 'N';
11350 unsigned int simdlen = clone_info->simdlen;
11351 unsigned int n;
11352 pretty_printer pp;
11354 gcc_assert (vecsize_mangle && simdlen);
11356 pp_string (&pp, "_ZGV");
11357 pp_character (&pp, vecsize_mangle);
11358 pp_character (&pp, mask);
11359 pp_decimal_int (&pp, simdlen);
11361 for (n = 0; n < clone_info->nargs; ++n)
11363 struct cgraph_simd_clone_arg arg = clone_info->args[n];
11365 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
11366 pp_character (&pp, 'u');
11367 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11369 gcc_assert (arg.linear_step != 0);
11370 pp_character (&pp, 'l');
11371 if (arg.linear_step > 1)
11372 pp_unsigned_wide_integer (&pp, arg.linear_step);
11373 else if (arg.linear_step < 0)
11375 pp_character (&pp, 'n');
11376 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
11377 arg.linear_step));
11380 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11382 pp_character (&pp, 's');
11383 pp_unsigned_wide_integer (&pp, arg.linear_step);
11385 else
11386 pp_character (&pp, 'v');
11387 if (arg.alignment)
11389 pp_character (&pp, 'a');
11390 pp_decimal_int (&pp, arg.alignment);
11394 pp_underscore (&pp);
11395 pp_string (&pp,
11396 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11397 const char *str = pp_formatted_text (&pp);
11399 /* If there already is a SIMD clone with the same mangled name, don't
11400 add another one. This can happen e.g. for
11401 #pragma omp declare simd
11402 #pragma omp declare simd simdlen(8)
11403 int foo (int, int);
11404 if the simdlen is assumed to be 8 for the first one, etc. */
11405 for (struct cgraph_node *clone = node->simd_clones; clone;
11406 clone = clone->simdclone->next_clone)
11407 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11408 str) == 0)
11409 return NULL_TREE;
11411 return get_identifier (str);
11414 /* Create a simd clone of OLD_NODE and return it. */
11416 static struct cgraph_node *
11417 simd_clone_create (struct cgraph_node *old_node)
11419 struct cgraph_node *new_node;
11420 if (old_node->definition)
11422 if (!old_node->has_gimple_body_p ())
11423 return NULL;
11424 old_node->get_body ();
11425 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
11426 false, NULL, NULL,
11427 "simdclone");
11429 else
11431 tree old_decl = old_node->decl;
11432 tree new_decl = copy_node (old_node->decl);
11433 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11434 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11435 SET_DECL_RTL (new_decl, NULL);
11436 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11437 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11438 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
11439 symtab->call_cgraph_insertion_hooks (new_node);
11441 if (new_node == NULL)
11442 return new_node;
11444 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11446 /* The function cgraph_function_versioning () will force the new
11447 symbol local. Undo this, and inherit external visability from
11448 the old node. */
11449 new_node->local.local = old_node->local.local;
11450 new_node->externally_visible = old_node->externally_visible;
11452 return new_node;
11455 /* Adjust the return type of the given function to its appropriate
11456 vector counterpart. Returns a simd array to be used throughout the
11457 function as a return value. */
11459 static tree
11460 simd_clone_adjust_return_type (struct cgraph_node *node)
11462 tree fndecl = node->decl;
11463 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11464 unsigned int veclen;
11465 tree t;
11467 /* Adjust the function return type. */
11468 if (orig_rettype == void_type_node)
11469 return NULL_TREE;
11470 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11471 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11472 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11473 veclen = node->simdclone->vecsize_int;
11474 else
11475 veclen = node->simdclone->vecsize_float;
11476 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11477 if (veclen > node->simdclone->simdlen)
11478 veclen = node->simdclone->simdlen;
11479 if (veclen == node->simdclone->simdlen)
11480 TREE_TYPE (TREE_TYPE (fndecl))
11481 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11482 node->simdclone->simdlen);
11483 else
11485 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11486 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11487 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11489 if (!node->definition)
11490 return NULL_TREE;
11492 t = DECL_RESULT (fndecl);
11493 /* Adjust the DECL_RESULT. */
11494 gcc_assert (TREE_TYPE (t) != void_type_node);
11495 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11496 relayout_decl (t);
11498 tree atype = build_array_type_nelts (orig_rettype,
11499 node->simdclone->simdlen);
11500 if (veclen != node->simdclone->simdlen)
11501 return build1 (VIEW_CONVERT_EXPR, atype, t);
11503 /* Set up a SIMD array to use as the return value. */
11504 tree retval = create_tmp_var_raw (atype, "retval");
11505 gimple_add_tmp_var (retval);
11506 return retval;
11509 /* Each vector argument has a corresponding array to be used locally
11510 as part of the eventual loop. Create such temporary array and
11511 return it.
11513 PREFIX is the prefix to be used for the temporary.
11515 TYPE is the inner element type.
11517 SIMDLEN is the number of elements. */
11519 static tree
11520 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11522 tree atype = build_array_type_nelts (type, simdlen);
11523 tree avar = create_tmp_var_raw (atype, prefix);
11524 gimple_add_tmp_var (avar);
11525 return avar;
11528 /* Modify the function argument types to their corresponding vector
11529 counterparts if appropriate. Also, create one array for each simd
11530 argument to be used locally when using the function arguments as
11531 part of the loop.
11533 NODE is the function whose arguments are to be adjusted.
11535 Returns an adjustment vector that will be filled describing how the
11536 argument types will be adjusted. */
11538 static ipa_parm_adjustment_vec
11539 simd_clone_adjust_argument_types (struct cgraph_node *node)
11541 vec<tree> args;
11542 ipa_parm_adjustment_vec adjustments;
11544 if (node->definition)
11545 args = ipa_get_vector_of_formal_parms (node->decl);
11546 else
11547 args = simd_clone_vector_of_formal_parm_types (node->decl);
11548 adjustments.create (args.length ());
11549 unsigned i, j, veclen;
11550 struct ipa_parm_adjustment adj;
11551 for (i = 0; i < node->simdclone->nargs; ++i)
11553 memset (&adj, 0, sizeof (adj));
11554 tree parm = args[i];
11555 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11556 adj.base_index = i;
11557 adj.base = parm;
11559 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11560 node->simdclone->args[i].orig_type = parm_type;
11562 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11564 /* No adjustment necessary for scalar arguments. */
11565 adj.op = IPA_PARM_OP_COPY;
11567 else
11569 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11570 veclen = node->simdclone->vecsize_int;
11571 else
11572 veclen = node->simdclone->vecsize_float;
11573 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11574 if (veclen > node->simdclone->simdlen)
11575 veclen = node->simdclone->simdlen;
11576 adj.arg_prefix = "simd";
11577 adj.type = build_vector_type (parm_type, veclen);
11578 node->simdclone->args[i].vector_type = adj.type;
11579 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11581 adjustments.safe_push (adj);
11582 if (j == veclen)
11584 memset (&adj, 0, sizeof (adj));
11585 adj.op = IPA_PARM_OP_NEW;
11586 adj.arg_prefix = "simd";
11587 adj.base_index = i;
11588 adj.type = node->simdclone->args[i].vector_type;
11592 if (node->definition)
11593 node->simdclone->args[i].simd_array
11594 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11595 parm_type, node->simdclone->simdlen);
11597 adjustments.safe_push (adj);
11600 if (node->simdclone->inbranch)
11602 tree base_type
11603 = simd_clone_compute_base_data_type (node->simdclone->origin,
11604 node->simdclone);
11606 memset (&adj, 0, sizeof (adj));
11607 adj.op = IPA_PARM_OP_NEW;
11608 adj.arg_prefix = "mask";
11610 adj.base_index = i;
11611 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11612 veclen = node->simdclone->vecsize_int;
11613 else
11614 veclen = node->simdclone->vecsize_float;
11615 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11616 if (veclen > node->simdclone->simdlen)
11617 veclen = node->simdclone->simdlen;
11618 adj.type = build_vector_type (base_type, veclen);
11619 adjustments.safe_push (adj);
11621 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11622 adjustments.safe_push (adj);
11624 /* We have previously allocated one extra entry for the mask. Use
11625 it and fill it. */
11626 struct cgraph_simd_clone *sc = node->simdclone;
11627 sc->nargs++;
11628 if (node->definition)
11630 sc->args[i].orig_arg
11631 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11632 sc->args[i].simd_array
11633 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11635 sc->args[i].orig_type = base_type;
11636 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11639 if (node->definition)
11640 ipa_modify_formal_parameters (node->decl, adjustments);
11641 else
11643 tree new_arg_types = NULL_TREE, new_reversed;
11644 bool last_parm_void = false;
11645 if (args.length () > 0 && args.last () == void_type_node)
11646 last_parm_void = true;
11648 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11649 j = adjustments.length ();
11650 for (i = 0; i < j; i++)
11652 struct ipa_parm_adjustment *adj = &adjustments[i];
11653 tree ptype;
11654 if (adj->op == IPA_PARM_OP_COPY)
11655 ptype = args[adj->base_index];
11656 else
11657 ptype = adj->type;
11658 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11660 new_reversed = nreverse (new_arg_types);
11661 if (last_parm_void)
11663 if (new_reversed)
11664 TREE_CHAIN (new_arg_types) = void_list_node;
11665 else
11666 new_reversed = void_list_node;
11669 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11670 TYPE_ARG_TYPES (new_type) = new_reversed;
11671 TREE_TYPE (node->decl) = new_type;
11673 adjustments.release ();
11675 args.release ();
11676 return adjustments;
11679 /* Initialize and copy the function arguments in NODE to their
11680 corresponding local simd arrays. Returns a fresh gimple_seq with
11681 the instruction sequence generated. */
11683 static gimple_seq
11684 simd_clone_init_simd_arrays (struct cgraph_node *node,
11685 ipa_parm_adjustment_vec adjustments)
11687 gimple_seq seq = NULL;
11688 unsigned i = 0, j = 0, k;
11690 for (tree arg = DECL_ARGUMENTS (node->decl);
11691 arg;
11692 arg = DECL_CHAIN (arg), i++, j++)
11694 if (adjustments[j].op == IPA_PARM_OP_COPY)
11695 continue;
11697 node->simdclone->args[i].vector_arg = arg;
11699 tree array = node->simdclone->args[i].simd_array;
11700 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11702 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11703 tree ptr = build_fold_addr_expr (array);
11704 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11705 build_int_cst (ptype, 0));
11706 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11707 gimplify_and_add (t, &seq);
11709 else
11711 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11712 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11713 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11715 tree ptr = build_fold_addr_expr (array);
11716 int elemsize;
11717 if (k)
11719 arg = DECL_CHAIN (arg);
11720 j++;
11722 elemsize
11723 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11724 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11725 build_int_cst (ptype, k * elemsize));
11726 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11727 gimplify_and_add (t, &seq);
11731 return seq;
11734 /* Callback info for ipa_simd_modify_stmt_ops below. */
11736 struct modify_stmt_info {
11737 ipa_parm_adjustment_vec adjustments;
11738 gimple stmt;
11739 /* True if the parent statement was modified by
11740 ipa_simd_modify_stmt_ops. */
11741 bool modified;
11744 /* Callback for walk_gimple_op.
11746 Adjust operands from a given statement as specified in the
11747 adjustments vector in the callback data. */
11749 static tree
11750 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11752 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11753 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11754 tree *orig_tp = tp;
11755 if (TREE_CODE (*tp) == ADDR_EXPR)
11756 tp = &TREE_OPERAND (*tp, 0);
11757 struct ipa_parm_adjustment *cand = NULL;
11758 if (TREE_CODE (*tp) == PARM_DECL)
11759 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11760 else
11762 if (TYPE_P (*tp))
11763 *walk_subtrees = 0;
11766 tree repl = NULL_TREE;
11767 if (cand)
11768 repl = unshare_expr (cand->new_decl);
11769 else
11771 if (tp != orig_tp)
11773 *walk_subtrees = 0;
11774 bool modified = info->modified;
11775 info->modified = false;
11776 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11777 if (!info->modified)
11779 info->modified = modified;
11780 return NULL_TREE;
11782 info->modified = modified;
11783 repl = *tp;
11785 else
11786 return NULL_TREE;
11789 if (tp != orig_tp)
11791 repl = build_fold_addr_expr (repl);
11792 gimple stmt;
11793 if (is_gimple_debug (info->stmt))
11795 tree vexpr = make_node (DEBUG_EXPR_DECL);
11796 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
11797 DECL_ARTIFICIAL (vexpr) = 1;
11798 TREE_TYPE (vexpr) = TREE_TYPE (repl);
11799 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
11800 repl = vexpr;
11802 else
11804 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl),
11805 NULL), repl);
11806 repl = gimple_assign_lhs (stmt);
11808 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11809 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11810 *orig_tp = repl;
11812 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11814 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11815 *tp = vce;
11817 else
11818 *tp = repl;
11820 info->modified = true;
11821 return NULL_TREE;
11824 /* Traverse the function body and perform all modifications as
11825 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11826 modified such that the replacement/reduction value will now be an
11827 offset into the corresponding simd_array.
11829 This function will replace all function argument uses with their
11830 corresponding simd array elements, and ajust the return values
11831 accordingly. */
11833 static void
11834 ipa_simd_modify_function_body (struct cgraph_node *node,
11835 ipa_parm_adjustment_vec adjustments,
11836 tree retval_array, tree iter)
11838 basic_block bb;
11839 unsigned int i, j, l;
11841 /* Re-use the adjustments array, but this time use it to replace
11842 every function argument use to an offset into the corresponding
11843 simd_array. */
11844 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11846 if (!node->simdclone->args[i].vector_arg)
11847 continue;
11849 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11850 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11851 adjustments[j].new_decl
11852 = build4 (ARRAY_REF,
11853 basetype,
11854 node->simdclone->args[i].simd_array,
11855 iter,
11856 NULL_TREE, NULL_TREE);
11857 if (adjustments[j].op == IPA_PARM_OP_NONE
11858 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11859 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11862 l = adjustments.length ();
11863 for (i = 1; i < num_ssa_names; i++)
11865 tree name = ssa_name (i);
11866 if (name
11867 && SSA_NAME_VAR (name)
11868 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11870 for (j = 0; j < l; j++)
11871 if (SSA_NAME_VAR (name) == adjustments[j].base
11872 && adjustments[j].new_decl)
11874 tree base_var;
11875 if (adjustments[j].new_ssa_base == NULL_TREE)
11877 base_var
11878 = copy_var_decl (adjustments[j].base,
11879 DECL_NAME (adjustments[j].base),
11880 TREE_TYPE (adjustments[j].base));
11881 adjustments[j].new_ssa_base = base_var;
11883 else
11884 base_var = adjustments[j].new_ssa_base;
11885 if (SSA_NAME_IS_DEFAULT_DEF (name))
11887 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11888 gimple_stmt_iterator gsi = gsi_after_labels (bb);
11889 tree new_decl = unshare_expr (adjustments[j].new_decl);
11890 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
11891 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11892 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
11893 gimple stmt = gimple_build_assign (name, new_decl);
11894 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11896 else
11897 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11902 struct modify_stmt_info info;
11903 info.adjustments = adjustments;
11905 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
11907 gimple_stmt_iterator gsi;
11909 gsi = gsi_start_bb (bb);
11910 while (!gsi_end_p (gsi))
11912 gimple stmt = gsi_stmt (gsi);
11913 info.stmt = stmt;
11914 struct walk_stmt_info wi;
11916 memset (&wi, 0, sizeof (wi));
11917 info.modified = false;
11918 wi.info = &info;
11919 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
11921 if (gimple_code (stmt) == GIMPLE_RETURN)
11923 tree retval = gimple_return_retval (stmt);
11924 if (!retval)
11926 gsi_remove (&gsi, true);
11927 continue;
11930 /* Replace `return foo' with `retval_array[iter] = foo'. */
11931 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
11932 retval_array, iter, NULL, NULL);
11933 stmt = gimple_build_assign (ref, retval);
11934 gsi_replace (&gsi, stmt, true);
11935 info.modified = true;
11938 if (info.modified)
11940 update_stmt (stmt);
11941 if (maybe_clean_eh_stmt (stmt))
11942 gimple_purge_dead_eh_edges (gimple_bb (stmt));
11944 gsi_next (&gsi);
11949 /* Adjust the argument types in NODE to their appropriate vector
11950 counterparts. */
11952 static void
11953 simd_clone_adjust (struct cgraph_node *node)
11955 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
11957 targetm.simd_clone.adjust (node);
11959 tree retval = simd_clone_adjust_return_type (node);
11960 ipa_parm_adjustment_vec adjustments
11961 = simd_clone_adjust_argument_types (node);
11963 push_gimplify_context ();
11965 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
11967 /* Adjust all uses of vector arguments accordingly. Adjust all
11968 return values accordingly. */
11969 tree iter = create_tmp_var (unsigned_type_node, "iter");
11970 tree iter1 = make_ssa_name (iter, NULL);
11971 tree iter2 = make_ssa_name (iter, NULL);
11972 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
11974 /* Initialize the iteration variable. */
11975 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11976 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
11977 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
11978 /* Insert the SIMD array and iv initialization at function
11979 entry. */
11980 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
11982 pop_gimplify_context (NULL);
11984 /* Create a new BB right before the original exit BB, to hold the
11985 iteration increment and the condition/branch. */
11986 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
11987 basic_block incr_bb = create_empty_bb (orig_exit);
11988 add_bb_to_loop (incr_bb, body_bb->loop_father);
11989 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11990 flag. Set it now to be a FALLTHRU_EDGE. */
11991 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
11992 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
11993 for (unsigned i = 0;
11994 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
11996 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
11997 redirect_edge_succ (e, incr_bb);
11999 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
12000 e->probability = REG_BR_PROB_BASE;
12001 gsi = gsi_last_bb (incr_bb);
12002 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
12003 build_int_cst (unsigned_type_node,
12004 1));
12005 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12007 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12008 struct loop *loop = alloc_loop ();
12009 cfun->has_force_vectorize_loops = true;
12010 loop->safelen = node->simdclone->simdlen;
12011 loop->force_vectorize = true;
12012 loop->header = body_bb;
12014 /* Branch around the body if the mask applies. */
12015 if (node->simdclone->inbranch)
12017 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
12018 tree mask_array
12019 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
12020 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
12021 tree aref = build4 (ARRAY_REF,
12022 TREE_TYPE (TREE_TYPE (mask_array)),
12023 mask_array, iter1,
12024 NULL, NULL);
12025 g = gimple_build_assign (mask, aref);
12026 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12027 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
12028 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
12030 aref = build1 (VIEW_CONVERT_EXPR,
12031 build_nonstandard_integer_type (bitsize, 0), mask);
12032 mask = make_ssa_name (TREE_TYPE (aref), NULL);
12033 g = gimple_build_assign (mask, aref);
12034 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12037 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
12038 NULL, NULL);
12039 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12040 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
12041 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
12044 /* Generate the condition. */
12045 g = gimple_build_cond (LT_EXPR,
12046 iter2,
12047 build_int_cst (unsigned_type_node,
12048 node->simdclone->simdlen),
12049 NULL, NULL);
12050 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12051 e = split_block (incr_bb, gsi_stmt (gsi));
12052 basic_block latch_bb = e->dest;
12053 basic_block new_exit_bb;
12054 new_exit_bb = split_block (latch_bb, NULL)->dest;
12055 loop->latch = latch_bb;
12057 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
12059 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
12060 /* The successor of incr_bb is already pointing to latch_bb; just
12061 change the flags.
12062 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12063 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
12065 gimple phi = create_phi_node (iter1, body_bb);
12066 edge preheader_edge = find_edge (entry_bb, body_bb);
12067 edge latch_edge = single_succ_edge (latch_bb);
12068 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
12069 UNKNOWN_LOCATION);
12070 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12072 /* Generate the new return. */
12073 gsi = gsi_last_bb (new_exit_bb);
12074 if (retval
12075 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
12076 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
12077 retval = TREE_OPERAND (retval, 0);
12078 else if (retval)
12080 retval = build1 (VIEW_CONVERT_EXPR,
12081 TREE_TYPE (TREE_TYPE (node->decl)),
12082 retval);
12083 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
12084 false, GSI_CONTINUE_LINKING);
12086 g = gimple_build_return (retval);
12087 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12089 /* Handle aligned clauses by replacing default defs of the aligned
12090 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12091 lhs. Handle linear by adding PHIs. */
12092 for (unsigned i = 0; i < node->simdclone->nargs; i++)
12093 if (node->simdclone->args[i].alignment
12094 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
12095 && (node->simdclone->args[i].alignment
12096 & (node->simdclone->args[i].alignment - 1)) == 0
12097 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
12098 == POINTER_TYPE)
12100 unsigned int alignment = node->simdclone->args[i].alignment;
12101 tree orig_arg = node->simdclone->args[i].orig_arg;
12102 tree def = ssa_default_def (cfun, orig_arg);
12103 if (def && !has_zero_uses (def))
12105 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
12106 gimple_seq seq = NULL;
12107 bool need_cvt = false;
12108 gimple call
12109 = gimple_build_call (fn, 2, def, size_int (alignment));
12110 g = call;
12111 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
12112 ptr_type_node))
12113 need_cvt = true;
12114 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
12115 gimple_call_set_lhs (g, t);
12116 gimple_seq_add_stmt_without_update (&seq, g);
12117 if (need_cvt)
12119 t = make_ssa_name (orig_arg, NULL);
12120 g = gimple_build_assign_with_ops (NOP_EXPR, t,
12121 gimple_call_lhs (g),
12122 NULL_TREE);
12123 gimple_seq_add_stmt_without_update (&seq, g);
12125 gsi_insert_seq_on_edge_immediate
12126 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
12128 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12129 int freq = compute_call_stmt_bb_frequency (current_function_decl,
12130 entry_bb);
12131 node->create_edge (cgraph_node::get_create (fn),
12132 call, entry_bb->count, freq);
12134 imm_use_iterator iter;
12135 use_operand_p use_p;
12136 gimple use_stmt;
12137 tree repl = gimple_get_lhs (g);
12138 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12139 if (is_gimple_debug (use_stmt) || use_stmt == call)
12140 continue;
12141 else
12142 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12143 SET_USE (use_p, repl);
12146 else if (node->simdclone->args[i].arg_type
12147 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12149 tree orig_arg = node->simdclone->args[i].orig_arg;
12150 tree def = ssa_default_def (cfun, orig_arg);
12151 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12152 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
12153 if (def && !has_zero_uses (def))
12155 iter1 = make_ssa_name (orig_arg, NULL);
12156 iter2 = make_ssa_name (orig_arg, NULL);
12157 phi = create_phi_node (iter1, body_bb);
12158 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
12159 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12160 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12161 ? PLUS_EXPR : POINTER_PLUS_EXPR;
12162 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12163 ? TREE_TYPE (orig_arg) : sizetype;
12164 tree addcst
12165 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
12166 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
12167 gsi = gsi_last_bb (incr_bb);
12168 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12170 imm_use_iterator iter;
12171 use_operand_p use_p;
12172 gimple use_stmt;
12173 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12174 if (use_stmt == phi)
12175 continue;
12176 else
12177 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12178 SET_USE (use_p, iter1);
12182 calculate_dominance_info (CDI_DOMINATORS);
12183 add_loop (loop, loop->header->loop_father);
12184 update_ssa (TODO_update_ssa);
12186 pop_cfun ();
12189 /* If the function in NODE is tagged as an elemental SIMD function,
12190 create the appropriate SIMD clones. */
12192 static void
12193 expand_simd_clones (struct cgraph_node *node)
12195 tree attr = lookup_attribute ("omp declare simd",
12196 DECL_ATTRIBUTES (node->decl));
12197 if (attr == NULL_TREE
12198 || node->global.inlined_to
12199 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
12200 return;
12202 /* Ignore
12203 #pragma omp declare simd
12204 extern int foo ();
12205 in C, there we don't know the argument types at all. */
12206 if (!node->definition
12207 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
12208 return;
12212 /* Start with parsing the "omp declare simd" attribute(s). */
12213 bool inbranch_clause_specified;
12214 struct cgraph_simd_clone *clone_info
12215 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
12216 &inbranch_clause_specified);
12217 if (clone_info == NULL)
12218 continue;
12220 int orig_simdlen = clone_info->simdlen;
12221 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
12222 /* The target can return 0 (no simd clones should be created),
12223 1 (just one ISA of simd clones should be created) or higher
12224 count of ISA variants. In that case, clone_info is initialized
12225 for the first ISA variant. */
12226 int count
12227 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
12228 base_type, 0);
12229 if (count == 0)
12230 continue;
12232 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12233 also create one inbranch and one !inbranch clone of it. */
12234 for (int i = 0; i < count * 2; i++)
12236 struct cgraph_simd_clone *clone = clone_info;
12237 if (inbranch_clause_specified && (i & 1) != 0)
12238 continue;
12240 if (i != 0)
12242 clone = simd_clone_struct_alloc (clone_info->nargs
12243 + ((i & 1) != 0));
12244 simd_clone_struct_copy (clone, clone_info);
12245 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12246 and simd_clone_adjust_argument_types did to the first
12247 clone's info. */
12248 clone->nargs -= clone_info->inbranch;
12249 clone->simdlen = orig_simdlen;
12250 /* And call the target hook again to get the right ISA. */
12251 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
12252 base_type,
12253 i / 2);
12254 if ((i & 1) != 0)
12255 clone->inbranch = 1;
12258 /* simd_clone_mangle might fail if such a clone has been created
12259 already. */
12260 tree id = simd_clone_mangle (node, clone);
12261 if (id == NULL_TREE)
12262 continue;
12264 /* Only when we are sure we want to create the clone actually
12265 clone the function (or definitions) or create another
12266 extern FUNCTION_DECL (for prototypes without definitions). */
12267 struct cgraph_node *n = simd_clone_create (node);
12268 if (n == NULL)
12269 continue;
12271 n->simdclone = clone;
12272 clone->origin = node;
12273 clone->next_clone = NULL;
12274 if (node->simd_clones == NULL)
12276 clone->prev_clone = n;
12277 node->simd_clones = n;
12279 else
12281 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
12282 clone->prev_clone->simdclone->next_clone = n;
12283 node->simd_clones->simdclone->prev_clone = n;
12285 symtab->change_decl_assembler_name (n->decl, id);
12286 /* And finally adjust the return type, parameters and for
12287 definitions also function body. */
12288 if (node->definition)
12289 simd_clone_adjust (n);
12290 else
12292 simd_clone_adjust_return_type (n);
12293 simd_clone_adjust_argument_types (n);
12297 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
12300 /* Entry point for IPA simd clone creation pass. */
12302 static unsigned int
12303 ipa_omp_simd_clone (void)
12305 struct cgraph_node *node;
12306 FOR_EACH_FUNCTION (node)
12307 expand_simd_clones (node);
12308 return 0;
12311 namespace {
12313 const pass_data pass_data_omp_simd_clone =
12315 SIMPLE_IPA_PASS, /* type */
12316 "simdclone", /* name */
12317 OPTGROUP_NONE, /* optinfo_flags */
12318 TV_NONE, /* tv_id */
12319 ( PROP_ssa | PROP_cfg ), /* properties_required */
12320 0, /* properties_provided */
12321 0, /* properties_destroyed */
12322 0, /* todo_flags_start */
12323 0, /* todo_flags_finish */
12326 class pass_omp_simd_clone : public simple_ipa_opt_pass
12328 public:
12329 pass_omp_simd_clone(gcc::context *ctxt)
12330 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
12333 /* opt_pass methods: */
12334 virtual bool gate (function *);
12335 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
12338 bool
12339 pass_omp_simd_clone::gate (function *)
12341 return ((flag_openmp || flag_openmp_simd
12342 || flag_cilkplus
12343 || (in_lto_p && !flag_wpa))
12344 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
12347 } // anon namespace
12349 simple_ipa_opt_pass *
12350 make_pass_omp_simd_clone (gcc::context *ctxt)
12352 return new pass_omp_simd_clone (ctxt);
12355 #include "gt-omp-low.h"