PR c/60784
[official-gcc.git] / gcc / omp-low.c
blob28b2c6aea8ca3a92ba7337c9b267c8be57a2e822
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 "pointer-set.h"
33 #include "basic-block.h"
34 #include "tree-ssa-alias.h"
35 #include "internal-fn.h"
36 #include "gimple-fold.h"
37 #include "gimple-expr.h"
38 #include "is-a.h"
39 #include "gimple.h"
40 #include "gimplify.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "gimple-walk.h"
44 #include "tree-iterator.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47 #include "diagnostic-core.h"
48 #include "gimple-ssa.h"
49 #include "cgraph.h"
50 #include "tree-cfg.h"
51 #include "tree-phinodes.h"
52 #include "ssa-iterators.h"
53 #include "tree-ssanames.h"
54 #include "tree-into-ssa.h"
55 #include "expr.h"
56 #include "tree-dfa.h"
57 #include "tree-ssa.h"
58 #include "flags.h"
59 #include "function.h"
60 #include "expr.h"
61 #include "tree-pass.h"
62 #include "except.h"
63 #include "splay-tree.h"
64 #include "optabs.h"
65 #include "cfgloop.h"
66 #include "target.h"
67 #include "omp-low.h"
68 #include "gimple-low.h"
69 #include "tree-cfgcleanup.h"
70 #include "pretty-print.h"
71 #include "ipa-prop.h"
72 #include "tree-nested.h"
73 #include "tree-eh.h"
76 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
77 phases. The first phase scans the function looking for OMP statements
78 and then for variables that must be replaced to satisfy data sharing
79 clauses. The second phase expands code for the constructs, as well as
80 re-gimplifying things when variables have been replaced with complex
81 expressions.
83 Final code generation is done by pass_expand_omp. The flowgraph is
84 scanned for parallel regions which are then moved to a new
85 function, to be invoked by the thread library. */
87 /* Parallel region information. Every parallel and workshare
88 directive is enclosed between two markers, the OMP_* directive
89 and a corresponding OMP_RETURN statement. */
91 struct omp_region
93 /* The enclosing region. */
94 struct omp_region *outer;
96 /* First child region. */
97 struct omp_region *inner;
99 /* Next peer region. */
100 struct omp_region *next;
102 /* Block containing the omp directive as its last stmt. */
103 basic_block entry;
105 /* Block containing the OMP_RETURN as its last stmt. */
106 basic_block exit;
108 /* Block containing the OMP_CONTINUE as its last stmt. */
109 basic_block cont;
111 /* If this is a combined parallel+workshare region, this is a list
112 of additional arguments needed by the combined parallel+workshare
113 library call. */
114 vec<tree, va_gc> *ws_args;
116 /* The code for the omp directive of this region. */
117 enum gimple_code type;
119 /* Schedule kind, only used for OMP_FOR type regions. */
120 enum omp_clause_schedule_kind sched_kind;
122 /* True if this is a combined parallel+workshare region. */
123 bool is_combined_parallel;
126 /* Context structure. Used to store information about each parallel
127 directive in the code. */
129 typedef struct omp_context
131 /* This field must be at the beginning, as we do "inheritance": Some
132 callback functions for tree-inline.c (e.g., omp_copy_decl)
133 receive a copy_body_data pointer that is up-casted to an
134 omp_context pointer. */
135 copy_body_data cb;
137 /* The tree of contexts corresponding to the encountered constructs. */
138 struct omp_context *outer;
139 gimple stmt;
141 /* Map variables to fields in a structure that allows communication
142 between sending and receiving threads. */
143 splay_tree field_map;
144 tree record_type;
145 tree sender_decl;
146 tree receiver_decl;
148 /* These are used just by task contexts, if task firstprivate fn is
149 needed. srecord_type is used to communicate from the thread
150 that encountered the task construct to task firstprivate fn,
151 record_type is allocated by GOMP_task, initialized by task firstprivate
152 fn and passed to the task body fn. */
153 splay_tree sfield_map;
154 tree srecord_type;
156 /* A chain of variables to add to the top-level block surrounding the
157 construct. In the case of a parallel, this is in the child function. */
158 tree block_vars;
160 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
161 barriers should jump to during omplower pass. */
162 tree cancel_label;
164 /* What to do with variables with implicitly determined sharing
165 attributes. */
166 enum omp_clause_default_kind default_kind;
168 /* Nesting depth of this context. Used to beautify error messages re
169 invalid gotos. The outermost ctx is depth 1, with depth 0 being
170 reserved for the main body of the function. */
171 int depth;
173 /* True if this parallel directive is nested within another. */
174 bool is_nested;
176 /* True if this construct can be cancelled. */
177 bool cancellable;
178 } omp_context;
181 struct omp_for_data_loop
183 tree v, n1, n2, step;
184 enum tree_code cond_code;
187 /* A structure describing the main elements of a parallel loop. */
189 struct omp_for_data
191 struct omp_for_data_loop loop;
192 tree chunk_size;
193 gimple for_stmt;
194 tree pre, iter_type;
195 int collapse;
196 bool have_nowait, have_ordered;
197 enum omp_clause_schedule_kind sched_kind;
198 struct omp_for_data_loop *loops;
202 static splay_tree all_contexts;
203 static int taskreg_nesting_level;
204 static int target_nesting_level;
205 static struct omp_region *root_omp_region;
206 static bitmap task_shared_vars;
208 static void scan_omp (gimple_seq *, omp_context *);
209 static tree scan_omp_1_op (tree *, int *, void *);
211 #define WALK_SUBSTMTS \
212 case GIMPLE_BIND: \
213 case GIMPLE_TRY: \
214 case GIMPLE_CATCH: \
215 case GIMPLE_EH_FILTER: \
216 case GIMPLE_TRANSACTION: \
217 /* The sub-statements for these should be walked. */ \
218 *handled_ops_p = false; \
219 break;
221 /* Convenience function for calling scan_omp_1_op on tree operands. */
223 static inline tree
224 scan_omp_op (tree *tp, omp_context *ctx)
226 struct walk_stmt_info wi;
228 memset (&wi, 0, sizeof (wi));
229 wi.info = ctx;
230 wi.want_locations = true;
232 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
235 static void lower_omp (gimple_seq *, omp_context *);
236 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
237 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
239 /* Find an OpenMP clause of type KIND within CLAUSES. */
241 tree
242 find_omp_clause (tree clauses, enum omp_clause_code kind)
244 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
245 if (OMP_CLAUSE_CODE (clauses) == kind)
246 return clauses;
248 return NULL_TREE;
251 /* Return true if CTX is for an omp parallel. */
253 static inline bool
254 is_parallel_ctx (omp_context *ctx)
256 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
260 /* Return true if CTX is for an omp task. */
262 static inline bool
263 is_task_ctx (omp_context *ctx)
265 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
269 /* Return true if CTX is for an omp parallel or omp task. */
271 static inline bool
272 is_taskreg_ctx (omp_context *ctx)
274 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
275 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
279 /* Return true if REGION is a combined parallel+workshare region. */
281 static inline bool
282 is_combined_parallel (struct omp_region *region)
284 return region->is_combined_parallel;
288 /* Extract the header elements of parallel loop FOR_STMT and store
289 them into *FD. */
291 static void
292 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
293 struct omp_for_data_loop *loops)
295 tree t, var, *collapse_iter, *collapse_count;
296 tree count = NULL_TREE, iter_type = long_integer_type_node;
297 struct omp_for_data_loop *loop;
298 int i;
299 struct omp_for_data_loop dummy_loop;
300 location_t loc = gimple_location (for_stmt);
301 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_KIND_SIMD;
302 bool distribute = gimple_omp_for_kind (for_stmt)
303 == GF_OMP_FOR_KIND_DISTRIBUTE;
305 fd->for_stmt = for_stmt;
306 fd->pre = NULL;
307 fd->collapse = gimple_omp_for_collapse (for_stmt);
308 if (fd->collapse > 1)
309 fd->loops = loops;
310 else
311 fd->loops = &fd->loop;
313 fd->have_nowait = distribute || simd;
314 fd->have_ordered = false;
315 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
316 fd->chunk_size = NULL_TREE;
317 collapse_iter = NULL;
318 collapse_count = NULL;
320 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
321 switch (OMP_CLAUSE_CODE (t))
323 case OMP_CLAUSE_NOWAIT:
324 fd->have_nowait = true;
325 break;
326 case OMP_CLAUSE_ORDERED:
327 fd->have_ordered = true;
328 break;
329 case OMP_CLAUSE_SCHEDULE:
330 gcc_assert (!distribute);
331 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
332 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
333 break;
334 case OMP_CLAUSE_DIST_SCHEDULE:
335 gcc_assert (distribute);
336 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
337 break;
338 case OMP_CLAUSE_COLLAPSE:
339 if (fd->collapse > 1)
341 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
342 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
344 default:
345 break;
348 /* FIXME: for now map schedule(auto) to schedule(static).
349 There should be analysis to determine whether all iterations
350 are approximately the same amount of work (then schedule(static)
351 is best) or if it varies (then schedule(dynamic,N) is better). */
352 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
354 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
355 gcc_assert (fd->chunk_size == NULL);
357 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
358 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
359 gcc_assert (fd->chunk_size == NULL);
360 else if (fd->chunk_size == NULL)
362 /* We only need to compute a default chunk size for ordered
363 static loops and dynamic loops. */
364 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
365 || fd->have_ordered)
366 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
367 ? integer_zero_node : integer_one_node;
370 for (i = 0; i < fd->collapse; i++)
372 if (fd->collapse == 1)
373 loop = &fd->loop;
374 else if (loops != NULL)
375 loop = loops + i;
376 else
377 loop = &dummy_loop;
379 loop->v = gimple_omp_for_index (for_stmt, i);
380 gcc_assert (SSA_VAR_P (loop->v));
381 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
382 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
383 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
384 loop->n1 = gimple_omp_for_initial (for_stmt, i);
386 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
387 loop->n2 = gimple_omp_for_final (for_stmt, i);
388 switch (loop->cond_code)
390 case LT_EXPR:
391 case GT_EXPR:
392 break;
393 case NE_EXPR:
394 gcc_assert (gimple_omp_for_kind (for_stmt)
395 == GF_OMP_FOR_KIND_CILKSIMD);
396 break;
397 case LE_EXPR:
398 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
399 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
400 else
401 loop->n2 = fold_build2_loc (loc,
402 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
403 build_int_cst (TREE_TYPE (loop->n2), 1));
404 loop->cond_code = LT_EXPR;
405 break;
406 case GE_EXPR:
407 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
408 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
409 else
410 loop->n2 = fold_build2_loc (loc,
411 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
412 build_int_cst (TREE_TYPE (loop->n2), 1));
413 loop->cond_code = GT_EXPR;
414 break;
415 default:
416 gcc_unreachable ();
419 t = gimple_omp_for_incr (for_stmt, i);
420 gcc_assert (TREE_OPERAND (t, 0) == var);
421 switch (TREE_CODE (t))
423 case PLUS_EXPR:
424 loop->step = TREE_OPERAND (t, 1);
425 break;
426 case POINTER_PLUS_EXPR:
427 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
428 break;
429 case MINUS_EXPR:
430 loop->step = TREE_OPERAND (t, 1);
431 loop->step = fold_build1_loc (loc,
432 NEGATE_EXPR, TREE_TYPE (loop->step),
433 loop->step);
434 break;
435 default:
436 gcc_unreachable ();
439 if (simd
440 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
441 && !fd->have_ordered))
443 if (fd->collapse == 1)
444 iter_type = TREE_TYPE (loop->v);
445 else if (i == 0
446 || TYPE_PRECISION (iter_type)
447 < TYPE_PRECISION (TREE_TYPE (loop->v)))
448 iter_type
449 = build_nonstandard_integer_type
450 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
452 else if (iter_type != long_long_unsigned_type_node)
454 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
455 iter_type = long_long_unsigned_type_node;
456 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
457 && TYPE_PRECISION (TREE_TYPE (loop->v))
458 >= TYPE_PRECISION (iter_type))
460 tree n;
462 if (loop->cond_code == LT_EXPR)
463 n = fold_build2_loc (loc,
464 PLUS_EXPR, TREE_TYPE (loop->v),
465 loop->n2, loop->step);
466 else
467 n = loop->n1;
468 if (TREE_CODE (n) != INTEGER_CST
469 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
470 iter_type = long_long_unsigned_type_node;
472 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
473 > TYPE_PRECISION (iter_type))
475 tree n1, n2;
477 if (loop->cond_code == LT_EXPR)
479 n1 = loop->n1;
480 n2 = fold_build2_loc (loc,
481 PLUS_EXPR, TREE_TYPE (loop->v),
482 loop->n2, loop->step);
484 else
486 n1 = fold_build2_loc (loc,
487 MINUS_EXPR, TREE_TYPE (loop->v),
488 loop->n2, loop->step);
489 n2 = loop->n1;
491 if (TREE_CODE (n1) != INTEGER_CST
492 || TREE_CODE (n2) != INTEGER_CST
493 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
494 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
495 iter_type = long_long_unsigned_type_node;
499 if (collapse_count && *collapse_count == NULL)
501 t = fold_binary (loop->cond_code, boolean_type_node,
502 fold_convert (TREE_TYPE (loop->v), loop->n1),
503 fold_convert (TREE_TYPE (loop->v), loop->n2));
504 if (t && integer_zerop (t))
505 count = build_zero_cst (long_long_unsigned_type_node);
506 else if ((i == 0 || count != NULL_TREE)
507 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
508 && TREE_CONSTANT (loop->n1)
509 && TREE_CONSTANT (loop->n2)
510 && TREE_CODE (loop->step) == INTEGER_CST)
512 tree itype = TREE_TYPE (loop->v);
514 if (POINTER_TYPE_P (itype))
515 itype = signed_type_for (itype);
516 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
517 t = fold_build2_loc (loc,
518 PLUS_EXPR, itype,
519 fold_convert_loc (loc, itype, loop->step), t);
520 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
521 fold_convert_loc (loc, itype, loop->n2));
522 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
523 fold_convert_loc (loc, itype, loop->n1));
524 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
525 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
526 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
527 fold_build1_loc (loc, NEGATE_EXPR, itype,
528 fold_convert_loc (loc, itype,
529 loop->step)));
530 else
531 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
532 fold_convert_loc (loc, itype, loop->step));
533 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
534 if (count != NULL_TREE)
535 count = fold_build2_loc (loc,
536 MULT_EXPR, long_long_unsigned_type_node,
537 count, t);
538 else
539 count = t;
540 if (TREE_CODE (count) != INTEGER_CST)
541 count = NULL_TREE;
543 else if (count && !integer_zerop (count))
544 count = NULL_TREE;
548 if (count
549 && !simd
550 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
551 || fd->have_ordered))
553 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
554 iter_type = long_long_unsigned_type_node;
555 else
556 iter_type = long_integer_type_node;
558 else if (collapse_iter && *collapse_iter != NULL)
559 iter_type = TREE_TYPE (*collapse_iter);
560 fd->iter_type = iter_type;
561 if (collapse_iter && *collapse_iter == NULL)
562 *collapse_iter = create_tmp_var (iter_type, ".iter");
563 if (collapse_count && *collapse_count == NULL)
565 if (count)
566 *collapse_count = fold_convert_loc (loc, iter_type, count);
567 else
568 *collapse_count = create_tmp_var (iter_type, ".count");
571 if (fd->collapse > 1)
573 fd->loop.v = *collapse_iter;
574 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
575 fd->loop.n2 = *collapse_count;
576 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
577 fd->loop.cond_code = LT_EXPR;
582 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
583 is the immediate dominator of PAR_ENTRY_BB, return true if there
584 are no data dependencies that would prevent expanding the parallel
585 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
587 When expanding a combined parallel+workshare region, the call to
588 the child function may need additional arguments in the case of
589 GIMPLE_OMP_FOR regions. In some cases, these arguments are
590 computed out of variables passed in from the parent to the child
591 via 'struct .omp_data_s'. For instance:
593 #pragma omp parallel for schedule (guided, i * 4)
594 for (j ...)
596 Is lowered into:
598 # BLOCK 2 (PAR_ENTRY_BB)
599 .omp_data_o.i = i;
600 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
602 # BLOCK 3 (WS_ENTRY_BB)
603 .omp_data_i = &.omp_data_o;
604 D.1667 = .omp_data_i->i;
605 D.1598 = D.1667 * 4;
606 #pragma omp for schedule (guided, D.1598)
608 When we outline the parallel region, the call to the child function
609 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
610 that value is computed *after* the call site. So, in principle we
611 cannot do the transformation.
613 To see whether the code in WS_ENTRY_BB blocks the combined
614 parallel+workshare call, we collect all the variables used in the
615 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
616 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
617 call.
619 FIXME. If we had the SSA form built at this point, we could merely
620 hoist the code in block 3 into block 2 and be done with it. But at
621 this point we don't have dataflow information and though we could
622 hack something up here, it is really not worth the aggravation. */
624 static bool
625 workshare_safe_to_combine_p (basic_block ws_entry_bb)
627 struct omp_for_data fd;
628 gimple ws_stmt = last_stmt (ws_entry_bb);
630 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
631 return true;
633 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
635 extract_omp_for_data (ws_stmt, &fd, NULL);
637 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
638 return false;
639 if (fd.iter_type != long_integer_type_node)
640 return false;
642 /* FIXME. We give up too easily here. If any of these arguments
643 are not constants, they will likely involve variables that have
644 been mapped into fields of .omp_data_s for sharing with the child
645 function. With appropriate data flow, it would be possible to
646 see through this. */
647 if (!is_gimple_min_invariant (fd.loop.n1)
648 || !is_gimple_min_invariant (fd.loop.n2)
649 || !is_gimple_min_invariant (fd.loop.step)
650 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
651 return false;
653 return true;
657 /* Collect additional arguments needed to emit a combined
658 parallel+workshare call. WS_STMT is the workshare directive being
659 expanded. */
661 static vec<tree, va_gc> *
662 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
664 tree t;
665 location_t loc = gimple_location (ws_stmt);
666 vec<tree, va_gc> *ws_args;
668 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
670 struct omp_for_data fd;
671 tree n1, n2;
673 extract_omp_for_data (ws_stmt, &fd, NULL);
674 n1 = fd.loop.n1;
675 n2 = fd.loop.n2;
677 if (gimple_omp_for_combined_into_p (ws_stmt))
679 tree innerc
680 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
681 OMP_CLAUSE__LOOPTEMP_);
682 gcc_assert (innerc);
683 n1 = OMP_CLAUSE_DECL (innerc);
684 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
685 OMP_CLAUSE__LOOPTEMP_);
686 gcc_assert (innerc);
687 n2 = OMP_CLAUSE_DECL (innerc);
690 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
692 t = fold_convert_loc (loc, long_integer_type_node, n1);
693 ws_args->quick_push (t);
695 t = fold_convert_loc (loc, long_integer_type_node, n2);
696 ws_args->quick_push (t);
698 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
699 ws_args->quick_push (t);
701 if (fd.chunk_size)
703 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
704 ws_args->quick_push (t);
707 return ws_args;
709 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
711 /* Number of sections is equal to the number of edges from the
712 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
713 the exit of the sections region. */
714 basic_block bb = single_succ (gimple_bb (ws_stmt));
715 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
716 vec_alloc (ws_args, 1);
717 ws_args->quick_push (t);
718 return ws_args;
721 gcc_unreachable ();
725 /* Discover whether REGION is a combined parallel+workshare region. */
727 static void
728 determine_parallel_type (struct omp_region *region)
730 basic_block par_entry_bb, par_exit_bb;
731 basic_block ws_entry_bb, ws_exit_bb;
733 if (region == NULL || region->inner == NULL
734 || region->exit == NULL || region->inner->exit == NULL
735 || region->inner->cont == NULL)
736 return;
738 /* We only support parallel+for and parallel+sections. */
739 if (region->type != GIMPLE_OMP_PARALLEL
740 || (region->inner->type != GIMPLE_OMP_FOR
741 && region->inner->type != GIMPLE_OMP_SECTIONS))
742 return;
744 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
745 WS_EXIT_BB -> PAR_EXIT_BB. */
746 par_entry_bb = region->entry;
747 par_exit_bb = region->exit;
748 ws_entry_bb = region->inner->entry;
749 ws_exit_bb = region->inner->exit;
751 if (single_succ (par_entry_bb) == ws_entry_bb
752 && single_succ (ws_exit_bb) == par_exit_bb
753 && workshare_safe_to_combine_p (ws_entry_bb)
754 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
755 || (last_and_only_stmt (ws_entry_bb)
756 && last_and_only_stmt (par_exit_bb))))
758 gimple par_stmt = last_stmt (par_entry_bb);
759 gimple ws_stmt = last_stmt (ws_entry_bb);
761 if (region->inner->type == GIMPLE_OMP_FOR)
763 /* If this is a combined parallel loop, we need to determine
764 whether or not to use the combined library calls. There
765 are two cases where we do not apply the transformation:
766 static loops and any kind of ordered loop. In the first
767 case, we already open code the loop so there is no need
768 to do anything else. In the latter case, the combined
769 parallel loop call would still need extra synchronization
770 to implement ordered semantics, so there would not be any
771 gain in using the combined call. */
772 tree clauses = gimple_omp_for_clauses (ws_stmt);
773 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
774 if (c == NULL
775 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
776 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
778 region->is_combined_parallel = false;
779 region->inner->is_combined_parallel = false;
780 return;
784 region->is_combined_parallel = true;
785 region->inner->is_combined_parallel = true;
786 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
791 /* Return true if EXPR is variable sized. */
793 static inline bool
794 is_variable_sized (const_tree expr)
796 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
799 /* Return true if DECL is a reference type. */
801 static inline bool
802 is_reference (tree decl)
804 return lang_hooks.decls.omp_privatize_by_reference (decl);
807 /* Lookup variables in the decl or field splay trees. The "maybe" form
808 allows for the variable form to not have been entered, otherwise we
809 assert that the variable must have been entered. */
811 static inline tree
812 lookup_decl (tree var, omp_context *ctx)
814 tree *n;
815 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
816 return *n;
819 static inline tree
820 maybe_lookup_decl (const_tree var, omp_context *ctx)
822 tree *n;
823 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
824 return n ? *n : NULL_TREE;
827 static inline tree
828 lookup_field (tree var, omp_context *ctx)
830 splay_tree_node n;
831 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
832 return (tree) n->value;
835 static inline tree
836 lookup_sfield (tree var, omp_context *ctx)
838 splay_tree_node n;
839 n = splay_tree_lookup (ctx->sfield_map
840 ? ctx->sfield_map : ctx->field_map,
841 (splay_tree_key) var);
842 return (tree) n->value;
845 static inline tree
846 maybe_lookup_field (tree var, omp_context *ctx)
848 splay_tree_node n;
849 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
850 return n ? (tree) n->value : NULL_TREE;
853 /* Return true if DECL should be copied by pointer. SHARED_CTX is
854 the parallel context if DECL is to be shared. */
856 static bool
857 use_pointer_for_field (tree decl, omp_context *shared_ctx)
859 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
860 return true;
862 /* We can only use copy-in/copy-out semantics for shared variables
863 when we know the value is not accessible from an outer scope. */
864 if (shared_ctx)
866 /* ??? Trivially accessible from anywhere. But why would we even
867 be passing an address in this case? Should we simply assert
868 this to be false, or should we have a cleanup pass that removes
869 these from the list of mappings? */
870 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
871 return true;
873 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
874 without analyzing the expression whether or not its location
875 is accessible to anyone else. In the case of nested parallel
876 regions it certainly may be. */
877 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
878 return true;
880 /* Do not use copy-in/copy-out for variables that have their
881 address taken. */
882 if (TREE_ADDRESSABLE (decl))
883 return true;
885 /* lower_send_shared_vars only uses copy-in, but not copy-out
886 for these. */
887 if (TREE_READONLY (decl)
888 || ((TREE_CODE (decl) == RESULT_DECL
889 || TREE_CODE (decl) == PARM_DECL)
890 && DECL_BY_REFERENCE (decl)))
891 return false;
893 /* Disallow copy-in/out in nested parallel if
894 decl is shared in outer parallel, otherwise
895 each thread could store the shared variable
896 in its own copy-in location, making the
897 variable no longer really shared. */
898 if (shared_ctx->is_nested)
900 omp_context *up;
902 for (up = shared_ctx->outer; up; up = up->outer)
903 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
904 break;
906 if (up)
908 tree c;
910 for (c = gimple_omp_taskreg_clauses (up->stmt);
911 c; c = OMP_CLAUSE_CHAIN (c))
912 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
913 && OMP_CLAUSE_DECL (c) == decl)
914 break;
916 if (c)
917 goto maybe_mark_addressable_and_ret;
921 /* For tasks avoid using copy-in/out. As tasks can be
922 deferred or executed in different thread, when GOMP_task
923 returns, the task hasn't necessarily terminated. */
924 if (is_task_ctx (shared_ctx))
926 tree outer;
927 maybe_mark_addressable_and_ret:
928 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
929 if (is_gimple_reg (outer))
931 /* Taking address of OUTER in lower_send_shared_vars
932 might need regimplification of everything that uses the
933 variable. */
934 if (!task_shared_vars)
935 task_shared_vars = BITMAP_ALLOC (NULL);
936 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
937 TREE_ADDRESSABLE (outer) = 1;
939 return true;
943 return false;
946 /* Construct a new automatic decl similar to VAR. */
948 static tree
949 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
951 tree copy = copy_var_decl (var, name, type);
953 DECL_CONTEXT (copy) = current_function_decl;
954 DECL_CHAIN (copy) = ctx->block_vars;
955 ctx->block_vars = copy;
957 return copy;
960 static tree
961 omp_copy_decl_1 (tree var, omp_context *ctx)
963 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
966 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
967 as appropriate. */
968 static tree
969 omp_build_component_ref (tree obj, tree field)
971 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
972 if (TREE_THIS_VOLATILE (field))
973 TREE_THIS_VOLATILE (ret) |= 1;
974 if (TREE_READONLY (field))
975 TREE_READONLY (ret) |= 1;
976 return ret;
979 /* Build tree nodes to access the field for VAR on the receiver side. */
981 static tree
982 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
984 tree x, field = lookup_field (var, ctx);
986 /* If the receiver record type was remapped in the child function,
987 remap the field into the new record type. */
988 x = maybe_lookup_field (field, ctx);
989 if (x != NULL)
990 field = x;
992 x = build_simple_mem_ref (ctx->receiver_decl);
993 x = omp_build_component_ref (x, field);
994 if (by_ref)
995 x = build_simple_mem_ref (x);
997 return x;
1000 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1001 of a parallel, this is a component reference; for workshare constructs
1002 this is some variable. */
1004 static tree
1005 build_outer_var_ref (tree var, omp_context *ctx)
1007 tree x;
1009 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1010 x = var;
1011 else if (is_variable_sized (var))
1013 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1014 x = build_outer_var_ref (x, ctx);
1015 x = build_simple_mem_ref (x);
1017 else if (is_taskreg_ctx (ctx))
1019 bool by_ref = use_pointer_for_field (var, NULL);
1020 x = build_receiver_ref (var, by_ref, ctx);
1022 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1023 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
1025 /* #pragma omp simd isn't a worksharing construct, and can reference even
1026 private vars in its linear etc. clauses. */
1027 x = NULL_TREE;
1028 if (ctx->outer && is_taskreg_ctx (ctx))
1029 x = lookup_decl (var, ctx->outer);
1030 else if (ctx->outer)
1031 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1032 if (x == NULL_TREE)
1033 x = var;
1035 else if (ctx->outer)
1036 x = lookup_decl (var, ctx->outer);
1037 else if (is_reference (var))
1038 /* This can happen with orphaned constructs. If var is reference, it is
1039 possible it is shared and as such valid. */
1040 x = var;
1041 else
1042 gcc_unreachable ();
1044 if (is_reference (var))
1045 x = build_simple_mem_ref (x);
1047 return x;
1050 /* Build tree nodes to access the field for VAR on the sender side. */
1052 static tree
1053 build_sender_ref (tree var, omp_context *ctx)
1055 tree field = lookup_sfield (var, ctx);
1056 return omp_build_component_ref (ctx->sender_decl, field);
1059 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1061 static void
1062 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1064 tree field, type, sfield = NULL_TREE;
1066 gcc_assert ((mask & 1) == 0
1067 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1068 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1069 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1071 type = TREE_TYPE (var);
1072 if (mask & 4)
1074 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1075 type = build_pointer_type (build_pointer_type (type));
1077 else if (by_ref)
1078 type = build_pointer_type (type);
1079 else if ((mask & 3) == 1 && is_reference (var))
1080 type = TREE_TYPE (type);
1082 field = build_decl (DECL_SOURCE_LOCATION (var),
1083 FIELD_DECL, DECL_NAME (var), type);
1085 /* Remember what variable this field was created for. This does have a
1086 side effect of making dwarf2out ignore this member, so for helpful
1087 debugging we clear it later in delete_omp_context. */
1088 DECL_ABSTRACT_ORIGIN (field) = var;
1089 if (type == TREE_TYPE (var))
1091 DECL_ALIGN (field) = DECL_ALIGN (var);
1092 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1093 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1095 else
1096 DECL_ALIGN (field) = TYPE_ALIGN (type);
1098 if ((mask & 3) == 3)
1100 insert_field_into_struct (ctx->record_type, field);
1101 if (ctx->srecord_type)
1103 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1104 FIELD_DECL, DECL_NAME (var), type);
1105 DECL_ABSTRACT_ORIGIN (sfield) = var;
1106 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1107 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1108 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1109 insert_field_into_struct (ctx->srecord_type, sfield);
1112 else
1114 if (ctx->srecord_type == NULL_TREE)
1116 tree t;
1118 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1119 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1120 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1122 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1123 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1124 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1125 insert_field_into_struct (ctx->srecord_type, sfield);
1126 splay_tree_insert (ctx->sfield_map,
1127 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1128 (splay_tree_value) sfield);
1131 sfield = field;
1132 insert_field_into_struct ((mask & 1) ? ctx->record_type
1133 : ctx->srecord_type, field);
1136 if (mask & 1)
1137 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1138 (splay_tree_value) field);
1139 if ((mask & 2) && ctx->sfield_map)
1140 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1141 (splay_tree_value) sfield);
1144 static tree
1145 install_var_local (tree var, omp_context *ctx)
1147 tree new_var = omp_copy_decl_1 (var, ctx);
1148 insert_decl_map (&ctx->cb, var, new_var);
1149 return new_var;
1152 /* Adjust the replacement for DECL in CTX for the new context. This means
1153 copying the DECL_VALUE_EXPR, and fixing up the type. */
1155 static void
1156 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1158 tree new_decl, size;
1160 new_decl = lookup_decl (decl, ctx);
1162 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1164 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1165 && DECL_HAS_VALUE_EXPR_P (decl))
1167 tree ve = DECL_VALUE_EXPR (decl);
1168 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1169 SET_DECL_VALUE_EXPR (new_decl, ve);
1170 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1173 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1175 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1176 if (size == error_mark_node)
1177 size = TYPE_SIZE (TREE_TYPE (new_decl));
1178 DECL_SIZE (new_decl) = size;
1180 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1181 if (size == error_mark_node)
1182 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1183 DECL_SIZE_UNIT (new_decl) = size;
1187 /* The callback for remap_decl. Search all containing contexts for a
1188 mapping of the variable; this avoids having to duplicate the splay
1189 tree ahead of time. We know a mapping doesn't already exist in the
1190 given context. Create new mappings to implement default semantics. */
1192 static tree
1193 omp_copy_decl (tree var, copy_body_data *cb)
1195 omp_context *ctx = (omp_context *) cb;
1196 tree new_var;
1198 if (TREE_CODE (var) == LABEL_DECL)
1200 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1201 DECL_CONTEXT (new_var) = current_function_decl;
1202 insert_decl_map (&ctx->cb, var, new_var);
1203 return new_var;
1206 while (!is_taskreg_ctx (ctx))
1208 ctx = ctx->outer;
1209 if (ctx == NULL)
1210 return var;
1211 new_var = maybe_lookup_decl (var, ctx);
1212 if (new_var)
1213 return new_var;
1216 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1217 return var;
1219 return error_mark_node;
1223 /* Debugging dumps for parallel regions. */
1224 void dump_omp_region (FILE *, struct omp_region *, int);
1225 void debug_omp_region (struct omp_region *);
1226 void debug_all_omp_regions (void);
1228 /* Dump the parallel region tree rooted at REGION. */
1230 void
1231 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1233 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1234 gimple_code_name[region->type]);
1236 if (region->inner)
1237 dump_omp_region (file, region->inner, indent + 4);
1239 if (region->cont)
1241 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1242 region->cont->index);
1245 if (region->exit)
1246 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1247 region->exit->index);
1248 else
1249 fprintf (file, "%*s[no exit marker]\n", indent, "");
1251 if (region->next)
1252 dump_omp_region (file, region->next, indent);
1255 DEBUG_FUNCTION void
1256 debug_omp_region (struct omp_region *region)
1258 dump_omp_region (stderr, region, 0);
1261 DEBUG_FUNCTION void
1262 debug_all_omp_regions (void)
1264 dump_omp_region (stderr, root_omp_region, 0);
1268 /* Create a new parallel region starting at STMT inside region PARENT. */
1270 static struct omp_region *
1271 new_omp_region (basic_block bb, enum gimple_code type,
1272 struct omp_region *parent)
1274 struct omp_region *region = XCNEW (struct omp_region);
1276 region->outer = parent;
1277 region->entry = bb;
1278 region->type = type;
1280 if (parent)
1282 /* This is a nested region. Add it to the list of inner
1283 regions in PARENT. */
1284 region->next = parent->inner;
1285 parent->inner = region;
1287 else
1289 /* This is a toplevel region. Add it to the list of toplevel
1290 regions in ROOT_OMP_REGION. */
1291 region->next = root_omp_region;
1292 root_omp_region = region;
1295 return region;
1298 /* Release the memory associated with the region tree rooted at REGION. */
1300 static void
1301 free_omp_region_1 (struct omp_region *region)
1303 struct omp_region *i, *n;
1305 for (i = region->inner; i ; i = n)
1307 n = i->next;
1308 free_omp_region_1 (i);
1311 free (region);
1314 /* Release the memory for the entire omp region tree. */
1316 void
1317 free_omp_regions (void)
1319 struct omp_region *r, *n;
1320 for (r = root_omp_region; r ; r = n)
1322 n = r->next;
1323 free_omp_region_1 (r);
1325 root_omp_region = NULL;
1329 /* Create a new context, with OUTER_CTX being the surrounding context. */
1331 static omp_context *
1332 new_omp_context (gimple stmt, omp_context *outer_ctx)
1334 omp_context *ctx = XCNEW (omp_context);
1336 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1337 (splay_tree_value) ctx);
1338 ctx->stmt = stmt;
1340 if (outer_ctx)
1342 ctx->outer = outer_ctx;
1343 ctx->cb = outer_ctx->cb;
1344 ctx->cb.block = NULL;
1345 ctx->depth = outer_ctx->depth + 1;
1347 else
1349 ctx->cb.src_fn = current_function_decl;
1350 ctx->cb.dst_fn = current_function_decl;
1351 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1352 gcc_checking_assert (ctx->cb.src_node);
1353 ctx->cb.dst_node = ctx->cb.src_node;
1354 ctx->cb.src_cfun = cfun;
1355 ctx->cb.copy_decl = omp_copy_decl;
1356 ctx->cb.eh_lp_nr = 0;
1357 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1358 ctx->depth = 1;
1361 ctx->cb.decl_map = pointer_map_create ();
1363 return ctx;
1366 static gimple_seq maybe_catch_exception (gimple_seq);
1368 /* Finalize task copyfn. */
1370 static void
1371 finalize_task_copyfn (gimple task_stmt)
1373 struct function *child_cfun;
1374 tree child_fn;
1375 gimple_seq seq = NULL, new_seq;
1376 gimple bind;
1378 child_fn = gimple_omp_task_copy_fn (task_stmt);
1379 if (child_fn == NULL_TREE)
1380 return;
1382 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1383 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1385 push_cfun (child_cfun);
1386 bind = gimplify_body (child_fn, false);
1387 gimple_seq_add_stmt (&seq, bind);
1388 new_seq = maybe_catch_exception (seq);
1389 if (new_seq != seq)
1391 bind = gimple_build_bind (NULL, new_seq, NULL);
1392 seq = NULL;
1393 gimple_seq_add_stmt (&seq, bind);
1395 gimple_set_body (child_fn, seq);
1396 pop_cfun ();
1398 /* Inform the callgraph about the new function. */
1399 cgraph_add_new_function (child_fn, false);
1402 /* Destroy a omp_context data structures. Called through the splay tree
1403 value delete callback. */
1405 static void
1406 delete_omp_context (splay_tree_value value)
1408 omp_context *ctx = (omp_context *) value;
1410 pointer_map_destroy (ctx->cb.decl_map);
1412 if (ctx->field_map)
1413 splay_tree_delete (ctx->field_map);
1414 if (ctx->sfield_map)
1415 splay_tree_delete (ctx->sfield_map);
1417 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1418 it produces corrupt debug information. */
1419 if (ctx->record_type)
1421 tree t;
1422 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1423 DECL_ABSTRACT_ORIGIN (t) = NULL;
1425 if (ctx->srecord_type)
1427 tree t;
1428 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1429 DECL_ABSTRACT_ORIGIN (t) = NULL;
1432 if (is_task_ctx (ctx))
1433 finalize_task_copyfn (ctx->stmt);
1435 XDELETE (ctx);
1438 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1439 context. */
1441 static void
1442 fixup_child_record_type (omp_context *ctx)
1444 tree f, type = ctx->record_type;
1446 /* ??? It isn't sufficient to just call remap_type here, because
1447 variably_modified_type_p doesn't work the way we expect for
1448 record types. Testing each field for whether it needs remapping
1449 and creating a new record by hand works, however. */
1450 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1451 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1452 break;
1453 if (f)
1455 tree name, new_fields = NULL;
1457 type = lang_hooks.types.make_type (RECORD_TYPE);
1458 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1459 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1460 TYPE_DECL, name, type);
1461 TYPE_NAME (type) = name;
1463 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1465 tree new_f = copy_node (f);
1466 DECL_CONTEXT (new_f) = type;
1467 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1468 DECL_CHAIN (new_f) = new_fields;
1469 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1470 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1471 &ctx->cb, NULL);
1472 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1473 &ctx->cb, NULL);
1474 new_fields = new_f;
1476 /* Arrange to be able to look up the receiver field
1477 given the sender field. */
1478 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1479 (splay_tree_value) new_f);
1481 TYPE_FIELDS (type) = nreverse (new_fields);
1482 layout_type (type);
1485 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1488 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1489 specified by CLAUSES. */
1491 static void
1492 scan_sharing_clauses (tree clauses, omp_context *ctx)
1494 tree c, decl;
1495 bool scan_array_reductions = false;
1497 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1499 bool by_ref;
1501 switch (OMP_CLAUSE_CODE (c))
1503 case OMP_CLAUSE_PRIVATE:
1504 decl = OMP_CLAUSE_DECL (c);
1505 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1506 goto do_private;
1507 else if (!is_variable_sized (decl))
1508 install_var_local (decl, ctx);
1509 break;
1511 case OMP_CLAUSE_SHARED:
1512 /* Ignore shared directives in teams construct. */
1513 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1514 break;
1515 gcc_assert (is_taskreg_ctx (ctx));
1516 decl = OMP_CLAUSE_DECL (c);
1517 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1518 || !is_variable_sized (decl));
1519 /* Global variables don't need to be copied,
1520 the receiver side will use them directly. */
1521 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1522 break;
1523 by_ref = use_pointer_for_field (decl, ctx);
1524 if (! TREE_READONLY (decl)
1525 || TREE_ADDRESSABLE (decl)
1526 || by_ref
1527 || is_reference (decl))
1529 install_var_field (decl, by_ref, 3, ctx);
1530 install_var_local (decl, ctx);
1531 break;
1533 /* We don't need to copy const scalar vars back. */
1534 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1535 goto do_private;
1537 case OMP_CLAUSE_LASTPRIVATE:
1538 /* Let the corresponding firstprivate clause create
1539 the variable. */
1540 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1541 break;
1542 /* FALLTHRU */
1544 case OMP_CLAUSE_FIRSTPRIVATE:
1545 case OMP_CLAUSE_REDUCTION:
1546 case OMP_CLAUSE_LINEAR:
1547 decl = OMP_CLAUSE_DECL (c);
1548 do_private:
1549 if (is_variable_sized (decl))
1551 if (is_task_ctx (ctx))
1552 install_var_field (decl, false, 1, ctx);
1553 break;
1555 else if (is_taskreg_ctx (ctx))
1557 bool global
1558 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1559 by_ref = use_pointer_for_field (decl, NULL);
1561 if (is_task_ctx (ctx)
1562 && (global || by_ref || is_reference (decl)))
1564 install_var_field (decl, false, 1, ctx);
1565 if (!global)
1566 install_var_field (decl, by_ref, 2, ctx);
1568 else if (!global)
1569 install_var_field (decl, by_ref, 3, ctx);
1571 install_var_local (decl, ctx);
1572 break;
1574 case OMP_CLAUSE__LOOPTEMP_:
1575 gcc_assert (is_parallel_ctx (ctx));
1576 decl = OMP_CLAUSE_DECL (c);
1577 install_var_field (decl, false, 3, ctx);
1578 install_var_local (decl, ctx);
1579 break;
1581 case OMP_CLAUSE_COPYPRIVATE:
1582 case OMP_CLAUSE_COPYIN:
1583 decl = OMP_CLAUSE_DECL (c);
1584 by_ref = use_pointer_for_field (decl, NULL);
1585 install_var_field (decl, by_ref, 3, ctx);
1586 break;
1588 case OMP_CLAUSE_DEFAULT:
1589 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1590 break;
1592 case OMP_CLAUSE_FINAL:
1593 case OMP_CLAUSE_IF:
1594 case OMP_CLAUSE_NUM_THREADS:
1595 case OMP_CLAUSE_NUM_TEAMS:
1596 case OMP_CLAUSE_THREAD_LIMIT:
1597 case OMP_CLAUSE_DEVICE:
1598 case OMP_CLAUSE_SCHEDULE:
1599 case OMP_CLAUSE_DIST_SCHEDULE:
1600 case OMP_CLAUSE_DEPEND:
1601 if (ctx->outer)
1602 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1603 break;
1605 case OMP_CLAUSE_TO:
1606 case OMP_CLAUSE_FROM:
1607 case OMP_CLAUSE_MAP:
1608 if (ctx->outer)
1609 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1610 decl = OMP_CLAUSE_DECL (c);
1611 /* Global variables with "omp declare target" attribute
1612 don't need to be copied, the receiver side will use them
1613 directly. */
1614 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1615 && DECL_P (decl)
1616 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1617 && lookup_attribute ("omp declare target",
1618 DECL_ATTRIBUTES (decl)))
1619 break;
1620 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1621 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1623 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1624 #pragma omp target data, there is nothing to map for
1625 those. */
1626 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1627 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1628 break;
1630 if (DECL_P (decl))
1632 if (DECL_SIZE (decl)
1633 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1635 tree decl2 = DECL_VALUE_EXPR (decl);
1636 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1637 decl2 = TREE_OPERAND (decl2, 0);
1638 gcc_assert (DECL_P (decl2));
1639 install_var_field (decl2, true, 3, ctx);
1640 install_var_local (decl2, ctx);
1641 install_var_local (decl, ctx);
1643 else
1645 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1646 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1647 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1648 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1649 install_var_field (decl, true, 7, ctx);
1650 else
1651 install_var_field (decl, true, 3, ctx);
1652 if (gimple_omp_target_kind (ctx->stmt)
1653 == GF_OMP_TARGET_KIND_REGION)
1654 install_var_local (decl, ctx);
1657 else
1659 tree base = get_base_address (decl);
1660 tree nc = OMP_CLAUSE_CHAIN (c);
1661 if (DECL_P (base)
1662 && nc != NULL_TREE
1663 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1664 && OMP_CLAUSE_DECL (nc) == base
1665 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1666 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1668 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1669 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1671 else
1673 gcc_assert (!splay_tree_lookup (ctx->field_map,
1674 (splay_tree_key) decl));
1675 tree field
1676 = build_decl (OMP_CLAUSE_LOCATION (c),
1677 FIELD_DECL, NULL_TREE, ptr_type_node);
1678 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1679 insert_field_into_struct (ctx->record_type, field);
1680 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1681 (splay_tree_value) field);
1684 break;
1686 case OMP_CLAUSE_NOWAIT:
1687 case OMP_CLAUSE_ORDERED:
1688 case OMP_CLAUSE_COLLAPSE:
1689 case OMP_CLAUSE_UNTIED:
1690 case OMP_CLAUSE_MERGEABLE:
1691 case OMP_CLAUSE_PROC_BIND:
1692 case OMP_CLAUSE_SAFELEN:
1693 break;
1695 case OMP_CLAUSE_ALIGNED:
1696 decl = OMP_CLAUSE_DECL (c);
1697 if (is_global_var (decl)
1698 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1699 install_var_local (decl, ctx);
1700 break;
1702 default:
1703 gcc_unreachable ();
1707 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1709 switch (OMP_CLAUSE_CODE (c))
1711 case OMP_CLAUSE_LASTPRIVATE:
1712 /* Let the corresponding firstprivate clause create
1713 the variable. */
1714 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1715 scan_array_reductions = true;
1716 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1717 break;
1718 /* FALLTHRU */
1720 case OMP_CLAUSE_PRIVATE:
1721 case OMP_CLAUSE_FIRSTPRIVATE:
1722 case OMP_CLAUSE_REDUCTION:
1723 case OMP_CLAUSE_LINEAR:
1724 decl = OMP_CLAUSE_DECL (c);
1725 if (is_variable_sized (decl))
1726 install_var_local (decl, ctx);
1727 fixup_remapped_decl (decl, ctx,
1728 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1729 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1730 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1731 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1732 scan_array_reductions = true;
1733 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1734 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1735 scan_array_reductions = true;
1736 break;
1738 case OMP_CLAUSE_SHARED:
1739 /* Ignore shared directives in teams construct. */
1740 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1741 break;
1742 decl = OMP_CLAUSE_DECL (c);
1743 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1744 fixup_remapped_decl (decl, ctx, false);
1745 break;
1747 case OMP_CLAUSE_MAP:
1748 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1749 break;
1750 decl = OMP_CLAUSE_DECL (c);
1751 if (DECL_P (decl)
1752 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1753 && lookup_attribute ("omp declare target",
1754 DECL_ATTRIBUTES (decl)))
1755 break;
1756 if (DECL_P (decl))
1758 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1759 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1760 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1762 tree new_decl = lookup_decl (decl, ctx);
1763 TREE_TYPE (new_decl)
1764 = remap_type (TREE_TYPE (decl), &ctx->cb);
1766 else if (DECL_SIZE (decl)
1767 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1769 tree decl2 = DECL_VALUE_EXPR (decl);
1770 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1771 decl2 = TREE_OPERAND (decl2, 0);
1772 gcc_assert (DECL_P (decl2));
1773 fixup_remapped_decl (decl2, ctx, false);
1774 fixup_remapped_decl (decl, ctx, true);
1776 else
1777 fixup_remapped_decl (decl, ctx, false);
1779 break;
1781 case OMP_CLAUSE_COPYPRIVATE:
1782 case OMP_CLAUSE_COPYIN:
1783 case OMP_CLAUSE_DEFAULT:
1784 case OMP_CLAUSE_IF:
1785 case OMP_CLAUSE_NUM_THREADS:
1786 case OMP_CLAUSE_NUM_TEAMS:
1787 case OMP_CLAUSE_THREAD_LIMIT:
1788 case OMP_CLAUSE_DEVICE:
1789 case OMP_CLAUSE_SCHEDULE:
1790 case OMP_CLAUSE_DIST_SCHEDULE:
1791 case OMP_CLAUSE_NOWAIT:
1792 case OMP_CLAUSE_ORDERED:
1793 case OMP_CLAUSE_COLLAPSE:
1794 case OMP_CLAUSE_UNTIED:
1795 case OMP_CLAUSE_FINAL:
1796 case OMP_CLAUSE_MERGEABLE:
1797 case OMP_CLAUSE_PROC_BIND:
1798 case OMP_CLAUSE_SAFELEN:
1799 case OMP_CLAUSE_ALIGNED:
1800 case OMP_CLAUSE_DEPEND:
1801 case OMP_CLAUSE__LOOPTEMP_:
1802 case OMP_CLAUSE_TO:
1803 case OMP_CLAUSE_FROM:
1804 break;
1806 default:
1807 gcc_unreachable ();
1811 if (scan_array_reductions)
1812 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1813 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1814 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1816 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1817 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1819 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1820 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1821 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1822 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1823 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1824 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1827 /* Create a new name for omp child function. Returns an identifier. */
1829 static tree
1830 create_omp_child_function_name (bool task_copy)
1832 return (clone_function_name (current_function_decl,
1833 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1836 /* Build a decl for the omp child function. It'll not contain a body
1837 yet, just the bare decl. */
1839 static void
1840 create_omp_child_function (omp_context *ctx, bool task_copy)
1842 tree decl, type, name, t;
1844 name = create_omp_child_function_name (task_copy);
1845 if (task_copy)
1846 type = build_function_type_list (void_type_node, ptr_type_node,
1847 ptr_type_node, NULL_TREE);
1848 else
1849 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1851 decl = build_decl (gimple_location (ctx->stmt),
1852 FUNCTION_DECL, name, type);
1854 if (!task_copy)
1855 ctx->cb.dst_fn = decl;
1856 else
1857 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1859 TREE_STATIC (decl) = 1;
1860 TREE_USED (decl) = 1;
1861 DECL_ARTIFICIAL (decl) = 1;
1862 DECL_NAMELESS (decl) = 1;
1863 DECL_IGNORED_P (decl) = 0;
1864 TREE_PUBLIC (decl) = 0;
1865 DECL_UNINLINABLE (decl) = 1;
1866 DECL_EXTERNAL (decl) = 0;
1867 DECL_CONTEXT (decl) = NULL_TREE;
1868 DECL_INITIAL (decl) = make_node (BLOCK);
1869 bool target_p = false;
1870 if (lookup_attribute ("omp declare target",
1871 DECL_ATTRIBUTES (current_function_decl)))
1872 target_p = true;
1873 else
1875 omp_context *octx;
1876 for (octx = ctx; octx; octx = octx->outer)
1877 if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
1878 && gimple_omp_target_kind (octx->stmt)
1879 == GF_OMP_TARGET_KIND_REGION)
1881 target_p = true;
1882 break;
1885 if (target_p)
1886 DECL_ATTRIBUTES (decl)
1887 = tree_cons (get_identifier ("omp declare target"),
1888 NULL_TREE, DECL_ATTRIBUTES (decl));
1890 t = build_decl (DECL_SOURCE_LOCATION (decl),
1891 RESULT_DECL, NULL_TREE, void_type_node);
1892 DECL_ARTIFICIAL (t) = 1;
1893 DECL_IGNORED_P (t) = 1;
1894 DECL_CONTEXT (t) = decl;
1895 DECL_RESULT (decl) = t;
1897 t = build_decl (DECL_SOURCE_LOCATION (decl),
1898 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1899 DECL_ARTIFICIAL (t) = 1;
1900 DECL_NAMELESS (t) = 1;
1901 DECL_ARG_TYPE (t) = ptr_type_node;
1902 DECL_CONTEXT (t) = current_function_decl;
1903 TREE_USED (t) = 1;
1904 DECL_ARGUMENTS (decl) = t;
1905 if (!task_copy)
1906 ctx->receiver_decl = t;
1907 else
1909 t = build_decl (DECL_SOURCE_LOCATION (decl),
1910 PARM_DECL, get_identifier (".omp_data_o"),
1911 ptr_type_node);
1912 DECL_ARTIFICIAL (t) = 1;
1913 DECL_NAMELESS (t) = 1;
1914 DECL_ARG_TYPE (t) = ptr_type_node;
1915 DECL_CONTEXT (t) = current_function_decl;
1916 TREE_USED (t) = 1;
1917 TREE_ADDRESSABLE (t) = 1;
1918 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1919 DECL_ARGUMENTS (decl) = t;
1922 /* Allocate memory for the function structure. The call to
1923 allocate_struct_function clobbers CFUN, so we need to restore
1924 it afterward. */
1925 push_struct_function (decl);
1926 cfun->function_end_locus = gimple_location (ctx->stmt);
1927 pop_cfun ();
1930 /* Callback for walk_gimple_seq. Check if combined parallel
1931 contains gimple_omp_for_combined_into_p OMP_FOR. */
1933 static tree
1934 find_combined_for (gimple_stmt_iterator *gsi_p,
1935 bool *handled_ops_p,
1936 struct walk_stmt_info *wi)
1938 gimple stmt = gsi_stmt (*gsi_p);
1940 *handled_ops_p = true;
1941 switch (gimple_code (stmt))
1943 WALK_SUBSTMTS;
1945 case GIMPLE_OMP_FOR:
1946 if (gimple_omp_for_combined_into_p (stmt)
1947 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
1949 wi->info = stmt;
1950 return integer_zero_node;
1952 break;
1953 default:
1954 break;
1956 return NULL;
1959 /* Scan an OpenMP parallel directive. */
1961 static void
1962 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1964 omp_context *ctx;
1965 tree name;
1966 gimple stmt = gsi_stmt (*gsi);
1968 /* Ignore parallel directives with empty bodies, unless there
1969 are copyin clauses. */
1970 if (optimize > 0
1971 && empty_body_p (gimple_omp_body (stmt))
1972 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1973 OMP_CLAUSE_COPYIN) == NULL)
1975 gsi_replace (gsi, gimple_build_nop (), false);
1976 return;
1979 if (gimple_omp_parallel_combined_p (stmt))
1981 gimple for_stmt;
1982 struct walk_stmt_info wi;
1984 memset (&wi, 0, sizeof (wi));
1985 wi.val_only = true;
1986 walk_gimple_seq (gimple_omp_body (stmt),
1987 find_combined_for, NULL, &wi);
1988 for_stmt = (gimple) wi.info;
1989 if (for_stmt)
1991 struct omp_for_data fd;
1992 extract_omp_for_data (for_stmt, &fd, NULL);
1993 /* We need two temporaries with fd.loop.v type (istart/iend)
1994 and then (fd.collapse - 1) temporaries with the same
1995 type for count2 ... countN-1 vars if not constant. */
1996 size_t count = 2, i;
1997 tree type = fd.iter_type;
1998 if (fd.collapse > 1
1999 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2000 count += fd.collapse - 1;
2001 for (i = 0; i < count; i++)
2003 tree temp = create_tmp_var (type, NULL);
2004 tree c = build_omp_clause (UNKNOWN_LOCATION,
2005 OMP_CLAUSE__LOOPTEMP_);
2006 OMP_CLAUSE_DECL (c) = temp;
2007 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2008 gimple_omp_parallel_set_clauses (stmt, c);
2013 ctx = new_omp_context (stmt, outer_ctx);
2014 if (taskreg_nesting_level > 1)
2015 ctx->is_nested = true;
2016 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2017 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2018 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2019 name = create_tmp_var_name (".omp_data_s");
2020 name = build_decl (gimple_location (stmt),
2021 TYPE_DECL, name, ctx->record_type);
2022 DECL_ARTIFICIAL (name) = 1;
2023 DECL_NAMELESS (name) = 1;
2024 TYPE_NAME (ctx->record_type) = name;
2025 create_omp_child_function (ctx, false);
2026 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2028 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2029 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2031 if (TYPE_FIELDS (ctx->record_type) == NULL)
2032 ctx->record_type = ctx->receiver_decl = NULL;
2033 else
2035 layout_type (ctx->record_type);
2036 fixup_child_record_type (ctx);
2040 /* Scan an OpenMP task directive. */
2042 static void
2043 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2045 omp_context *ctx;
2046 tree name, t;
2047 gimple stmt = gsi_stmt (*gsi);
2048 location_t loc = gimple_location (stmt);
2050 /* Ignore task directives with empty bodies. */
2051 if (optimize > 0
2052 && empty_body_p (gimple_omp_body (stmt)))
2054 gsi_replace (gsi, gimple_build_nop (), false);
2055 return;
2058 ctx = new_omp_context (stmt, outer_ctx);
2059 if (taskreg_nesting_level > 1)
2060 ctx->is_nested = true;
2061 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2062 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2063 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2064 name = create_tmp_var_name (".omp_data_s");
2065 name = build_decl (gimple_location (stmt),
2066 TYPE_DECL, name, ctx->record_type);
2067 DECL_ARTIFICIAL (name) = 1;
2068 DECL_NAMELESS (name) = 1;
2069 TYPE_NAME (ctx->record_type) = name;
2070 create_omp_child_function (ctx, false);
2071 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2073 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2075 if (ctx->srecord_type)
2077 name = create_tmp_var_name (".omp_data_a");
2078 name = build_decl (gimple_location (stmt),
2079 TYPE_DECL, name, ctx->srecord_type);
2080 DECL_ARTIFICIAL (name) = 1;
2081 DECL_NAMELESS (name) = 1;
2082 TYPE_NAME (ctx->srecord_type) = name;
2083 create_omp_child_function (ctx, true);
2086 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2088 if (TYPE_FIELDS (ctx->record_type) == NULL)
2090 ctx->record_type = ctx->receiver_decl = NULL;
2091 t = build_int_cst (long_integer_type_node, 0);
2092 gimple_omp_task_set_arg_size (stmt, t);
2093 t = build_int_cst (long_integer_type_node, 1);
2094 gimple_omp_task_set_arg_align (stmt, t);
2096 else
2098 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2099 /* Move VLA fields to the end. */
2100 p = &TYPE_FIELDS (ctx->record_type);
2101 while (*p)
2102 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2103 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2105 *q = *p;
2106 *p = TREE_CHAIN (*p);
2107 TREE_CHAIN (*q) = NULL_TREE;
2108 q = &TREE_CHAIN (*q);
2110 else
2111 p = &DECL_CHAIN (*p);
2112 *p = vla_fields;
2113 layout_type (ctx->record_type);
2114 fixup_child_record_type (ctx);
2115 if (ctx->srecord_type)
2116 layout_type (ctx->srecord_type);
2117 t = fold_convert_loc (loc, long_integer_type_node,
2118 TYPE_SIZE_UNIT (ctx->record_type));
2119 gimple_omp_task_set_arg_size (stmt, t);
2120 t = build_int_cst (long_integer_type_node,
2121 TYPE_ALIGN_UNIT (ctx->record_type));
2122 gimple_omp_task_set_arg_align (stmt, t);
2127 /* Scan an OpenMP loop directive. */
2129 static void
2130 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2132 omp_context *ctx;
2133 size_t i;
2135 ctx = new_omp_context (stmt, outer_ctx);
2137 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2139 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2140 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2142 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2143 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2144 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2145 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2147 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2150 /* Scan an OpenMP sections directive. */
2152 static void
2153 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2155 omp_context *ctx;
2157 ctx = new_omp_context (stmt, outer_ctx);
2158 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2159 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2162 /* Scan an OpenMP single directive. */
2164 static void
2165 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2167 omp_context *ctx;
2168 tree name;
2170 ctx = new_omp_context (stmt, outer_ctx);
2171 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2172 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2173 name = create_tmp_var_name (".omp_copy_s");
2174 name = build_decl (gimple_location (stmt),
2175 TYPE_DECL, name, ctx->record_type);
2176 TYPE_NAME (ctx->record_type) = name;
2178 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2179 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2181 if (TYPE_FIELDS (ctx->record_type) == NULL)
2182 ctx->record_type = NULL;
2183 else
2184 layout_type (ctx->record_type);
2187 /* Scan an OpenMP target{, data, update} directive. */
2189 static void
2190 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2192 omp_context *ctx;
2193 tree name;
2194 int kind = gimple_omp_target_kind (stmt);
2196 ctx = new_omp_context (stmt, outer_ctx);
2197 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2198 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2199 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2200 name = create_tmp_var_name (".omp_data_t");
2201 name = build_decl (gimple_location (stmt),
2202 TYPE_DECL, name, ctx->record_type);
2203 DECL_ARTIFICIAL (name) = 1;
2204 DECL_NAMELESS (name) = 1;
2205 TYPE_NAME (ctx->record_type) = name;
2206 if (kind == GF_OMP_TARGET_KIND_REGION)
2208 create_omp_child_function (ctx, false);
2209 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2212 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2213 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2215 if (TYPE_FIELDS (ctx->record_type) == NULL)
2216 ctx->record_type = ctx->receiver_decl = NULL;
2217 else
2219 TYPE_FIELDS (ctx->record_type)
2220 = nreverse (TYPE_FIELDS (ctx->record_type));
2221 #ifdef ENABLE_CHECKING
2222 tree field;
2223 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2224 for (field = TYPE_FIELDS (ctx->record_type);
2225 field;
2226 field = DECL_CHAIN (field))
2227 gcc_assert (DECL_ALIGN (field) == align);
2228 #endif
2229 layout_type (ctx->record_type);
2230 if (kind == GF_OMP_TARGET_KIND_REGION)
2231 fixup_child_record_type (ctx);
2235 /* Scan an OpenMP teams directive. */
2237 static void
2238 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2240 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2241 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2242 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2245 /* Check OpenMP nesting restrictions. */
2246 static bool
2247 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2249 if (ctx != NULL)
2251 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2252 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2254 error_at (gimple_location (stmt),
2255 "OpenMP constructs may not be nested inside simd region");
2256 return false;
2258 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2260 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2261 || (gimple_omp_for_kind (stmt)
2262 != GF_OMP_FOR_KIND_DISTRIBUTE))
2263 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2265 error_at (gimple_location (stmt),
2266 "only distribute or parallel constructs are allowed to "
2267 "be closely nested inside teams construct");
2268 return false;
2272 switch (gimple_code (stmt))
2274 case GIMPLE_OMP_FOR:
2275 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_KIND_SIMD)
2276 return true;
2277 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2279 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2281 error_at (gimple_location (stmt),
2282 "distribute construct must be closely nested inside "
2283 "teams construct");
2284 return false;
2286 return true;
2288 /* FALLTHRU */
2289 case GIMPLE_CALL:
2290 if (is_gimple_call (stmt)
2291 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2292 == BUILT_IN_GOMP_CANCEL
2293 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2294 == BUILT_IN_GOMP_CANCELLATION_POINT))
2296 const char *bad = NULL;
2297 const char *kind = NULL;
2298 if (ctx == NULL)
2300 error_at (gimple_location (stmt), "orphaned %qs construct",
2301 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2302 == BUILT_IN_GOMP_CANCEL
2303 ? "#pragma omp cancel"
2304 : "#pragma omp cancellation point");
2305 return false;
2307 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2308 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2309 : 0)
2311 case 1:
2312 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2313 bad = "#pragma omp parallel";
2314 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2315 == BUILT_IN_GOMP_CANCEL
2316 && !integer_zerop (gimple_call_arg (stmt, 1)))
2317 ctx->cancellable = true;
2318 kind = "parallel";
2319 break;
2320 case 2:
2321 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2322 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2323 bad = "#pragma omp for";
2324 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2325 == BUILT_IN_GOMP_CANCEL
2326 && !integer_zerop (gimple_call_arg (stmt, 1)))
2328 ctx->cancellable = true;
2329 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2330 OMP_CLAUSE_NOWAIT))
2331 warning_at (gimple_location (stmt), 0,
2332 "%<#pragma omp cancel for%> inside "
2333 "%<nowait%> for construct");
2334 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2335 OMP_CLAUSE_ORDERED))
2336 warning_at (gimple_location (stmt), 0,
2337 "%<#pragma omp cancel for%> inside "
2338 "%<ordered%> for construct");
2340 kind = "for";
2341 break;
2342 case 4:
2343 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2344 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2345 bad = "#pragma omp sections";
2346 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2347 == BUILT_IN_GOMP_CANCEL
2348 && !integer_zerop (gimple_call_arg (stmt, 1)))
2350 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2352 ctx->cancellable = true;
2353 if (find_omp_clause (gimple_omp_sections_clauses
2354 (ctx->stmt),
2355 OMP_CLAUSE_NOWAIT))
2356 warning_at (gimple_location (stmt), 0,
2357 "%<#pragma omp cancel sections%> inside "
2358 "%<nowait%> sections construct");
2360 else
2362 gcc_assert (ctx->outer
2363 && gimple_code (ctx->outer->stmt)
2364 == GIMPLE_OMP_SECTIONS);
2365 ctx->outer->cancellable = true;
2366 if (find_omp_clause (gimple_omp_sections_clauses
2367 (ctx->outer->stmt),
2368 OMP_CLAUSE_NOWAIT))
2369 warning_at (gimple_location (stmt), 0,
2370 "%<#pragma omp cancel sections%> inside "
2371 "%<nowait%> sections construct");
2374 kind = "sections";
2375 break;
2376 case 8:
2377 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2378 bad = "#pragma omp task";
2379 else
2380 ctx->cancellable = true;
2381 kind = "taskgroup";
2382 break;
2383 default:
2384 error_at (gimple_location (stmt), "invalid arguments");
2385 return false;
2387 if (bad)
2389 error_at (gimple_location (stmt),
2390 "%<%s %s%> construct not closely nested inside of %qs",
2391 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2392 == BUILT_IN_GOMP_CANCEL
2393 ? "#pragma omp cancel"
2394 : "#pragma omp cancellation point", kind, bad);
2395 return false;
2398 /* FALLTHRU */
2399 case GIMPLE_OMP_SECTIONS:
2400 case GIMPLE_OMP_SINGLE:
2401 for (; ctx != NULL; ctx = ctx->outer)
2402 switch (gimple_code (ctx->stmt))
2404 case GIMPLE_OMP_FOR:
2405 case GIMPLE_OMP_SECTIONS:
2406 case GIMPLE_OMP_SINGLE:
2407 case GIMPLE_OMP_ORDERED:
2408 case GIMPLE_OMP_MASTER:
2409 case GIMPLE_OMP_TASK:
2410 case GIMPLE_OMP_CRITICAL:
2411 if (is_gimple_call (stmt))
2413 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2414 != BUILT_IN_GOMP_BARRIER)
2415 return true;
2416 error_at (gimple_location (stmt),
2417 "barrier region may not be closely nested inside "
2418 "of work-sharing, critical, ordered, master or "
2419 "explicit task region");
2420 return false;
2422 error_at (gimple_location (stmt),
2423 "work-sharing region may not be closely nested inside "
2424 "of work-sharing, critical, ordered, master or explicit "
2425 "task region");
2426 return false;
2427 case GIMPLE_OMP_PARALLEL:
2428 return true;
2429 default:
2430 break;
2432 break;
2433 case GIMPLE_OMP_MASTER:
2434 for (; ctx != NULL; ctx = ctx->outer)
2435 switch (gimple_code (ctx->stmt))
2437 case GIMPLE_OMP_FOR:
2438 case GIMPLE_OMP_SECTIONS:
2439 case GIMPLE_OMP_SINGLE:
2440 case GIMPLE_OMP_TASK:
2441 error_at (gimple_location (stmt),
2442 "master region may not be closely nested inside "
2443 "of work-sharing or explicit task region");
2444 return false;
2445 case GIMPLE_OMP_PARALLEL:
2446 return true;
2447 default:
2448 break;
2450 break;
2451 case GIMPLE_OMP_ORDERED:
2452 for (; ctx != NULL; ctx = ctx->outer)
2453 switch (gimple_code (ctx->stmt))
2455 case GIMPLE_OMP_CRITICAL:
2456 case GIMPLE_OMP_TASK:
2457 error_at (gimple_location (stmt),
2458 "ordered region may not be closely nested inside "
2459 "of critical or explicit task region");
2460 return false;
2461 case GIMPLE_OMP_FOR:
2462 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2463 OMP_CLAUSE_ORDERED) == NULL)
2465 error_at (gimple_location (stmt),
2466 "ordered region must be closely nested inside "
2467 "a loop region with an ordered clause");
2468 return false;
2470 return true;
2471 case GIMPLE_OMP_PARALLEL:
2472 error_at (gimple_location (stmt),
2473 "ordered region must be closely nested inside "
2474 "a loop region with an ordered clause");
2475 return false;
2476 default:
2477 break;
2479 break;
2480 case GIMPLE_OMP_CRITICAL:
2481 for (; ctx != NULL; ctx = ctx->outer)
2482 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2483 && (gimple_omp_critical_name (stmt)
2484 == gimple_omp_critical_name (ctx->stmt)))
2486 error_at (gimple_location (stmt),
2487 "critical region may not be nested inside a critical "
2488 "region with the same name");
2489 return false;
2491 break;
2492 case GIMPLE_OMP_TEAMS:
2493 if (ctx == NULL
2494 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2495 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2497 error_at (gimple_location (stmt),
2498 "teams construct not closely nested inside of target "
2499 "region");
2500 return false;
2502 break;
2503 default:
2504 break;
2506 return true;
2510 /* Helper function scan_omp.
2512 Callback for walk_tree or operators in walk_gimple_stmt used to
2513 scan for OpenMP directives in TP. */
2515 static tree
2516 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2518 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2519 omp_context *ctx = (omp_context *) wi->info;
2520 tree t = *tp;
2522 switch (TREE_CODE (t))
2524 case VAR_DECL:
2525 case PARM_DECL:
2526 case LABEL_DECL:
2527 case RESULT_DECL:
2528 if (ctx)
2529 *tp = remap_decl (t, &ctx->cb);
2530 break;
2532 default:
2533 if (ctx && TYPE_P (t))
2534 *tp = remap_type (t, &ctx->cb);
2535 else if (!DECL_P (t))
2537 *walk_subtrees = 1;
2538 if (ctx)
2540 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2541 if (tem != TREE_TYPE (t))
2543 if (TREE_CODE (t) == INTEGER_CST)
2544 *tp = build_int_cst_wide (tem,
2545 TREE_INT_CST_LOW (t),
2546 TREE_INT_CST_HIGH (t));
2547 else
2548 TREE_TYPE (t) = tem;
2552 break;
2555 return NULL_TREE;
2558 /* Return true if FNDECL is a setjmp or a longjmp. */
2560 static bool
2561 setjmp_or_longjmp_p (const_tree fndecl)
2563 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2564 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2565 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2566 return true;
2568 tree declname = DECL_NAME (fndecl);
2569 if (!declname)
2570 return false;
2571 const char *name = IDENTIFIER_POINTER (declname);
2572 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2576 /* Helper function for scan_omp.
2578 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2579 the current statement in GSI. */
2581 static tree
2582 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2583 struct walk_stmt_info *wi)
2585 gimple stmt = gsi_stmt (*gsi);
2586 omp_context *ctx = (omp_context *) wi->info;
2588 if (gimple_has_location (stmt))
2589 input_location = gimple_location (stmt);
2591 /* Check the OpenMP nesting restrictions. */
2592 bool remove = false;
2593 if (is_gimple_omp (stmt))
2594 remove = !check_omp_nesting_restrictions (stmt, ctx);
2595 else if (is_gimple_call (stmt))
2597 tree fndecl = gimple_call_fndecl (stmt);
2598 if (fndecl)
2600 if (setjmp_or_longjmp_p (fndecl)
2601 && ctx
2602 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2603 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2605 remove = true;
2606 error_at (gimple_location (stmt),
2607 "setjmp/longjmp inside simd construct");
2609 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2610 switch (DECL_FUNCTION_CODE (fndecl))
2612 case BUILT_IN_GOMP_BARRIER:
2613 case BUILT_IN_GOMP_CANCEL:
2614 case BUILT_IN_GOMP_CANCELLATION_POINT:
2615 case BUILT_IN_GOMP_TASKYIELD:
2616 case BUILT_IN_GOMP_TASKWAIT:
2617 case BUILT_IN_GOMP_TASKGROUP_START:
2618 case BUILT_IN_GOMP_TASKGROUP_END:
2619 remove = !check_omp_nesting_restrictions (stmt, ctx);
2620 break;
2621 default:
2622 break;
2626 if (remove)
2628 stmt = gimple_build_nop ();
2629 gsi_replace (gsi, stmt, false);
2632 *handled_ops_p = true;
2634 switch (gimple_code (stmt))
2636 case GIMPLE_OMP_PARALLEL:
2637 taskreg_nesting_level++;
2638 scan_omp_parallel (gsi, ctx);
2639 taskreg_nesting_level--;
2640 break;
2642 case GIMPLE_OMP_TASK:
2643 taskreg_nesting_level++;
2644 scan_omp_task (gsi, ctx);
2645 taskreg_nesting_level--;
2646 break;
2648 case GIMPLE_OMP_FOR:
2649 scan_omp_for (stmt, ctx);
2650 break;
2652 case GIMPLE_OMP_SECTIONS:
2653 scan_omp_sections (stmt, ctx);
2654 break;
2656 case GIMPLE_OMP_SINGLE:
2657 scan_omp_single (stmt, ctx);
2658 break;
2660 case GIMPLE_OMP_SECTION:
2661 case GIMPLE_OMP_MASTER:
2662 case GIMPLE_OMP_TASKGROUP:
2663 case GIMPLE_OMP_ORDERED:
2664 case GIMPLE_OMP_CRITICAL:
2665 ctx = new_omp_context (stmt, ctx);
2666 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2667 break;
2669 case GIMPLE_OMP_TARGET:
2670 scan_omp_target (stmt, ctx);
2671 break;
2673 case GIMPLE_OMP_TEAMS:
2674 scan_omp_teams (stmt, ctx);
2675 break;
2677 case GIMPLE_BIND:
2679 tree var;
2681 *handled_ops_p = false;
2682 if (ctx)
2683 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2684 insert_decl_map (&ctx->cb, var, var);
2686 break;
2687 default:
2688 *handled_ops_p = false;
2689 break;
2692 return NULL_TREE;
2696 /* Scan all the statements starting at the current statement. CTX
2697 contains context information about the OpenMP directives and
2698 clauses found during the scan. */
2700 static void
2701 scan_omp (gimple_seq *body_p, omp_context *ctx)
2703 location_t saved_location;
2704 struct walk_stmt_info wi;
2706 memset (&wi, 0, sizeof (wi));
2707 wi.info = ctx;
2708 wi.want_locations = true;
2710 saved_location = input_location;
2711 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2712 input_location = saved_location;
2715 /* Re-gimplification and code generation routines. */
2717 /* Build a call to GOMP_barrier. */
2719 static gimple
2720 build_omp_barrier (tree lhs)
2722 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2723 : BUILT_IN_GOMP_BARRIER);
2724 gimple g = gimple_build_call (fndecl, 0);
2725 if (lhs)
2726 gimple_call_set_lhs (g, lhs);
2727 return g;
2730 /* If a context was created for STMT when it was scanned, return it. */
2732 static omp_context *
2733 maybe_lookup_ctx (gimple stmt)
2735 splay_tree_node n;
2736 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2737 return n ? (omp_context *) n->value : NULL;
2741 /* Find the mapping for DECL in CTX or the immediately enclosing
2742 context that has a mapping for DECL.
2744 If CTX is a nested parallel directive, we may have to use the decl
2745 mappings created in CTX's parent context. Suppose that we have the
2746 following parallel nesting (variable UIDs showed for clarity):
2748 iD.1562 = 0;
2749 #omp parallel shared(iD.1562) -> outer parallel
2750 iD.1562 = iD.1562 + 1;
2752 #omp parallel shared (iD.1562) -> inner parallel
2753 iD.1562 = iD.1562 - 1;
2755 Each parallel structure will create a distinct .omp_data_s structure
2756 for copying iD.1562 in/out of the directive:
2758 outer parallel .omp_data_s.1.i -> iD.1562
2759 inner parallel .omp_data_s.2.i -> iD.1562
2761 A shared variable mapping will produce a copy-out operation before
2762 the parallel directive and a copy-in operation after it. So, in
2763 this case we would have:
2765 iD.1562 = 0;
2766 .omp_data_o.1.i = iD.1562;
2767 #omp parallel shared(iD.1562) -> outer parallel
2768 .omp_data_i.1 = &.omp_data_o.1
2769 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2771 .omp_data_o.2.i = iD.1562; -> **
2772 #omp parallel shared(iD.1562) -> inner parallel
2773 .omp_data_i.2 = &.omp_data_o.2
2774 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2777 ** This is a problem. The symbol iD.1562 cannot be referenced
2778 inside the body of the outer parallel region. But since we are
2779 emitting this copy operation while expanding the inner parallel
2780 directive, we need to access the CTX structure of the outer
2781 parallel directive to get the correct mapping:
2783 .omp_data_o.2.i = .omp_data_i.1->i
2785 Since there may be other workshare or parallel directives enclosing
2786 the parallel directive, it may be necessary to walk up the context
2787 parent chain. This is not a problem in general because nested
2788 parallelism happens only rarely. */
2790 static tree
2791 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2793 tree t;
2794 omp_context *up;
2796 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2797 t = maybe_lookup_decl (decl, up);
2799 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2801 return t ? t : decl;
2805 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2806 in outer contexts. */
2808 static tree
2809 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2811 tree t = NULL;
2812 omp_context *up;
2814 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2815 t = maybe_lookup_decl (decl, up);
2817 return t ? t : decl;
2821 /* Construct the initialization value for reduction CLAUSE. */
2823 tree
2824 omp_reduction_init (tree clause, tree type)
2826 location_t loc = OMP_CLAUSE_LOCATION (clause);
2827 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2829 case PLUS_EXPR:
2830 case MINUS_EXPR:
2831 case BIT_IOR_EXPR:
2832 case BIT_XOR_EXPR:
2833 case TRUTH_OR_EXPR:
2834 case TRUTH_ORIF_EXPR:
2835 case TRUTH_XOR_EXPR:
2836 case NE_EXPR:
2837 return build_zero_cst (type);
2839 case MULT_EXPR:
2840 case TRUTH_AND_EXPR:
2841 case TRUTH_ANDIF_EXPR:
2842 case EQ_EXPR:
2843 return fold_convert_loc (loc, type, integer_one_node);
2845 case BIT_AND_EXPR:
2846 return fold_convert_loc (loc, type, integer_minus_one_node);
2848 case MAX_EXPR:
2849 if (SCALAR_FLOAT_TYPE_P (type))
2851 REAL_VALUE_TYPE max, min;
2852 if (HONOR_INFINITIES (TYPE_MODE (type)))
2854 real_inf (&max);
2855 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2857 else
2858 real_maxval (&min, 1, TYPE_MODE (type));
2859 return build_real (type, min);
2861 else
2863 gcc_assert (INTEGRAL_TYPE_P (type));
2864 return TYPE_MIN_VALUE (type);
2867 case MIN_EXPR:
2868 if (SCALAR_FLOAT_TYPE_P (type))
2870 REAL_VALUE_TYPE max;
2871 if (HONOR_INFINITIES (TYPE_MODE (type)))
2872 real_inf (&max);
2873 else
2874 real_maxval (&max, 0, TYPE_MODE (type));
2875 return build_real (type, max);
2877 else
2879 gcc_assert (INTEGRAL_TYPE_P (type));
2880 return TYPE_MAX_VALUE (type);
2883 default:
2884 gcc_unreachable ();
2888 /* Return alignment to be assumed for var in CLAUSE, which should be
2889 OMP_CLAUSE_ALIGNED. */
2891 static tree
2892 omp_clause_aligned_alignment (tree clause)
2894 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
2895 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
2897 /* Otherwise return implementation defined alignment. */
2898 unsigned int al = 1;
2899 enum machine_mode mode, vmode;
2900 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2901 if (vs)
2902 vs = 1 << floor_log2 (vs);
2903 static enum mode_class classes[]
2904 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
2905 for (int i = 0; i < 4; i += 2)
2906 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
2907 mode != VOIDmode;
2908 mode = GET_MODE_WIDER_MODE (mode))
2910 vmode = targetm.vectorize.preferred_simd_mode (mode);
2911 if (GET_MODE_CLASS (vmode) != classes[i + 1])
2912 continue;
2913 while (vs
2914 && GET_MODE_SIZE (vmode) < vs
2915 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
2916 vmode = GET_MODE_2XWIDER_MODE (vmode);
2918 tree type = lang_hooks.types.type_for_mode (mode, 1);
2919 if (type == NULL_TREE || TYPE_MODE (type) != mode)
2920 continue;
2921 type = build_vector_type (type, GET_MODE_SIZE (vmode)
2922 / GET_MODE_SIZE (mode));
2923 if (TYPE_MODE (type) != vmode)
2924 continue;
2925 if (TYPE_ALIGN_UNIT (type) > al)
2926 al = TYPE_ALIGN_UNIT (type);
2928 return build_int_cst (integer_type_node, al);
2931 /* Return maximum possible vectorization factor for the target. */
2933 static int
2934 omp_max_vf (void)
2936 if (!optimize
2937 || optimize_debug
2938 || !flag_tree_loop_optimize
2939 || (!flag_tree_loop_vectorize
2940 && (global_options_set.x_flag_tree_loop_vectorize
2941 || global_options_set.x_flag_tree_vectorize)))
2942 return 1;
2944 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2945 if (vs)
2947 vs = 1 << floor_log2 (vs);
2948 return vs;
2950 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
2951 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
2952 return GET_MODE_NUNITS (vqimode);
2953 return 1;
2956 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2957 privatization. */
2959 static bool
2960 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
2961 tree &idx, tree &lane, tree &ivar, tree &lvar)
2963 if (max_vf == 0)
2965 max_vf = omp_max_vf ();
2966 if (max_vf > 1)
2968 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2969 OMP_CLAUSE_SAFELEN);
2970 if (c
2971 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
2972 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
2974 if (max_vf > 1)
2976 idx = create_tmp_var (unsigned_type_node, NULL);
2977 lane = create_tmp_var (unsigned_type_node, NULL);
2980 if (max_vf == 1)
2981 return false;
2983 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
2984 tree avar = create_tmp_var_raw (atype, NULL);
2985 if (TREE_ADDRESSABLE (new_var))
2986 TREE_ADDRESSABLE (avar) = 1;
2987 DECL_ATTRIBUTES (avar)
2988 = tree_cons (get_identifier ("omp simd array"), NULL,
2989 DECL_ATTRIBUTES (avar));
2990 gimple_add_tmp_var (avar);
2991 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
2992 NULL_TREE, NULL_TREE);
2993 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
2994 NULL_TREE, NULL_TREE);
2995 if (DECL_P (new_var))
2997 SET_DECL_VALUE_EXPR (new_var, lvar);
2998 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3000 return true;
3003 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3004 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3005 private variables. Initialization statements go in ILIST, while calls
3006 to destructors go in DLIST. */
3008 static void
3009 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3010 omp_context *ctx, struct omp_for_data *fd)
3012 tree c, dtor, copyin_seq, x, ptr;
3013 bool copyin_by_ref = false;
3014 bool lastprivate_firstprivate = false;
3015 bool reduction_omp_orig_ref = false;
3016 int pass;
3017 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3018 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD);
3019 int max_vf = 0;
3020 tree lane = NULL_TREE, idx = NULL_TREE;
3021 tree ivar = NULL_TREE, lvar = NULL_TREE;
3022 gimple_seq llist[2] = { NULL, NULL };
3024 copyin_seq = NULL;
3026 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3027 with data sharing clauses referencing variable sized vars. That
3028 is unnecessarily hard to support and very unlikely to result in
3029 vectorized code anyway. */
3030 if (is_simd)
3031 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3032 switch (OMP_CLAUSE_CODE (c))
3034 case OMP_CLAUSE_REDUCTION:
3035 case OMP_CLAUSE_PRIVATE:
3036 case OMP_CLAUSE_FIRSTPRIVATE:
3037 case OMP_CLAUSE_LASTPRIVATE:
3038 case OMP_CLAUSE_LINEAR:
3039 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3040 max_vf = 1;
3041 break;
3042 default:
3043 continue;
3046 /* Do all the fixed sized types in the first pass, and the variable sized
3047 types in the second pass. This makes sure that the scalar arguments to
3048 the variable sized types are processed before we use them in the
3049 variable sized operations. */
3050 for (pass = 0; pass < 2; ++pass)
3052 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3054 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3055 tree var, new_var;
3056 bool by_ref;
3057 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3059 switch (c_kind)
3061 case OMP_CLAUSE_PRIVATE:
3062 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3063 continue;
3064 break;
3065 case OMP_CLAUSE_SHARED:
3066 /* Ignore shared directives in teams construct. */
3067 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3068 continue;
3069 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3071 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3072 continue;
3074 case OMP_CLAUSE_FIRSTPRIVATE:
3075 case OMP_CLAUSE_COPYIN:
3076 case OMP_CLAUSE_LINEAR:
3077 break;
3078 case OMP_CLAUSE_REDUCTION:
3079 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3080 reduction_omp_orig_ref = true;
3081 break;
3082 case OMP_CLAUSE__LOOPTEMP_:
3083 /* Handle _looptemp_ clauses only on parallel. */
3084 if (fd)
3085 continue;
3086 break;
3087 case OMP_CLAUSE_LASTPRIVATE:
3088 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3090 lastprivate_firstprivate = true;
3091 if (pass != 0)
3092 continue;
3094 break;
3095 case OMP_CLAUSE_ALIGNED:
3096 if (pass == 0)
3097 continue;
3098 var = OMP_CLAUSE_DECL (c);
3099 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3100 && !is_global_var (var))
3102 new_var = maybe_lookup_decl (var, ctx);
3103 if (new_var == NULL_TREE)
3104 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3105 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3106 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3107 omp_clause_aligned_alignment (c));
3108 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3109 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3110 gimplify_and_add (x, ilist);
3112 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3113 && is_global_var (var))
3115 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3116 new_var = lookup_decl (var, ctx);
3117 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3118 t = build_fold_addr_expr_loc (clause_loc, t);
3119 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3120 t = build_call_expr_loc (clause_loc, t2, 2, t,
3121 omp_clause_aligned_alignment (c));
3122 t = fold_convert_loc (clause_loc, ptype, t);
3123 x = create_tmp_var (ptype, NULL);
3124 t = build2 (MODIFY_EXPR, ptype, x, t);
3125 gimplify_and_add (t, ilist);
3126 t = build_simple_mem_ref_loc (clause_loc, x);
3127 SET_DECL_VALUE_EXPR (new_var, t);
3128 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3130 continue;
3131 default:
3132 continue;
3135 new_var = var = OMP_CLAUSE_DECL (c);
3136 if (c_kind != OMP_CLAUSE_COPYIN)
3137 new_var = lookup_decl (var, ctx);
3139 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3141 if (pass != 0)
3142 continue;
3144 else if (is_variable_sized (var))
3146 /* For variable sized types, we need to allocate the
3147 actual storage here. Call alloca and store the
3148 result in the pointer decl that we created elsewhere. */
3149 if (pass == 0)
3150 continue;
3152 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3154 gimple stmt;
3155 tree tmp, atmp;
3157 ptr = DECL_VALUE_EXPR (new_var);
3158 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3159 ptr = TREE_OPERAND (ptr, 0);
3160 gcc_assert (DECL_P (ptr));
3161 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3163 /* void *tmp = __builtin_alloca */
3164 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3165 stmt = gimple_build_call (atmp, 1, x);
3166 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3167 gimple_add_tmp_var (tmp);
3168 gimple_call_set_lhs (stmt, tmp);
3170 gimple_seq_add_stmt (ilist, stmt);
3172 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3173 gimplify_assign (ptr, x, ilist);
3176 else if (is_reference (var))
3178 /* For references that are being privatized for Fortran,
3179 allocate new backing storage for the new pointer
3180 variable. This allows us to avoid changing all the
3181 code that expects a pointer to something that expects
3182 a direct variable. */
3183 if (pass == 0)
3184 continue;
3186 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3187 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3189 x = build_receiver_ref (var, false, ctx);
3190 x = build_fold_addr_expr_loc (clause_loc, x);
3192 else if (TREE_CONSTANT (x))
3194 /* For reduction with placeholder in SIMD loop,
3195 defer adding the initialization of the reference,
3196 because if we decide to use SIMD array for it,
3197 the initilization could cause expansion ICE. */
3198 if (c_kind == OMP_CLAUSE_REDUCTION
3199 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
3200 && is_simd)
3201 x = NULL_TREE;
3202 else
3204 const char *name = NULL;
3205 if (DECL_NAME (var))
3206 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3208 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3209 name);
3210 gimple_add_tmp_var (x);
3211 TREE_ADDRESSABLE (x) = 1;
3212 x = build_fold_addr_expr_loc (clause_loc, x);
3215 else
3217 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3218 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3221 if (x)
3223 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3224 gimplify_assign (new_var, x, ilist);
3227 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3229 else if (c_kind == OMP_CLAUSE_REDUCTION
3230 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3232 if (pass == 0)
3233 continue;
3235 else if (pass != 0)
3236 continue;
3238 switch (OMP_CLAUSE_CODE (c))
3240 case OMP_CLAUSE_SHARED:
3241 /* Ignore shared directives in teams construct. */
3242 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3243 continue;
3244 /* Shared global vars are just accessed directly. */
3245 if (is_global_var (new_var))
3246 break;
3247 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3248 needs to be delayed until after fixup_child_record_type so
3249 that we get the correct type during the dereference. */
3250 by_ref = use_pointer_for_field (var, ctx);
3251 x = build_receiver_ref (var, by_ref, ctx);
3252 SET_DECL_VALUE_EXPR (new_var, x);
3253 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3255 /* ??? If VAR is not passed by reference, and the variable
3256 hasn't been initialized yet, then we'll get a warning for
3257 the store into the omp_data_s structure. Ideally, we'd be
3258 able to notice this and not store anything at all, but
3259 we're generating code too early. Suppress the warning. */
3260 if (!by_ref)
3261 TREE_NO_WARNING (var) = 1;
3262 break;
3264 case OMP_CLAUSE_LASTPRIVATE:
3265 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3266 break;
3267 /* FALLTHRU */
3269 case OMP_CLAUSE_PRIVATE:
3270 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3271 x = build_outer_var_ref (var, ctx);
3272 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3274 if (is_task_ctx (ctx))
3275 x = build_receiver_ref (var, false, ctx);
3276 else
3277 x = build_outer_var_ref (var, ctx);
3279 else
3280 x = NULL;
3281 do_private:
3282 tree nx;
3283 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3284 if (is_simd)
3286 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3287 if ((TREE_ADDRESSABLE (new_var) || nx || y
3288 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3289 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3290 idx, lane, ivar, lvar))
3292 if (nx)
3293 x = lang_hooks.decls.omp_clause_default_ctor
3294 (c, unshare_expr (ivar), x);
3295 if (nx && x)
3296 gimplify_and_add (x, &llist[0]);
3297 if (y)
3299 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3300 if (y)
3302 gimple_seq tseq = NULL;
3304 dtor = y;
3305 gimplify_stmt (&dtor, &tseq);
3306 gimple_seq_add_seq (&llist[1], tseq);
3309 break;
3312 if (nx)
3313 gimplify_and_add (nx, ilist);
3314 /* FALLTHRU */
3316 do_dtor:
3317 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3318 if (x)
3320 gimple_seq tseq = NULL;
3322 dtor = x;
3323 gimplify_stmt (&dtor, &tseq);
3324 gimple_seq_add_seq (dlist, tseq);
3326 break;
3328 case OMP_CLAUSE_LINEAR:
3329 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3330 goto do_firstprivate;
3331 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3332 x = NULL;
3333 else
3334 x = build_outer_var_ref (var, ctx);
3335 goto do_private;
3337 case OMP_CLAUSE_FIRSTPRIVATE:
3338 if (is_task_ctx (ctx))
3340 if (is_reference (var) || is_variable_sized (var))
3341 goto do_dtor;
3342 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3343 ctx))
3344 || use_pointer_for_field (var, NULL))
3346 x = build_receiver_ref (var, false, ctx);
3347 SET_DECL_VALUE_EXPR (new_var, x);
3348 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3349 goto do_dtor;
3352 do_firstprivate:
3353 x = build_outer_var_ref (var, ctx);
3354 if (is_simd)
3356 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3357 && gimple_omp_for_combined_into_p (ctx->stmt))
3359 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3360 ? sizetype : TREE_TYPE (x);
3361 tree t = fold_convert (stept,
3362 OMP_CLAUSE_LINEAR_STEP (c));
3363 tree c = find_omp_clause (clauses,
3364 OMP_CLAUSE__LOOPTEMP_);
3365 gcc_assert (c);
3366 tree l = OMP_CLAUSE_DECL (c);
3367 if (fd->collapse == 1)
3369 tree n1 = fd->loop.n1;
3370 tree step = fd->loop.step;
3371 tree itype = TREE_TYPE (l);
3372 if (POINTER_TYPE_P (itype))
3373 itype = signed_type_for (itype);
3374 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3375 if (TYPE_UNSIGNED (itype)
3376 && fd->loop.cond_code == GT_EXPR)
3377 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3378 fold_build1 (NEGATE_EXPR,
3379 itype, l),
3380 fold_build1 (NEGATE_EXPR,
3381 itype, step));
3382 else
3383 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3385 t = fold_build2 (MULT_EXPR, stept,
3386 fold_convert (stept, l), t);
3387 if (POINTER_TYPE_P (TREE_TYPE (x)))
3388 x = fold_build2 (POINTER_PLUS_EXPR,
3389 TREE_TYPE (x), x, t);
3390 else
3391 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3394 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3395 || TREE_ADDRESSABLE (new_var))
3396 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3397 idx, lane, ivar, lvar))
3399 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3401 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3402 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3403 gimplify_and_add (x, ilist);
3404 gimple_stmt_iterator gsi
3405 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3406 gimple g
3407 = gimple_build_assign (unshare_expr (lvar), iv);
3408 gsi_insert_before_without_update (&gsi, g,
3409 GSI_SAME_STMT);
3410 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3411 ? sizetype : TREE_TYPE (x);
3412 tree t = fold_convert (stept,
3413 OMP_CLAUSE_LINEAR_STEP (c));
3414 enum tree_code code = PLUS_EXPR;
3415 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3416 code = POINTER_PLUS_EXPR;
3417 g = gimple_build_assign_with_ops (code, iv, iv, t);
3418 gsi_insert_before_without_update (&gsi, g,
3419 GSI_SAME_STMT);
3420 break;
3422 x = lang_hooks.decls.omp_clause_copy_ctor
3423 (c, unshare_expr (ivar), x);
3424 gimplify_and_add (x, &llist[0]);
3425 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3426 if (x)
3428 gimple_seq tseq = NULL;
3430 dtor = x;
3431 gimplify_stmt (&dtor, &tseq);
3432 gimple_seq_add_seq (&llist[1], tseq);
3434 break;
3437 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3438 gimplify_and_add (x, ilist);
3439 goto do_dtor;
3441 case OMP_CLAUSE__LOOPTEMP_:
3442 gcc_assert (is_parallel_ctx (ctx));
3443 x = build_outer_var_ref (var, ctx);
3444 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3445 gimplify_and_add (x, ilist);
3446 break;
3448 case OMP_CLAUSE_COPYIN:
3449 by_ref = use_pointer_for_field (var, NULL);
3450 x = build_receiver_ref (var, by_ref, ctx);
3451 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3452 append_to_statement_list (x, &copyin_seq);
3453 copyin_by_ref |= by_ref;
3454 break;
3456 case OMP_CLAUSE_REDUCTION:
3457 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3459 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3460 gimple tseq;
3461 x = build_outer_var_ref (var, ctx);
3463 if (is_reference (var)
3464 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3465 TREE_TYPE (x)))
3466 x = build_fold_addr_expr_loc (clause_loc, x);
3467 SET_DECL_VALUE_EXPR (placeholder, x);
3468 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3469 tree new_vard = new_var;
3470 if (is_reference (var))
3472 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3473 new_vard = TREE_OPERAND (new_var, 0);
3474 gcc_assert (DECL_P (new_vard));
3476 if (is_simd
3477 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3478 idx, lane, ivar, lvar))
3480 if (new_vard == new_var)
3482 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3483 SET_DECL_VALUE_EXPR (new_var, ivar);
3485 else
3487 SET_DECL_VALUE_EXPR (new_vard,
3488 build_fold_addr_expr (ivar));
3489 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3491 x = lang_hooks.decls.omp_clause_default_ctor
3492 (c, unshare_expr (ivar),
3493 build_outer_var_ref (var, ctx));
3494 if (x)
3495 gimplify_and_add (x, &llist[0]);
3496 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3498 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3499 lower_omp (&tseq, ctx);
3500 gimple_seq_add_seq (&llist[0], tseq);
3502 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3503 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3504 lower_omp (&tseq, ctx);
3505 gimple_seq_add_seq (&llist[1], tseq);
3506 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3507 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3508 if (new_vard == new_var)
3509 SET_DECL_VALUE_EXPR (new_var, lvar);
3510 else
3511 SET_DECL_VALUE_EXPR (new_vard,
3512 build_fold_addr_expr (lvar));
3513 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3514 if (x)
3516 tseq = NULL;
3517 dtor = x;
3518 gimplify_stmt (&dtor, &tseq);
3519 gimple_seq_add_seq (&llist[1], tseq);
3521 break;
3523 /* If this is a reference to constant size reduction var
3524 with placeholder, we haven't emitted the initializer
3525 for it because it is undesirable if SIMD arrays are used.
3526 But if they aren't used, we need to emit the deferred
3527 initialization now. */
3528 else if (is_reference (var) && is_simd)
3530 tree z
3531 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3532 if (TREE_CONSTANT (z))
3534 const char *name = NULL;
3535 if (DECL_NAME (var))
3536 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3538 z = create_tmp_var_raw
3539 (TREE_TYPE (TREE_TYPE (new_vard)), name);
3540 gimple_add_tmp_var (z);
3541 TREE_ADDRESSABLE (z) = 1;
3542 z = build_fold_addr_expr_loc (clause_loc, z);
3543 gimplify_assign (new_vard, z, ilist);
3546 x = lang_hooks.decls.omp_clause_default_ctor
3547 (c, new_var, unshare_expr (x));
3548 if (x)
3549 gimplify_and_add (x, ilist);
3550 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3552 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3553 lower_omp (&tseq, ctx);
3554 gimple_seq_add_seq (ilist, tseq);
3556 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3557 if (is_simd)
3559 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3560 lower_omp (&tseq, ctx);
3561 gimple_seq_add_seq (dlist, tseq);
3562 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3564 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3565 goto do_dtor;
3567 else
3569 x = omp_reduction_init (c, TREE_TYPE (new_var));
3570 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3571 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3573 /* reduction(-:var) sums up the partial results, so it
3574 acts identically to reduction(+:var). */
3575 if (code == MINUS_EXPR)
3576 code = PLUS_EXPR;
3578 if (is_simd
3579 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3580 idx, lane, ivar, lvar))
3582 tree ref = build_outer_var_ref (var, ctx);
3584 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3586 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3587 ref = build_outer_var_ref (var, ctx);
3588 gimplify_assign (ref, x, &llist[1]);
3590 else
3592 gimplify_assign (new_var, x, ilist);
3593 if (is_simd)
3595 tree ref = build_outer_var_ref (var, ctx);
3597 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3598 ref = build_outer_var_ref (var, ctx);
3599 gimplify_assign (ref, x, dlist);
3603 break;
3605 default:
3606 gcc_unreachable ();
3611 if (lane)
3613 tree uid = create_tmp_var (ptr_type_node, "simduid");
3614 /* Don't want uninit warnings on simduid, it is always uninitialized,
3615 but we use it not for the value, but for the DECL_UID only. */
3616 TREE_NO_WARNING (uid) = 1;
3617 gimple g
3618 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3619 gimple_call_set_lhs (g, lane);
3620 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3621 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3622 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3623 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3624 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3625 gimple_omp_for_set_clauses (ctx->stmt, c);
3626 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3627 build_int_cst (unsigned_type_node, 0),
3628 NULL_TREE);
3629 gimple_seq_add_stmt (ilist, g);
3630 for (int i = 0; i < 2; i++)
3631 if (llist[i])
3633 tree vf = create_tmp_var (unsigned_type_node, NULL);
3634 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3635 gimple_call_set_lhs (g, vf);
3636 gimple_seq *seq = i == 0 ? ilist : dlist;
3637 gimple_seq_add_stmt (seq, g);
3638 tree t = build_int_cst (unsigned_type_node, 0);
3639 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3640 gimple_seq_add_stmt (seq, g);
3641 tree body = create_artificial_label (UNKNOWN_LOCATION);
3642 tree header = create_artificial_label (UNKNOWN_LOCATION);
3643 tree end = create_artificial_label (UNKNOWN_LOCATION);
3644 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3645 gimple_seq_add_stmt (seq, gimple_build_label (body));
3646 gimple_seq_add_seq (seq, llist[i]);
3647 t = build_int_cst (unsigned_type_node, 1);
3648 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3649 gimple_seq_add_stmt (seq, g);
3650 gimple_seq_add_stmt (seq, gimple_build_label (header));
3651 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3652 gimple_seq_add_stmt (seq, g);
3653 gimple_seq_add_stmt (seq, gimple_build_label (end));
3657 /* The copyin sequence is not to be executed by the main thread, since
3658 that would result in self-copies. Perhaps not visible to scalars,
3659 but it certainly is to C++ operator=. */
3660 if (copyin_seq)
3662 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3664 x = build2 (NE_EXPR, boolean_type_node, x,
3665 build_int_cst (TREE_TYPE (x), 0));
3666 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3667 gimplify_and_add (x, ilist);
3670 /* If any copyin variable is passed by reference, we must ensure the
3671 master thread doesn't modify it before it is copied over in all
3672 threads. Similarly for variables in both firstprivate and
3673 lastprivate clauses we need to ensure the lastprivate copying
3674 happens after firstprivate copying in all threads. And similarly
3675 for UDRs if initializer expression refers to omp_orig. */
3676 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3678 /* Don't add any barrier for #pragma omp simd or
3679 #pragma omp distribute. */
3680 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3681 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3682 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3685 /* If max_vf is non-zero, then we can use only a vectorization factor
3686 up to the max_vf we chose. So stick it into the safelen clause. */
3687 if (max_vf)
3689 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3690 OMP_CLAUSE_SAFELEN);
3691 if (c == NULL_TREE
3692 || compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3693 max_vf) == 1)
3695 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3696 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3697 max_vf);
3698 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3699 gimple_omp_for_set_clauses (ctx->stmt, c);
3705 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3706 both parallel and workshare constructs. PREDICATE may be NULL if it's
3707 always true. */
3709 static void
3710 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3711 omp_context *ctx)
3713 tree x, c, label = NULL, orig_clauses = clauses;
3714 bool par_clauses = false;
3715 tree simduid = NULL, lastlane = NULL;
3717 /* Early exit if there are no lastprivate or linear clauses. */
3718 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3719 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3720 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3721 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3722 break;
3723 if (clauses == NULL)
3725 /* If this was a workshare clause, see if it had been combined
3726 with its parallel. In that case, look for the clauses on the
3727 parallel statement itself. */
3728 if (is_parallel_ctx (ctx))
3729 return;
3731 ctx = ctx->outer;
3732 if (ctx == NULL || !is_parallel_ctx (ctx))
3733 return;
3735 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3736 OMP_CLAUSE_LASTPRIVATE);
3737 if (clauses == NULL)
3738 return;
3739 par_clauses = true;
3742 if (predicate)
3744 gimple stmt;
3745 tree label_true, arm1, arm2;
3747 label = create_artificial_label (UNKNOWN_LOCATION);
3748 label_true = create_artificial_label (UNKNOWN_LOCATION);
3749 arm1 = TREE_OPERAND (predicate, 0);
3750 arm2 = TREE_OPERAND (predicate, 1);
3751 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3752 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3753 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3754 label_true, label);
3755 gimple_seq_add_stmt (stmt_list, stmt);
3756 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3759 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3760 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
3762 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3763 if (simduid)
3764 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3767 for (c = clauses; c ;)
3769 tree var, new_var;
3770 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3772 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3773 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3774 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3776 var = OMP_CLAUSE_DECL (c);
3777 new_var = lookup_decl (var, ctx);
3779 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3781 tree val = DECL_VALUE_EXPR (new_var);
3782 if (TREE_CODE (val) == ARRAY_REF
3783 && VAR_P (TREE_OPERAND (val, 0))
3784 && lookup_attribute ("omp simd array",
3785 DECL_ATTRIBUTES (TREE_OPERAND (val,
3786 0))))
3788 if (lastlane == NULL)
3790 lastlane = create_tmp_var (unsigned_type_node, NULL);
3791 gimple g
3792 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
3793 2, simduid,
3794 TREE_OPERAND (val, 1));
3795 gimple_call_set_lhs (g, lastlane);
3796 gimple_seq_add_stmt (stmt_list, g);
3798 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
3799 TREE_OPERAND (val, 0), lastlane,
3800 NULL_TREE, NULL_TREE);
3804 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3805 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
3807 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
3808 gimple_seq_add_seq (stmt_list,
3809 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3810 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
3812 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3813 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
3815 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
3816 gimple_seq_add_seq (stmt_list,
3817 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
3818 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
3821 x = build_outer_var_ref (var, ctx);
3822 if (is_reference (var))
3823 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3824 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
3825 gimplify_and_add (x, stmt_list);
3827 c = OMP_CLAUSE_CHAIN (c);
3828 if (c == NULL && !par_clauses)
3830 /* If this was a workshare clause, see if it had been combined
3831 with its parallel. In that case, continue looking for the
3832 clauses also on the parallel statement itself. */
3833 if (is_parallel_ctx (ctx))
3834 break;
3836 ctx = ctx->outer;
3837 if (ctx == NULL || !is_parallel_ctx (ctx))
3838 break;
3840 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3841 OMP_CLAUSE_LASTPRIVATE);
3842 par_clauses = true;
3846 if (label)
3847 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
3851 /* Generate code to implement the REDUCTION clauses. */
3853 static void
3854 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
3856 gimple_seq sub_seq = NULL;
3857 gimple stmt;
3858 tree x, c;
3859 int count = 0;
3861 /* SIMD reductions are handled in lower_rec_input_clauses. */
3862 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3863 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
3864 return;
3866 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3867 update in that case, otherwise use a lock. */
3868 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
3869 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
3871 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3873 /* Never use OMP_ATOMIC for array reductions or UDRs. */
3874 count = -1;
3875 break;
3877 count++;
3880 if (count == 0)
3881 return;
3883 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3885 tree var, ref, new_var;
3886 enum tree_code code;
3887 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3889 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
3890 continue;
3892 var = OMP_CLAUSE_DECL (c);
3893 new_var = lookup_decl (var, ctx);
3894 if (is_reference (var))
3895 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3896 ref = build_outer_var_ref (var, ctx);
3897 code = OMP_CLAUSE_REDUCTION_CODE (c);
3899 /* reduction(-:var) sums up the partial results, so it acts
3900 identically to reduction(+:var). */
3901 if (code == MINUS_EXPR)
3902 code = PLUS_EXPR;
3904 if (count == 1)
3906 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
3908 addr = save_expr (addr);
3909 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
3910 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
3911 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
3912 gimplify_and_add (x, stmt_seqp);
3913 return;
3916 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3918 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3920 if (is_reference (var)
3921 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3922 TREE_TYPE (ref)))
3923 ref = build_fold_addr_expr_loc (clause_loc, ref);
3924 SET_DECL_VALUE_EXPR (placeholder, ref);
3925 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3926 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
3927 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
3928 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3929 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
3931 else
3933 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3934 ref = build_outer_var_ref (var, ctx);
3935 gimplify_assign (ref, x, &sub_seq);
3939 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
3941 gimple_seq_add_stmt (stmt_seqp, stmt);
3943 gimple_seq_add_seq (stmt_seqp, sub_seq);
3945 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
3947 gimple_seq_add_stmt (stmt_seqp, stmt);
3951 /* Generate code to implement the COPYPRIVATE clauses. */
3953 static void
3954 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
3955 omp_context *ctx)
3957 tree c;
3959 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3961 tree var, new_var, ref, x;
3962 bool by_ref;
3963 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3965 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
3966 continue;
3968 var = OMP_CLAUSE_DECL (c);
3969 by_ref = use_pointer_for_field (var, NULL);
3971 ref = build_sender_ref (var, ctx);
3972 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
3973 if (by_ref)
3975 x = build_fold_addr_expr_loc (clause_loc, new_var);
3976 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
3978 gimplify_assign (ref, x, slist);
3980 ref = build_receiver_ref (var, false, ctx);
3981 if (by_ref)
3983 ref = fold_convert_loc (clause_loc,
3984 build_pointer_type (TREE_TYPE (new_var)),
3985 ref);
3986 ref = build_fold_indirect_ref_loc (clause_loc, ref);
3988 if (is_reference (var))
3990 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
3991 ref = build_simple_mem_ref_loc (clause_loc, ref);
3992 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3994 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
3995 gimplify_and_add (x, rlist);
4000 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4001 and REDUCTION from the sender (aka parent) side. */
4003 static void
4004 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4005 omp_context *ctx)
4007 tree c;
4009 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4011 tree val, ref, x, var;
4012 bool by_ref, do_in = false, do_out = false;
4013 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4015 switch (OMP_CLAUSE_CODE (c))
4017 case OMP_CLAUSE_PRIVATE:
4018 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4019 break;
4020 continue;
4021 case OMP_CLAUSE_FIRSTPRIVATE:
4022 case OMP_CLAUSE_COPYIN:
4023 case OMP_CLAUSE_LASTPRIVATE:
4024 case OMP_CLAUSE_REDUCTION:
4025 case OMP_CLAUSE__LOOPTEMP_:
4026 break;
4027 default:
4028 continue;
4031 val = OMP_CLAUSE_DECL (c);
4032 var = lookup_decl_in_outer_ctx (val, ctx);
4034 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4035 && is_global_var (var))
4036 continue;
4037 if (is_variable_sized (val))
4038 continue;
4039 by_ref = use_pointer_for_field (val, NULL);
4041 switch (OMP_CLAUSE_CODE (c))
4043 case OMP_CLAUSE_PRIVATE:
4044 case OMP_CLAUSE_FIRSTPRIVATE:
4045 case OMP_CLAUSE_COPYIN:
4046 case OMP_CLAUSE__LOOPTEMP_:
4047 do_in = true;
4048 break;
4050 case OMP_CLAUSE_LASTPRIVATE:
4051 if (by_ref || is_reference (val))
4053 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4054 continue;
4055 do_in = true;
4057 else
4059 do_out = true;
4060 if (lang_hooks.decls.omp_private_outer_ref (val))
4061 do_in = true;
4063 break;
4065 case OMP_CLAUSE_REDUCTION:
4066 do_in = true;
4067 do_out = !(by_ref || is_reference (val));
4068 break;
4070 default:
4071 gcc_unreachable ();
4074 if (do_in)
4076 ref = build_sender_ref (val, ctx);
4077 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4078 gimplify_assign (ref, x, ilist);
4079 if (is_task_ctx (ctx))
4080 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4083 if (do_out)
4085 ref = build_sender_ref (val, ctx);
4086 gimplify_assign (var, ref, olist);
4091 /* Generate code to implement SHARED from the sender (aka parent)
4092 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4093 list things that got automatically shared. */
4095 static void
4096 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4098 tree var, ovar, nvar, f, x, record_type;
4100 if (ctx->record_type == NULL)
4101 return;
4103 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4104 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4106 ovar = DECL_ABSTRACT_ORIGIN (f);
4107 nvar = maybe_lookup_decl (ovar, ctx);
4108 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4109 continue;
4111 /* If CTX is a nested parallel directive. Find the immediately
4112 enclosing parallel or workshare construct that contains a
4113 mapping for OVAR. */
4114 var = lookup_decl_in_outer_ctx (ovar, ctx);
4116 if (use_pointer_for_field (ovar, ctx))
4118 x = build_sender_ref (ovar, ctx);
4119 var = build_fold_addr_expr (var);
4120 gimplify_assign (x, var, ilist);
4122 else
4124 x = build_sender_ref (ovar, ctx);
4125 gimplify_assign (x, var, ilist);
4127 if (!TREE_READONLY (var)
4128 /* We don't need to receive a new reference to a result
4129 or parm decl. In fact we may not store to it as we will
4130 invalidate any pending RSO and generate wrong gimple
4131 during inlining. */
4132 && !((TREE_CODE (var) == RESULT_DECL
4133 || TREE_CODE (var) == PARM_DECL)
4134 && DECL_BY_REFERENCE (var)))
4136 x = build_sender_ref (ovar, ctx);
4137 gimplify_assign (var, x, olist);
4144 /* A convenience function to build an empty GIMPLE_COND with just the
4145 condition. */
4147 static gimple
4148 gimple_build_cond_empty (tree cond)
4150 enum tree_code pred_code;
4151 tree lhs, rhs;
4153 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4154 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4158 /* Build the function calls to GOMP_parallel_start etc to actually
4159 generate the parallel operation. REGION is the parallel region
4160 being expanded. BB is the block where to insert the code. WS_ARGS
4161 will be set if this is a call to a combined parallel+workshare
4162 construct, it contains the list of additional arguments needed by
4163 the workshare construct. */
4165 static void
4166 expand_parallel_call (struct omp_region *region, basic_block bb,
4167 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4169 tree t, t1, t2, val, cond, c, clauses, flags;
4170 gimple_stmt_iterator gsi;
4171 gimple stmt;
4172 enum built_in_function start_ix;
4173 int start_ix2;
4174 location_t clause_loc;
4175 vec<tree, va_gc> *args;
4177 clauses = gimple_omp_parallel_clauses (entry_stmt);
4179 /* Determine what flavor of GOMP_parallel we will be
4180 emitting. */
4181 start_ix = BUILT_IN_GOMP_PARALLEL;
4182 if (is_combined_parallel (region))
4184 switch (region->inner->type)
4186 case GIMPLE_OMP_FOR:
4187 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4188 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4189 + (region->inner->sched_kind
4190 == OMP_CLAUSE_SCHEDULE_RUNTIME
4191 ? 3 : region->inner->sched_kind));
4192 start_ix = (enum built_in_function)start_ix2;
4193 break;
4194 case GIMPLE_OMP_SECTIONS:
4195 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4196 break;
4197 default:
4198 gcc_unreachable ();
4202 /* By default, the value of NUM_THREADS is zero (selected at run time)
4203 and there is no conditional. */
4204 cond = NULL_TREE;
4205 val = build_int_cst (unsigned_type_node, 0);
4206 flags = build_int_cst (unsigned_type_node, 0);
4208 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4209 if (c)
4210 cond = OMP_CLAUSE_IF_EXPR (c);
4212 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4213 if (c)
4215 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4216 clause_loc = OMP_CLAUSE_LOCATION (c);
4218 else
4219 clause_loc = gimple_location (entry_stmt);
4221 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4222 if (c)
4223 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4225 /* Ensure 'val' is of the correct type. */
4226 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4228 /* If we found the clause 'if (cond)', build either
4229 (cond != 0) or (cond ? val : 1u). */
4230 if (cond)
4232 gimple_stmt_iterator gsi;
4234 cond = gimple_boolify (cond);
4236 if (integer_zerop (val))
4237 val = fold_build2_loc (clause_loc,
4238 EQ_EXPR, unsigned_type_node, cond,
4239 build_int_cst (TREE_TYPE (cond), 0));
4240 else
4242 basic_block cond_bb, then_bb, else_bb;
4243 edge e, e_then, e_else;
4244 tree tmp_then, tmp_else, tmp_join, tmp_var;
4246 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4247 if (gimple_in_ssa_p (cfun))
4249 tmp_then = make_ssa_name (tmp_var, NULL);
4250 tmp_else = make_ssa_name (tmp_var, NULL);
4251 tmp_join = make_ssa_name (tmp_var, NULL);
4253 else
4255 tmp_then = tmp_var;
4256 tmp_else = tmp_var;
4257 tmp_join = tmp_var;
4260 e = split_block (bb, NULL);
4261 cond_bb = e->src;
4262 bb = e->dest;
4263 remove_edge (e);
4265 then_bb = create_empty_bb (cond_bb);
4266 else_bb = create_empty_bb (then_bb);
4267 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4268 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4270 stmt = gimple_build_cond_empty (cond);
4271 gsi = gsi_start_bb (cond_bb);
4272 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4274 gsi = gsi_start_bb (then_bb);
4275 stmt = gimple_build_assign (tmp_then, val);
4276 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4278 gsi = gsi_start_bb (else_bb);
4279 stmt = gimple_build_assign
4280 (tmp_else, build_int_cst (unsigned_type_node, 1));
4281 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4283 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4284 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4285 if (current_loops)
4287 add_bb_to_loop (then_bb, cond_bb->loop_father);
4288 add_bb_to_loop (else_bb, cond_bb->loop_father);
4290 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4291 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4293 if (gimple_in_ssa_p (cfun))
4295 gimple phi = create_phi_node (tmp_join, bb);
4296 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4297 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4300 val = tmp_join;
4303 gsi = gsi_start_bb (bb);
4304 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4305 false, GSI_CONTINUE_LINKING);
4308 gsi = gsi_last_bb (bb);
4309 t = gimple_omp_parallel_data_arg (entry_stmt);
4310 if (t == NULL)
4311 t1 = null_pointer_node;
4312 else
4313 t1 = build_fold_addr_expr (t);
4314 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4316 vec_alloc (args, 4 + vec_safe_length (ws_args));
4317 args->quick_push (t2);
4318 args->quick_push (t1);
4319 args->quick_push (val);
4320 if (ws_args)
4321 args->splice (*ws_args);
4322 args->quick_push (flags);
4324 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4325 builtin_decl_explicit (start_ix), args);
4327 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4328 false, GSI_CONTINUE_LINKING);
4332 /* Build the function call to GOMP_task to actually
4333 generate the task operation. BB is the block where to insert the code. */
4335 static void
4336 expand_task_call (basic_block bb, gimple entry_stmt)
4338 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4339 gimple_stmt_iterator gsi;
4340 location_t loc = gimple_location (entry_stmt);
4342 clauses = gimple_omp_task_clauses (entry_stmt);
4344 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4345 if (c)
4346 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4347 else
4348 cond = boolean_true_node;
4350 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4351 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4352 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4353 flags = build_int_cst (unsigned_type_node,
4354 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4356 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4357 if (c)
4359 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4360 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4361 build_int_cst (unsigned_type_node, 2),
4362 build_int_cst (unsigned_type_node, 0));
4363 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4365 if (depend)
4366 depend = OMP_CLAUSE_DECL (depend);
4367 else
4368 depend = build_int_cst (ptr_type_node, 0);
4370 gsi = gsi_last_bb (bb);
4371 t = gimple_omp_task_data_arg (entry_stmt);
4372 if (t == NULL)
4373 t2 = null_pointer_node;
4374 else
4375 t2 = build_fold_addr_expr_loc (loc, t);
4376 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4377 t = gimple_omp_task_copy_fn (entry_stmt);
4378 if (t == NULL)
4379 t3 = null_pointer_node;
4380 else
4381 t3 = build_fold_addr_expr_loc (loc, t);
4383 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4384 8, t1, t2, t3,
4385 gimple_omp_task_arg_size (entry_stmt),
4386 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4387 depend);
4389 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4390 false, GSI_CONTINUE_LINKING);
4394 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4395 catch handler and return it. This prevents programs from violating the
4396 structured block semantics with throws. */
4398 static gimple_seq
4399 maybe_catch_exception (gimple_seq body)
4401 gimple g;
4402 tree decl;
4404 if (!flag_exceptions)
4405 return body;
4407 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4408 decl = lang_hooks.eh_protect_cleanup_actions ();
4409 else
4410 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4412 g = gimple_build_eh_must_not_throw (decl);
4413 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4414 GIMPLE_TRY_CATCH);
4416 return gimple_seq_alloc_with_stmt (g);
4419 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4421 static tree
4422 vec2chain (vec<tree, va_gc> *v)
4424 tree chain = NULL_TREE, t;
4425 unsigned ix;
4427 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4429 DECL_CHAIN (t) = chain;
4430 chain = t;
4433 return chain;
4437 /* Remove barriers in REGION->EXIT's block. Note that this is only
4438 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4439 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4440 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4441 removed. */
4443 static void
4444 remove_exit_barrier (struct omp_region *region)
4446 gimple_stmt_iterator gsi;
4447 basic_block exit_bb;
4448 edge_iterator ei;
4449 edge e;
4450 gimple stmt;
4451 int any_addressable_vars = -1;
4453 exit_bb = region->exit;
4455 /* If the parallel region doesn't return, we don't have REGION->EXIT
4456 block at all. */
4457 if (! exit_bb)
4458 return;
4460 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4461 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4462 statements that can appear in between are extremely limited -- no
4463 memory operations at all. Here, we allow nothing at all, so the
4464 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4465 gsi = gsi_last_bb (exit_bb);
4466 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4467 gsi_prev (&gsi);
4468 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4469 return;
4471 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4473 gsi = gsi_last_bb (e->src);
4474 if (gsi_end_p (gsi))
4475 continue;
4476 stmt = gsi_stmt (gsi);
4477 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4478 && !gimple_omp_return_nowait_p (stmt))
4480 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4481 in many cases. If there could be tasks queued, the barrier
4482 might be needed to let the tasks run before some local
4483 variable of the parallel that the task uses as shared
4484 runs out of scope. The task can be spawned either
4485 from within current function (this would be easy to check)
4486 or from some function it calls and gets passed an address
4487 of such a variable. */
4488 if (any_addressable_vars < 0)
4490 gimple parallel_stmt = last_stmt (region->entry);
4491 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4492 tree local_decls, block, decl;
4493 unsigned ix;
4495 any_addressable_vars = 0;
4496 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4497 if (TREE_ADDRESSABLE (decl))
4499 any_addressable_vars = 1;
4500 break;
4502 for (block = gimple_block (stmt);
4503 !any_addressable_vars
4504 && block
4505 && TREE_CODE (block) == BLOCK;
4506 block = BLOCK_SUPERCONTEXT (block))
4508 for (local_decls = BLOCK_VARS (block);
4509 local_decls;
4510 local_decls = DECL_CHAIN (local_decls))
4511 if (TREE_ADDRESSABLE (local_decls))
4513 any_addressable_vars = 1;
4514 break;
4516 if (block == gimple_block (parallel_stmt))
4517 break;
4520 if (!any_addressable_vars)
4521 gimple_omp_return_set_nowait (stmt);
4526 static void
4527 remove_exit_barriers (struct omp_region *region)
4529 if (region->type == GIMPLE_OMP_PARALLEL)
4530 remove_exit_barrier (region);
4532 if (region->inner)
4534 region = region->inner;
4535 remove_exit_barriers (region);
4536 while (region->next)
4538 region = region->next;
4539 remove_exit_barriers (region);
4544 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4545 calls. These can't be declared as const functions, but
4546 within one parallel body they are constant, so they can be
4547 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4548 which are declared const. Similarly for task body, except
4549 that in untied task omp_get_thread_num () can change at any task
4550 scheduling point. */
4552 static void
4553 optimize_omp_library_calls (gimple entry_stmt)
4555 basic_block bb;
4556 gimple_stmt_iterator gsi;
4557 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4558 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4559 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4560 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4561 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4562 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4563 OMP_CLAUSE_UNTIED) != NULL);
4565 FOR_EACH_BB_FN (bb, cfun)
4566 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4568 gimple call = gsi_stmt (gsi);
4569 tree decl;
4571 if (is_gimple_call (call)
4572 && (decl = gimple_call_fndecl (call))
4573 && DECL_EXTERNAL (decl)
4574 && TREE_PUBLIC (decl)
4575 && DECL_INITIAL (decl) == NULL)
4577 tree built_in;
4579 if (DECL_NAME (decl) == thr_num_id)
4581 /* In #pragma omp task untied omp_get_thread_num () can change
4582 during the execution of the task region. */
4583 if (untied_task)
4584 continue;
4585 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4587 else if (DECL_NAME (decl) == num_thr_id)
4588 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4589 else
4590 continue;
4592 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4593 || gimple_call_num_args (call) != 0)
4594 continue;
4596 if (flag_exceptions && !TREE_NOTHROW (decl))
4597 continue;
4599 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4600 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4601 TREE_TYPE (TREE_TYPE (built_in))))
4602 continue;
4604 gimple_call_set_fndecl (call, built_in);
4609 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4610 regimplified. */
4612 static tree
4613 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4615 tree t = *tp;
4617 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4618 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4619 return t;
4621 if (TREE_CODE (t) == ADDR_EXPR)
4622 recompute_tree_invariant_for_addr_expr (t);
4624 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4625 return NULL_TREE;
4628 /* Prepend TO = FROM assignment before *GSI_P. */
4630 static void
4631 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4633 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4634 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4635 true, GSI_SAME_STMT);
4636 gimple stmt = gimple_build_assign (to, from);
4637 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4638 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4639 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4641 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4642 gimple_regimplify_operands (stmt, &gsi);
4646 /* Expand the OpenMP parallel or task directive starting at REGION. */
4648 static void
4649 expand_omp_taskreg (struct omp_region *region)
4651 basic_block entry_bb, exit_bb, new_bb;
4652 struct function *child_cfun;
4653 tree child_fn, block, t;
4654 gimple_stmt_iterator gsi;
4655 gimple entry_stmt, stmt;
4656 edge e;
4657 vec<tree, va_gc> *ws_args;
4659 entry_stmt = last_stmt (region->entry);
4660 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4661 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4663 entry_bb = region->entry;
4664 exit_bb = region->exit;
4666 if (is_combined_parallel (region))
4667 ws_args = region->ws_args;
4668 else
4669 ws_args = NULL;
4671 if (child_cfun->cfg)
4673 /* Due to inlining, it may happen that we have already outlined
4674 the region, in which case all we need to do is make the
4675 sub-graph unreachable and emit the parallel call. */
4676 edge entry_succ_e, exit_succ_e;
4677 gimple_stmt_iterator gsi;
4679 entry_succ_e = single_succ_edge (entry_bb);
4681 gsi = gsi_last_bb (entry_bb);
4682 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4683 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4684 gsi_remove (&gsi, true);
4686 new_bb = entry_bb;
4687 if (exit_bb)
4689 exit_succ_e = single_succ_edge (exit_bb);
4690 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4692 remove_edge_and_dominated_blocks (entry_succ_e);
4694 else
4696 unsigned srcidx, dstidx, num;
4698 /* If the parallel region needs data sent from the parent
4699 function, then the very first statement (except possible
4700 tree profile counter updates) of the parallel body
4701 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4702 &.OMP_DATA_O is passed as an argument to the child function,
4703 we need to replace it with the argument as seen by the child
4704 function.
4706 In most cases, this will end up being the identity assignment
4707 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4708 a function call that has been inlined, the original PARM_DECL
4709 .OMP_DATA_I may have been converted into a different local
4710 variable. In which case, we need to keep the assignment. */
4711 if (gimple_omp_taskreg_data_arg (entry_stmt))
4713 basic_block entry_succ_bb = single_succ (entry_bb);
4714 gimple_stmt_iterator gsi;
4715 tree arg, narg;
4716 gimple parcopy_stmt = NULL;
4718 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4720 gimple stmt;
4722 gcc_assert (!gsi_end_p (gsi));
4723 stmt = gsi_stmt (gsi);
4724 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4725 continue;
4727 if (gimple_num_ops (stmt) == 2)
4729 tree arg = gimple_assign_rhs1 (stmt);
4731 /* We're ignore the subcode because we're
4732 effectively doing a STRIP_NOPS. */
4734 if (TREE_CODE (arg) == ADDR_EXPR
4735 && TREE_OPERAND (arg, 0)
4736 == gimple_omp_taskreg_data_arg (entry_stmt))
4738 parcopy_stmt = stmt;
4739 break;
4744 gcc_assert (parcopy_stmt != NULL);
4745 arg = DECL_ARGUMENTS (child_fn);
4747 if (!gimple_in_ssa_p (cfun))
4749 if (gimple_assign_lhs (parcopy_stmt) == arg)
4750 gsi_remove (&gsi, true);
4751 else
4753 /* ?? Is setting the subcode really necessary ?? */
4754 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
4755 gimple_assign_set_rhs1 (parcopy_stmt, arg);
4758 else
4760 /* If we are in ssa form, we must load the value from the default
4761 definition of the argument. That should not be defined now,
4762 since the argument is not used uninitialized. */
4763 gcc_assert (ssa_default_def (cfun, arg) == NULL);
4764 narg = make_ssa_name (arg, gimple_build_nop ());
4765 set_ssa_default_def (cfun, arg, narg);
4766 /* ?? Is setting the subcode really necessary ?? */
4767 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
4768 gimple_assign_set_rhs1 (parcopy_stmt, narg);
4769 update_stmt (parcopy_stmt);
4773 /* Declare local variables needed in CHILD_CFUN. */
4774 block = DECL_INITIAL (child_fn);
4775 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4776 /* The gimplifier could record temporaries in parallel/task block
4777 rather than in containing function's local_decls chain,
4778 which would mean cgraph missed finalizing them. Do it now. */
4779 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4780 if (TREE_CODE (t) == VAR_DECL
4781 && TREE_STATIC (t)
4782 && !DECL_EXTERNAL (t))
4783 varpool_finalize_decl (t);
4784 DECL_SAVED_TREE (child_fn) = NULL;
4785 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4786 gimple_set_body (child_fn, NULL);
4787 TREE_USED (block) = 1;
4789 /* Reset DECL_CONTEXT on function arguments. */
4790 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
4791 DECL_CONTEXT (t) = child_fn;
4793 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
4794 so that it can be moved to the child function. */
4795 gsi = gsi_last_bb (entry_bb);
4796 stmt = gsi_stmt (gsi);
4797 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
4798 || gimple_code (stmt) == GIMPLE_OMP_TASK));
4799 gsi_remove (&gsi, true);
4800 e = split_block (entry_bb, stmt);
4801 entry_bb = e->dest;
4802 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4804 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4805 if (exit_bb)
4807 gsi = gsi_last_bb (exit_bb);
4808 gcc_assert (!gsi_end_p (gsi)
4809 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4810 stmt = gimple_build_return (NULL);
4811 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4812 gsi_remove (&gsi, true);
4815 /* Move the parallel region into CHILD_CFUN. */
4817 if (gimple_in_ssa_p (cfun))
4819 init_tree_ssa (child_cfun);
4820 init_ssa_operands (child_cfun);
4821 child_cfun->gimple_df->in_ssa_p = true;
4822 block = NULL_TREE;
4824 else
4825 block = gimple_block (entry_stmt);
4827 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
4828 if (exit_bb)
4829 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
4830 /* When the OMP expansion process cannot guarantee an up-to-date
4831 loop tree arrange for the child function to fixup loops. */
4832 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
4833 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
4835 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
4836 num = vec_safe_length (child_cfun->local_decls);
4837 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
4839 t = (*child_cfun->local_decls)[srcidx];
4840 if (DECL_CONTEXT (t) == cfun->decl)
4841 continue;
4842 if (srcidx != dstidx)
4843 (*child_cfun->local_decls)[dstidx] = t;
4844 dstidx++;
4846 if (dstidx != num)
4847 vec_safe_truncate (child_cfun->local_decls, dstidx);
4849 /* Inform the callgraph about the new function. */
4850 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
4851 cgraph_add_new_function (child_fn, true);
4853 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4854 fixed in a following pass. */
4855 push_cfun (child_cfun);
4856 if (optimize)
4857 optimize_omp_library_calls (entry_stmt);
4858 rebuild_cgraph_edges ();
4860 /* Some EH regions might become dead, see PR34608. If
4861 pass_cleanup_cfg isn't the first pass to happen with the
4862 new child, these dead EH edges might cause problems.
4863 Clean them up now. */
4864 if (flag_exceptions)
4866 basic_block bb;
4867 bool changed = false;
4869 FOR_EACH_BB_FN (bb, cfun)
4870 changed |= gimple_purge_dead_eh_edges (bb);
4871 if (changed)
4872 cleanup_tree_cfg ();
4874 if (gimple_in_ssa_p (cfun))
4875 update_ssa (TODO_update_ssa);
4876 pop_cfun ();
4879 /* Emit a library call to launch the children threads. */
4880 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
4881 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
4882 else
4883 expand_task_call (new_bb, entry_stmt);
4884 if (gimple_in_ssa_p (cfun))
4885 update_ssa (TODO_update_ssa_only_virtuals);
4889 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4890 of the combined collapse > 1 loop constructs, generate code like:
4891 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4892 if (cond3 is <)
4893 adj = STEP3 - 1;
4894 else
4895 adj = STEP3 + 1;
4896 count3 = (adj + N32 - N31) / STEP3;
4897 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4898 if (cond2 is <)
4899 adj = STEP2 - 1;
4900 else
4901 adj = STEP2 + 1;
4902 count2 = (adj + N22 - N21) / STEP2;
4903 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4904 if (cond1 is <)
4905 adj = STEP1 - 1;
4906 else
4907 adj = STEP1 + 1;
4908 count1 = (adj + N12 - N11) / STEP1;
4909 count = count1 * count2 * count3;
4910 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4911 count = 0;
4912 and set ZERO_ITER_BB to that bb. If this isn't the outermost
4913 of the combined loop constructs, just initialize COUNTS array
4914 from the _looptemp_ clauses. */
4916 /* NOTE: It *could* be better to moosh all of the BBs together,
4917 creating one larger BB with all the computation and the unexpected
4918 jump at the end. I.e.
4920 bool zero3, zero2, zero1, zero;
4922 zero3 = N32 c3 N31;
4923 count3 = (N32 - N31) /[cl] STEP3;
4924 zero2 = N22 c2 N21;
4925 count2 = (N22 - N21) /[cl] STEP2;
4926 zero1 = N12 c1 N11;
4927 count1 = (N12 - N11) /[cl] STEP1;
4928 zero = zero3 || zero2 || zero1;
4929 count = count1 * count2 * count3;
4930 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4932 After all, we expect the zero=false, and thus we expect to have to
4933 evaluate all of the comparison expressions, so short-circuiting
4934 oughtn't be a win. Since the condition isn't protecting a
4935 denominator, we're not concerned about divide-by-zero, so we can
4936 fully evaluate count even if a numerator turned out to be wrong.
4938 It seems like putting this all together would create much better
4939 scheduling opportunities, and less pressure on the chip's branch
4940 predictor. */
4942 static void
4943 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4944 basic_block &entry_bb, tree *counts,
4945 basic_block &zero_iter_bb, int &first_zero_iter,
4946 basic_block &l2_dom_bb)
4948 tree t, type = TREE_TYPE (fd->loop.v);
4949 gimple stmt;
4950 edge e, ne;
4951 int i;
4953 /* Collapsed loops need work for expansion into SSA form. */
4954 gcc_assert (!gimple_in_ssa_p (cfun));
4956 if (gimple_omp_for_combined_into_p (fd->for_stmt)
4957 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
4959 /* First two _looptemp_ clauses are for istart/iend, counts[0]
4960 isn't supposed to be handled, as the inner loop doesn't
4961 use it. */
4962 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
4963 OMP_CLAUSE__LOOPTEMP_);
4964 gcc_assert (innerc);
4965 for (i = 0; i < fd->collapse; i++)
4967 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
4968 OMP_CLAUSE__LOOPTEMP_);
4969 gcc_assert (innerc);
4970 if (i)
4971 counts[i] = OMP_CLAUSE_DECL (innerc);
4972 else
4973 counts[0] = NULL_TREE;
4975 return;
4978 for (i = 0; i < fd->collapse; i++)
4980 tree itype = TREE_TYPE (fd->loops[i].v);
4982 if (SSA_VAR_P (fd->loop.n2)
4983 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
4984 fold_convert (itype, fd->loops[i].n1),
4985 fold_convert (itype, fd->loops[i].n2)))
4986 == NULL_TREE || !integer_onep (t)))
4988 tree n1, n2;
4989 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
4990 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
4991 true, GSI_SAME_STMT);
4992 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
4993 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
4994 true, GSI_SAME_STMT);
4995 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
4996 NULL_TREE, NULL_TREE);
4997 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4998 if (walk_tree (gimple_cond_lhs_ptr (stmt),
4999 expand_omp_regimplify_p, NULL, NULL)
5000 || walk_tree (gimple_cond_rhs_ptr (stmt),
5001 expand_omp_regimplify_p, NULL, NULL))
5003 *gsi = gsi_for_stmt (stmt);
5004 gimple_regimplify_operands (stmt, gsi);
5006 e = split_block (entry_bb, stmt);
5007 if (zero_iter_bb == NULL)
5009 first_zero_iter = i;
5010 zero_iter_bb = create_empty_bb (entry_bb);
5011 if (current_loops)
5012 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5013 *gsi = gsi_after_labels (zero_iter_bb);
5014 stmt = gimple_build_assign (fd->loop.n2,
5015 build_zero_cst (type));
5016 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5017 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5018 entry_bb);
5020 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5021 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5022 e->flags = EDGE_TRUE_VALUE;
5023 e->probability = REG_BR_PROB_BASE - ne->probability;
5024 if (l2_dom_bb == NULL)
5025 l2_dom_bb = entry_bb;
5026 entry_bb = e->dest;
5027 *gsi = gsi_last_bb (entry_bb);
5030 if (POINTER_TYPE_P (itype))
5031 itype = signed_type_for (itype);
5032 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5033 ? -1 : 1));
5034 t = fold_build2 (PLUS_EXPR, itype,
5035 fold_convert (itype, fd->loops[i].step), t);
5036 t = fold_build2 (PLUS_EXPR, itype, t,
5037 fold_convert (itype, fd->loops[i].n2));
5038 t = fold_build2 (MINUS_EXPR, itype, t,
5039 fold_convert (itype, fd->loops[i].n1));
5040 /* ?? We could probably use CEIL_DIV_EXPR instead of
5041 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5042 generate the same code in the end because generically we
5043 don't know that the values involved must be negative for
5044 GT?? */
5045 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5046 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5047 fold_build1 (NEGATE_EXPR, itype, t),
5048 fold_build1 (NEGATE_EXPR, itype,
5049 fold_convert (itype,
5050 fd->loops[i].step)));
5051 else
5052 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5053 fold_convert (itype, fd->loops[i].step));
5054 t = fold_convert (type, t);
5055 if (TREE_CODE (t) == INTEGER_CST)
5056 counts[i] = t;
5057 else
5059 counts[i] = create_tmp_reg (type, ".count");
5060 expand_omp_build_assign (gsi, counts[i], t);
5062 if (SSA_VAR_P (fd->loop.n2))
5064 if (i == 0)
5065 t = counts[0];
5066 else
5067 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5068 expand_omp_build_assign (gsi, fd->loop.n2, t);
5074 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5075 T = V;
5076 V3 = N31 + (T % count3) * STEP3;
5077 T = T / count3;
5078 V2 = N21 + (T % count2) * STEP2;
5079 T = T / count2;
5080 V1 = N11 + T * STEP1;
5081 if this loop doesn't have an inner loop construct combined with it.
5082 If it does have an inner loop construct combined with it and the
5083 iteration count isn't known constant, store values from counts array
5084 into its _looptemp_ temporaries instead. */
5086 static void
5087 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5088 tree *counts, gimple inner_stmt, tree startvar)
5090 int i;
5091 if (gimple_omp_for_combined_p (fd->for_stmt))
5093 /* If fd->loop.n2 is constant, then no propagation of the counts
5094 is needed, they are constant. */
5095 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5096 return;
5098 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5099 ? gimple_omp_parallel_clauses (inner_stmt)
5100 : gimple_omp_for_clauses (inner_stmt);
5101 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5102 isn't supposed to be handled, as the inner loop doesn't
5103 use it. */
5104 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5105 gcc_assert (innerc);
5106 for (i = 0; i < fd->collapse; i++)
5108 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5109 OMP_CLAUSE__LOOPTEMP_);
5110 gcc_assert (innerc);
5111 if (i)
5113 tree tem = OMP_CLAUSE_DECL (innerc);
5114 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5115 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5116 false, GSI_CONTINUE_LINKING);
5117 gimple stmt = gimple_build_assign (tem, t);
5118 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5121 return;
5124 tree type = TREE_TYPE (fd->loop.v);
5125 tree tem = create_tmp_reg (type, ".tem");
5126 gimple stmt = gimple_build_assign (tem, startvar);
5127 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5129 for (i = fd->collapse - 1; i >= 0; i--)
5131 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5132 itype = vtype;
5133 if (POINTER_TYPE_P (vtype))
5134 itype = signed_type_for (vtype);
5135 if (i != 0)
5136 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5137 else
5138 t = tem;
5139 t = fold_convert (itype, t);
5140 t = fold_build2 (MULT_EXPR, itype, t,
5141 fold_convert (itype, fd->loops[i].step));
5142 if (POINTER_TYPE_P (vtype))
5143 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5144 else
5145 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5146 t = force_gimple_operand_gsi (gsi, t,
5147 DECL_P (fd->loops[i].v)
5148 && TREE_ADDRESSABLE (fd->loops[i].v),
5149 NULL_TREE, false,
5150 GSI_CONTINUE_LINKING);
5151 stmt = gimple_build_assign (fd->loops[i].v, t);
5152 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5153 if (i != 0)
5155 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5156 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5157 false, GSI_CONTINUE_LINKING);
5158 stmt = gimple_build_assign (tem, t);
5159 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5165 /* Helper function for expand_omp_for_*. Generate code like:
5166 L10:
5167 V3 += STEP3;
5168 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5169 L11:
5170 V3 = N31;
5171 V2 += STEP2;
5172 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5173 L12:
5174 V2 = N21;
5175 V1 += STEP1;
5176 goto BODY_BB; */
5178 static basic_block
5179 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5180 basic_block body_bb)
5182 basic_block last_bb, bb, collapse_bb = NULL;
5183 int i;
5184 gimple_stmt_iterator gsi;
5185 edge e;
5186 tree t;
5187 gimple stmt;
5189 last_bb = cont_bb;
5190 for (i = fd->collapse - 1; i >= 0; i--)
5192 tree vtype = TREE_TYPE (fd->loops[i].v);
5194 bb = create_empty_bb (last_bb);
5195 if (current_loops)
5196 add_bb_to_loop (bb, last_bb->loop_father);
5197 gsi = gsi_start_bb (bb);
5199 if (i < fd->collapse - 1)
5201 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5202 e->probability = REG_BR_PROB_BASE / 8;
5204 t = fd->loops[i + 1].n1;
5205 t = force_gimple_operand_gsi (&gsi, t,
5206 DECL_P (fd->loops[i + 1].v)
5207 && TREE_ADDRESSABLE (fd->loops[i
5208 + 1].v),
5209 NULL_TREE, false,
5210 GSI_CONTINUE_LINKING);
5211 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5212 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5214 else
5215 collapse_bb = bb;
5217 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5219 if (POINTER_TYPE_P (vtype))
5220 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5221 else
5222 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5223 t = force_gimple_operand_gsi (&gsi, t,
5224 DECL_P (fd->loops[i].v)
5225 && TREE_ADDRESSABLE (fd->loops[i].v),
5226 NULL_TREE, false, GSI_CONTINUE_LINKING);
5227 stmt = gimple_build_assign (fd->loops[i].v, t);
5228 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5230 if (i > 0)
5232 t = fd->loops[i].n2;
5233 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5234 false, GSI_CONTINUE_LINKING);
5235 tree v = fd->loops[i].v;
5236 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5237 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5238 false, GSI_CONTINUE_LINKING);
5239 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5240 stmt = gimple_build_cond_empty (t);
5241 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5242 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5243 e->probability = REG_BR_PROB_BASE * 7 / 8;
5245 else
5246 make_edge (bb, body_bb, EDGE_FALLTHRU);
5247 last_bb = bb;
5250 return collapse_bb;
5254 /* A subroutine of expand_omp_for. Generate code for a parallel
5255 loop with any schedule. Given parameters:
5257 for (V = N1; V cond N2; V += STEP) BODY;
5259 where COND is "<" or ">", we generate pseudocode
5261 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5262 if (more) goto L0; else goto L3;
5264 V = istart0;
5265 iend = iend0;
5267 BODY;
5268 V += STEP;
5269 if (V cond iend) goto L1; else goto L2;
5271 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5274 If this is a combined omp parallel loop, instead of the call to
5275 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5276 If this is gimple_omp_for_combined_p loop, then instead of assigning
5277 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5278 inner GIMPLE_OMP_FOR and V += STEP; and
5279 if (V cond iend) goto L1; else goto L2; are removed.
5281 For collapsed loops, given parameters:
5282 collapse(3)
5283 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5284 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5285 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5286 BODY;
5288 we generate pseudocode
5290 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5291 if (cond3 is <)
5292 adj = STEP3 - 1;
5293 else
5294 adj = STEP3 + 1;
5295 count3 = (adj + N32 - N31) / STEP3;
5296 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5297 if (cond2 is <)
5298 adj = STEP2 - 1;
5299 else
5300 adj = STEP2 + 1;
5301 count2 = (adj + N22 - N21) / STEP2;
5302 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5303 if (cond1 is <)
5304 adj = STEP1 - 1;
5305 else
5306 adj = STEP1 + 1;
5307 count1 = (adj + N12 - N11) / STEP1;
5308 count = count1 * count2 * count3;
5309 goto Z1;
5311 count = 0;
5313 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5314 if (more) goto L0; else goto L3;
5316 V = istart0;
5317 T = V;
5318 V3 = N31 + (T % count3) * STEP3;
5319 T = T / count3;
5320 V2 = N21 + (T % count2) * STEP2;
5321 T = T / count2;
5322 V1 = N11 + T * STEP1;
5323 iend = iend0;
5325 BODY;
5326 V += 1;
5327 if (V < iend) goto L10; else goto L2;
5328 L10:
5329 V3 += STEP3;
5330 if (V3 cond3 N32) goto L1; else goto L11;
5331 L11:
5332 V3 = N31;
5333 V2 += STEP2;
5334 if (V2 cond2 N22) goto L1; else goto L12;
5335 L12:
5336 V2 = N21;
5337 V1 += STEP1;
5338 goto L1;
5340 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5345 static void
5346 expand_omp_for_generic (struct omp_region *region,
5347 struct omp_for_data *fd,
5348 enum built_in_function start_fn,
5349 enum built_in_function next_fn,
5350 gimple inner_stmt)
5352 tree type, istart0, iend0, iend;
5353 tree t, vmain, vback, bias = NULL_TREE;
5354 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5355 basic_block l2_bb = NULL, l3_bb = NULL;
5356 gimple_stmt_iterator gsi;
5357 gimple stmt;
5358 bool in_combined_parallel = is_combined_parallel (region);
5359 bool broken_loop = region->cont == NULL;
5360 edge e, ne;
5361 tree *counts = NULL;
5362 int i;
5364 gcc_assert (!broken_loop || !in_combined_parallel);
5365 gcc_assert (fd->iter_type == long_integer_type_node
5366 || !in_combined_parallel);
5368 type = TREE_TYPE (fd->loop.v);
5369 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5370 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5371 TREE_ADDRESSABLE (istart0) = 1;
5372 TREE_ADDRESSABLE (iend0) = 1;
5374 /* See if we need to bias by LLONG_MIN. */
5375 if (fd->iter_type == long_long_unsigned_type_node
5376 && TREE_CODE (type) == INTEGER_TYPE
5377 && !TYPE_UNSIGNED (type))
5379 tree n1, n2;
5381 if (fd->loop.cond_code == LT_EXPR)
5383 n1 = fd->loop.n1;
5384 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5386 else
5388 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5389 n2 = fd->loop.n1;
5391 if (TREE_CODE (n1) != INTEGER_CST
5392 || TREE_CODE (n2) != INTEGER_CST
5393 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5394 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5397 entry_bb = region->entry;
5398 cont_bb = region->cont;
5399 collapse_bb = NULL;
5400 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5401 gcc_assert (broken_loop
5402 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5403 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5404 l1_bb = single_succ (l0_bb);
5405 if (!broken_loop)
5407 l2_bb = create_empty_bb (cont_bb);
5408 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5409 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5411 else
5412 l2_bb = NULL;
5413 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5414 exit_bb = region->exit;
5416 gsi = gsi_last_bb (entry_bb);
5418 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5419 if (fd->collapse > 1)
5421 int first_zero_iter = -1;
5422 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5424 counts = XALLOCAVEC (tree, fd->collapse);
5425 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5426 zero_iter_bb, first_zero_iter,
5427 l2_dom_bb);
5429 if (zero_iter_bb)
5431 /* Some counts[i] vars might be uninitialized if
5432 some loop has zero iterations. But the body shouldn't
5433 be executed in that case, so just avoid uninit warnings. */
5434 for (i = first_zero_iter; i < fd->collapse; i++)
5435 if (SSA_VAR_P (counts[i]))
5436 TREE_NO_WARNING (counts[i]) = 1;
5437 gsi_prev (&gsi);
5438 e = split_block (entry_bb, gsi_stmt (gsi));
5439 entry_bb = e->dest;
5440 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5441 gsi = gsi_last_bb (entry_bb);
5442 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5443 get_immediate_dominator (CDI_DOMINATORS,
5444 zero_iter_bb));
5447 if (in_combined_parallel)
5449 /* In a combined parallel loop, emit a call to
5450 GOMP_loop_foo_next. */
5451 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5452 build_fold_addr_expr (istart0),
5453 build_fold_addr_expr (iend0));
5455 else
5457 tree t0, t1, t2, t3, t4;
5458 /* If this is not a combined parallel loop, emit a call to
5459 GOMP_loop_foo_start in ENTRY_BB. */
5460 t4 = build_fold_addr_expr (iend0);
5461 t3 = build_fold_addr_expr (istart0);
5462 t2 = fold_convert (fd->iter_type, fd->loop.step);
5463 t1 = fd->loop.n2;
5464 t0 = fd->loop.n1;
5465 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5467 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5468 OMP_CLAUSE__LOOPTEMP_);
5469 gcc_assert (innerc);
5470 t0 = OMP_CLAUSE_DECL (innerc);
5471 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5472 OMP_CLAUSE__LOOPTEMP_);
5473 gcc_assert (innerc);
5474 t1 = OMP_CLAUSE_DECL (innerc);
5476 if (POINTER_TYPE_P (TREE_TYPE (t0))
5477 && TYPE_PRECISION (TREE_TYPE (t0))
5478 != TYPE_PRECISION (fd->iter_type))
5480 /* Avoid casting pointers to integer of a different size. */
5481 tree itype = signed_type_for (type);
5482 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5483 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5485 else
5487 t1 = fold_convert (fd->iter_type, t1);
5488 t0 = fold_convert (fd->iter_type, t0);
5490 if (bias)
5492 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5493 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5495 if (fd->iter_type == long_integer_type_node)
5497 if (fd->chunk_size)
5499 t = fold_convert (fd->iter_type, fd->chunk_size);
5500 t = build_call_expr (builtin_decl_explicit (start_fn),
5501 6, t0, t1, t2, t, t3, t4);
5503 else
5504 t = build_call_expr (builtin_decl_explicit (start_fn),
5505 5, t0, t1, t2, t3, t4);
5507 else
5509 tree t5;
5510 tree c_bool_type;
5511 tree bfn_decl;
5513 /* The GOMP_loop_ull_*start functions have additional boolean
5514 argument, true for < loops and false for > loops.
5515 In Fortran, the C bool type can be different from
5516 boolean_type_node. */
5517 bfn_decl = builtin_decl_explicit (start_fn);
5518 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5519 t5 = build_int_cst (c_bool_type,
5520 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5521 if (fd->chunk_size)
5523 tree bfn_decl = builtin_decl_explicit (start_fn);
5524 t = fold_convert (fd->iter_type, fd->chunk_size);
5525 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5527 else
5528 t = build_call_expr (builtin_decl_explicit (start_fn),
5529 6, t5, t0, t1, t2, t3, t4);
5532 if (TREE_TYPE (t) != boolean_type_node)
5533 t = fold_build2 (NE_EXPR, boolean_type_node,
5534 t, build_int_cst (TREE_TYPE (t), 0));
5535 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5536 true, GSI_SAME_STMT);
5537 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5539 /* Remove the GIMPLE_OMP_FOR statement. */
5540 gsi_remove (&gsi, true);
5542 /* Iteration setup for sequential loop goes in L0_BB. */
5543 tree startvar = fd->loop.v;
5544 tree endvar = NULL_TREE;
5546 if (gimple_omp_for_combined_p (fd->for_stmt))
5548 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5549 && gimple_omp_for_kind (inner_stmt)
5550 == GF_OMP_FOR_KIND_SIMD);
5551 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5552 OMP_CLAUSE__LOOPTEMP_);
5553 gcc_assert (innerc);
5554 startvar = OMP_CLAUSE_DECL (innerc);
5555 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5556 OMP_CLAUSE__LOOPTEMP_);
5557 gcc_assert (innerc);
5558 endvar = OMP_CLAUSE_DECL (innerc);
5561 gsi = gsi_start_bb (l0_bb);
5562 t = istart0;
5563 if (bias)
5564 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5565 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5566 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5567 t = fold_convert (TREE_TYPE (startvar), t);
5568 t = force_gimple_operand_gsi (&gsi, t,
5569 DECL_P (startvar)
5570 && TREE_ADDRESSABLE (startvar),
5571 NULL_TREE, false, GSI_CONTINUE_LINKING);
5572 stmt = gimple_build_assign (startvar, t);
5573 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5575 t = iend0;
5576 if (bias)
5577 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5578 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5579 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5580 t = fold_convert (TREE_TYPE (startvar), t);
5581 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5582 false, GSI_CONTINUE_LINKING);
5583 if (endvar)
5585 stmt = gimple_build_assign (endvar, iend);
5586 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5588 if (fd->collapse > 1)
5589 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5591 if (!broken_loop)
5593 /* Code to control the increment and predicate for the sequential
5594 loop goes in the CONT_BB. */
5595 gsi = gsi_last_bb (cont_bb);
5596 stmt = gsi_stmt (gsi);
5597 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5598 vmain = gimple_omp_continue_control_use (stmt);
5599 vback = gimple_omp_continue_control_def (stmt);
5601 if (!gimple_omp_for_combined_p (fd->for_stmt))
5603 if (POINTER_TYPE_P (type))
5604 t = fold_build_pointer_plus (vmain, fd->loop.step);
5605 else
5606 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5607 t = force_gimple_operand_gsi (&gsi, t,
5608 DECL_P (vback)
5609 && TREE_ADDRESSABLE (vback),
5610 NULL_TREE, true, GSI_SAME_STMT);
5611 stmt = gimple_build_assign (vback, t);
5612 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5614 t = build2 (fd->loop.cond_code, boolean_type_node,
5615 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5616 iend);
5617 stmt = gimple_build_cond_empty (t);
5618 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5621 /* Remove GIMPLE_OMP_CONTINUE. */
5622 gsi_remove (&gsi, true);
5624 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5625 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5627 /* Emit code to get the next parallel iteration in L2_BB. */
5628 gsi = gsi_start_bb (l2_bb);
5630 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5631 build_fold_addr_expr (istart0),
5632 build_fold_addr_expr (iend0));
5633 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5634 false, GSI_CONTINUE_LINKING);
5635 if (TREE_TYPE (t) != boolean_type_node)
5636 t = fold_build2 (NE_EXPR, boolean_type_node,
5637 t, build_int_cst (TREE_TYPE (t), 0));
5638 stmt = gimple_build_cond_empty (t);
5639 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5642 /* Add the loop cleanup function. */
5643 gsi = gsi_last_bb (exit_bb);
5644 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5645 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5646 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5647 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5648 else
5649 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5650 stmt = gimple_build_call (t, 0);
5651 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5652 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5653 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5654 gsi_remove (&gsi, true);
5656 /* Connect the new blocks. */
5657 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5658 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5660 if (!broken_loop)
5662 gimple_seq phis;
5664 e = find_edge (cont_bb, l3_bb);
5665 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5667 phis = phi_nodes (l3_bb);
5668 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5670 gimple phi = gsi_stmt (gsi);
5671 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5672 PHI_ARG_DEF_FROM_EDGE (phi, e));
5674 remove_edge (e);
5676 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5677 if (current_loops)
5678 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5679 e = find_edge (cont_bb, l1_bb);
5680 if (gimple_omp_for_combined_p (fd->for_stmt))
5682 remove_edge (e);
5683 e = NULL;
5685 else if (fd->collapse > 1)
5687 remove_edge (e);
5688 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5690 else
5691 e->flags = EDGE_TRUE_VALUE;
5692 if (e)
5694 e->probability = REG_BR_PROB_BASE * 7 / 8;
5695 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5697 else
5699 e = find_edge (cont_bb, l2_bb);
5700 e->flags = EDGE_FALLTHRU;
5702 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5704 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5705 recompute_dominator (CDI_DOMINATORS, l2_bb));
5706 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5707 recompute_dominator (CDI_DOMINATORS, l3_bb));
5708 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5709 recompute_dominator (CDI_DOMINATORS, l0_bb));
5710 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5711 recompute_dominator (CDI_DOMINATORS, l1_bb));
5713 struct loop *outer_loop = alloc_loop ();
5714 outer_loop->header = l0_bb;
5715 outer_loop->latch = l2_bb;
5716 add_loop (outer_loop, l0_bb->loop_father);
5718 if (!gimple_omp_for_combined_p (fd->for_stmt))
5720 struct loop *loop = alloc_loop ();
5721 loop->header = l1_bb;
5722 /* The loop may have multiple latches. */
5723 add_loop (loop, outer_loop);
5729 /* A subroutine of expand_omp_for. Generate code for a parallel
5730 loop with static schedule and no specified chunk size. Given
5731 parameters:
5733 for (V = N1; V cond N2; V += STEP) BODY;
5735 where COND is "<" or ">", we generate pseudocode
5737 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5738 if (cond is <)
5739 adj = STEP - 1;
5740 else
5741 adj = STEP + 1;
5742 if ((__typeof (V)) -1 > 0 && cond is >)
5743 n = -(adj + N2 - N1) / -STEP;
5744 else
5745 n = (adj + N2 - N1) / STEP;
5746 q = n / nthreads;
5747 tt = n % nthreads;
5748 if (threadid < tt) goto L3; else goto L4;
5750 tt = 0;
5751 q = q + 1;
5753 s0 = q * threadid + tt;
5754 e0 = s0 + q;
5755 V = s0 * STEP + N1;
5756 if (s0 >= e0) goto L2; else goto L0;
5758 e = e0 * STEP + N1;
5760 BODY;
5761 V += STEP;
5762 if (V cond e) goto L1;
5766 static void
5767 expand_omp_for_static_nochunk (struct omp_region *region,
5768 struct omp_for_data *fd,
5769 gimple inner_stmt)
5771 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
5772 tree type, itype, vmain, vback;
5773 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
5774 basic_block body_bb, cont_bb, collapse_bb = NULL;
5775 basic_block fin_bb;
5776 gimple_stmt_iterator gsi;
5777 gimple stmt;
5778 edge ep;
5779 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
5780 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
5781 bool broken_loop = region->cont == NULL;
5782 tree *counts = NULL;
5783 tree n1, n2, step;
5785 itype = type = TREE_TYPE (fd->loop.v);
5786 if (POINTER_TYPE_P (type))
5787 itype = signed_type_for (type);
5789 entry_bb = region->entry;
5790 cont_bb = region->cont;
5791 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5792 fin_bb = BRANCH_EDGE (entry_bb)->dest;
5793 gcc_assert (broken_loop
5794 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
5795 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5796 body_bb = single_succ (seq_start_bb);
5797 if (!broken_loop)
5799 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
5800 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5802 exit_bb = region->exit;
5804 /* Iteration space partitioning goes in ENTRY_BB. */
5805 gsi = gsi_last_bb (entry_bb);
5806 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5808 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
5810 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
5811 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
5814 if (fd->collapse > 1)
5816 int first_zero_iter = -1;
5817 basic_block l2_dom_bb = NULL;
5819 counts = XALLOCAVEC (tree, fd->collapse);
5820 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5821 fin_bb, first_zero_iter,
5822 l2_dom_bb);
5823 t = NULL_TREE;
5825 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
5826 t = integer_one_node;
5827 else
5828 t = fold_binary (fd->loop.cond_code, boolean_type_node,
5829 fold_convert (type, fd->loop.n1),
5830 fold_convert (type, fd->loop.n2));
5831 if (fd->collapse == 1
5832 && TYPE_UNSIGNED (type)
5833 && (t == NULL_TREE || !integer_onep (t)))
5835 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5836 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5837 true, GSI_SAME_STMT);
5838 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5839 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5840 true, GSI_SAME_STMT);
5841 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
5842 NULL_TREE, NULL_TREE);
5843 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5844 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5845 expand_omp_regimplify_p, NULL, NULL)
5846 || walk_tree (gimple_cond_rhs_ptr (stmt),
5847 expand_omp_regimplify_p, NULL, NULL))
5849 gsi = gsi_for_stmt (stmt);
5850 gimple_regimplify_operands (stmt, &gsi);
5852 ep = split_block (entry_bb, stmt);
5853 ep->flags = EDGE_TRUE_VALUE;
5854 entry_bb = ep->dest;
5855 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
5856 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
5857 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
5858 if (gimple_in_ssa_p (cfun))
5860 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
5861 for (gsi = gsi_start_phis (fin_bb);
5862 !gsi_end_p (gsi); gsi_next (&gsi))
5864 gimple phi = gsi_stmt (gsi);
5865 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
5866 ep, UNKNOWN_LOCATION);
5869 gsi = gsi_last_bb (entry_bb);
5872 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
5873 t = fold_convert (itype, t);
5874 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5875 true, GSI_SAME_STMT);
5877 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
5878 t = fold_convert (itype, t);
5879 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5880 true, GSI_SAME_STMT);
5882 n1 = fd->loop.n1;
5883 n2 = fd->loop.n2;
5884 step = fd->loop.step;
5885 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5887 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5888 OMP_CLAUSE__LOOPTEMP_);
5889 gcc_assert (innerc);
5890 n1 = OMP_CLAUSE_DECL (innerc);
5891 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5892 OMP_CLAUSE__LOOPTEMP_);
5893 gcc_assert (innerc);
5894 n2 = OMP_CLAUSE_DECL (innerc);
5896 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
5897 true, NULL_TREE, true, GSI_SAME_STMT);
5898 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
5899 true, NULL_TREE, true, GSI_SAME_STMT);
5900 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
5901 true, NULL_TREE, true, GSI_SAME_STMT);
5903 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
5904 t = fold_build2 (PLUS_EXPR, itype, step, t);
5905 t = fold_build2 (PLUS_EXPR, itype, t, n2);
5906 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
5907 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
5908 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5909 fold_build1 (NEGATE_EXPR, itype, t),
5910 fold_build1 (NEGATE_EXPR, itype, step));
5911 else
5912 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
5913 t = fold_convert (itype, t);
5914 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5916 q = create_tmp_reg (itype, "q");
5917 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
5918 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5919 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
5921 tt = create_tmp_reg (itype, "tt");
5922 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
5923 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5924 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
5926 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
5927 stmt = gimple_build_cond_empty (t);
5928 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5930 second_bb = split_block (entry_bb, stmt)->dest;
5931 gsi = gsi_last_bb (second_bb);
5932 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5934 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
5935 GSI_SAME_STMT);
5936 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
5937 build_int_cst (itype, 1));
5938 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5940 third_bb = split_block (second_bb, stmt)->dest;
5941 gsi = gsi_last_bb (third_bb);
5942 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5944 t = build2 (MULT_EXPR, itype, q, threadid);
5945 t = build2 (PLUS_EXPR, itype, t, tt);
5946 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5948 t = fold_build2 (PLUS_EXPR, itype, s0, q);
5949 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5951 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
5952 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5954 /* Remove the GIMPLE_OMP_FOR statement. */
5955 gsi_remove (&gsi, true);
5957 /* Setup code for sequential iteration goes in SEQ_START_BB. */
5958 gsi = gsi_start_bb (seq_start_bb);
5960 tree startvar = fd->loop.v;
5961 tree endvar = NULL_TREE;
5963 if (gimple_omp_for_combined_p (fd->for_stmt))
5965 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5966 ? gimple_omp_parallel_clauses (inner_stmt)
5967 : gimple_omp_for_clauses (inner_stmt);
5968 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5969 gcc_assert (innerc);
5970 startvar = OMP_CLAUSE_DECL (innerc);
5971 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5972 OMP_CLAUSE__LOOPTEMP_);
5973 gcc_assert (innerc);
5974 endvar = OMP_CLAUSE_DECL (innerc);
5976 t = fold_convert (itype, s0);
5977 t = fold_build2 (MULT_EXPR, itype, t, step);
5978 if (POINTER_TYPE_P (type))
5979 t = fold_build_pointer_plus (n1, t);
5980 else
5981 t = fold_build2 (PLUS_EXPR, type, t, n1);
5982 t = fold_convert (TREE_TYPE (startvar), t);
5983 t = force_gimple_operand_gsi (&gsi, t,
5984 DECL_P (startvar)
5985 && TREE_ADDRESSABLE (startvar),
5986 NULL_TREE, false, GSI_CONTINUE_LINKING);
5987 stmt = gimple_build_assign (startvar, t);
5988 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5990 t = fold_convert (itype, e0);
5991 t = fold_build2 (MULT_EXPR, itype, t, step);
5992 if (POINTER_TYPE_P (type))
5993 t = fold_build_pointer_plus (n1, t);
5994 else
5995 t = fold_build2 (PLUS_EXPR, type, t, n1);
5996 t = fold_convert (TREE_TYPE (startvar), t);
5997 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5998 false, GSI_CONTINUE_LINKING);
5999 if (endvar)
6001 stmt = gimple_build_assign (endvar, e);
6002 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6004 if (fd->collapse > 1)
6005 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6007 if (!broken_loop)
6009 /* The code controlling the sequential loop replaces the
6010 GIMPLE_OMP_CONTINUE. */
6011 gsi = gsi_last_bb (cont_bb);
6012 stmt = gsi_stmt (gsi);
6013 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6014 vmain = gimple_omp_continue_control_use (stmt);
6015 vback = gimple_omp_continue_control_def (stmt);
6017 if (!gimple_omp_for_combined_p (fd->for_stmt))
6019 if (POINTER_TYPE_P (type))
6020 t = fold_build_pointer_plus (vmain, step);
6021 else
6022 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6023 t = force_gimple_operand_gsi (&gsi, t,
6024 DECL_P (vback)
6025 && TREE_ADDRESSABLE (vback),
6026 NULL_TREE, true, GSI_SAME_STMT);
6027 stmt = gimple_build_assign (vback, t);
6028 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6030 t = build2 (fd->loop.cond_code, boolean_type_node,
6031 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6032 ? t : vback, e);
6033 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6036 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6037 gsi_remove (&gsi, true);
6039 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6040 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6043 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6044 gsi = gsi_last_bb (exit_bb);
6045 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6047 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6048 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6050 gsi_remove (&gsi, true);
6052 /* Connect all the blocks. */
6053 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6054 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6055 ep = find_edge (entry_bb, second_bb);
6056 ep->flags = EDGE_TRUE_VALUE;
6057 ep->probability = REG_BR_PROB_BASE / 4;
6058 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6059 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6061 if (!broken_loop)
6063 ep = find_edge (cont_bb, body_bb);
6064 if (gimple_omp_for_combined_p (fd->for_stmt))
6066 remove_edge (ep);
6067 ep = NULL;
6069 else if (fd->collapse > 1)
6071 remove_edge (ep);
6072 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6074 else
6075 ep->flags = EDGE_TRUE_VALUE;
6076 find_edge (cont_bb, fin_bb)->flags
6077 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6080 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6081 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6082 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6084 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6085 recompute_dominator (CDI_DOMINATORS, body_bb));
6086 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6087 recompute_dominator (CDI_DOMINATORS, fin_bb));
6089 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6091 struct loop *loop = alloc_loop ();
6092 loop->header = body_bb;
6093 if (collapse_bb == NULL)
6094 loop->latch = cont_bb;
6095 add_loop (loop, body_bb->loop_father);
6100 /* A subroutine of expand_omp_for. Generate code for a parallel
6101 loop with static schedule and a specified chunk size. Given
6102 parameters:
6104 for (V = N1; V cond N2; V += STEP) BODY;
6106 where COND is "<" or ">", we generate pseudocode
6108 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6109 if (cond is <)
6110 adj = STEP - 1;
6111 else
6112 adj = STEP + 1;
6113 if ((__typeof (V)) -1 > 0 && cond is >)
6114 n = -(adj + N2 - N1) / -STEP;
6115 else
6116 n = (adj + N2 - N1) / STEP;
6117 trip = 0;
6118 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6119 here so that V is defined
6120 if the loop is not entered
6122 s0 = (trip * nthreads + threadid) * CHUNK;
6123 e0 = min(s0 + CHUNK, n);
6124 if (s0 < n) goto L1; else goto L4;
6126 V = s0 * STEP + N1;
6127 e = e0 * STEP + N1;
6129 BODY;
6130 V += STEP;
6131 if (V cond e) goto L2; else goto L3;
6133 trip += 1;
6134 goto L0;
6138 static void
6139 expand_omp_for_static_chunk (struct omp_region *region,
6140 struct omp_for_data *fd, gimple inner_stmt)
6142 tree n, s0, e0, e, t;
6143 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6144 tree type, itype, v_main, v_back, v_extra;
6145 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6146 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6147 gimple_stmt_iterator si;
6148 gimple stmt;
6149 edge se;
6150 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6151 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6152 bool broken_loop = region->cont == NULL;
6153 tree *counts = NULL;
6154 tree n1, n2, step;
6156 itype = type = TREE_TYPE (fd->loop.v);
6157 if (POINTER_TYPE_P (type))
6158 itype = signed_type_for (type);
6160 entry_bb = region->entry;
6161 se = split_block (entry_bb, last_stmt (entry_bb));
6162 entry_bb = se->src;
6163 iter_part_bb = se->dest;
6164 cont_bb = region->cont;
6165 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6166 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6167 gcc_assert (broken_loop
6168 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6169 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6170 body_bb = single_succ (seq_start_bb);
6171 if (!broken_loop)
6173 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6174 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6175 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6177 exit_bb = region->exit;
6179 /* Trip and adjustment setup goes in ENTRY_BB. */
6180 si = gsi_last_bb (entry_bb);
6181 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
6183 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6185 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6186 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6189 if (fd->collapse > 1)
6191 int first_zero_iter = -1;
6192 basic_block l2_dom_bb = NULL;
6194 counts = XALLOCAVEC (tree, fd->collapse);
6195 expand_omp_for_init_counts (fd, &si, entry_bb, counts,
6196 fin_bb, first_zero_iter,
6197 l2_dom_bb);
6198 t = NULL_TREE;
6200 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6201 t = integer_one_node;
6202 else
6203 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6204 fold_convert (type, fd->loop.n1),
6205 fold_convert (type, fd->loop.n2));
6206 if (fd->collapse == 1
6207 && TYPE_UNSIGNED (type)
6208 && (t == NULL_TREE || !integer_onep (t)))
6210 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6211 n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
6212 true, GSI_SAME_STMT);
6213 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6214 n2 = force_gimple_operand_gsi (&si, n2, true, NULL_TREE,
6215 true, GSI_SAME_STMT);
6216 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6217 NULL_TREE, NULL_TREE);
6218 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6219 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6220 expand_omp_regimplify_p, NULL, NULL)
6221 || walk_tree (gimple_cond_rhs_ptr (stmt),
6222 expand_omp_regimplify_p, NULL, NULL))
6224 si = gsi_for_stmt (stmt);
6225 gimple_regimplify_operands (stmt, &si);
6227 se = split_block (entry_bb, stmt);
6228 se->flags = EDGE_TRUE_VALUE;
6229 entry_bb = se->dest;
6230 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6231 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6232 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6233 if (gimple_in_ssa_p (cfun))
6235 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6236 for (si = gsi_start_phis (fin_bb);
6237 !gsi_end_p (si); gsi_next (&si))
6239 gimple phi = gsi_stmt (si);
6240 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6241 se, UNKNOWN_LOCATION);
6244 si = gsi_last_bb (entry_bb);
6247 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6248 t = fold_convert (itype, t);
6249 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6250 true, GSI_SAME_STMT);
6252 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6253 t = fold_convert (itype, t);
6254 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6255 true, GSI_SAME_STMT);
6257 n1 = fd->loop.n1;
6258 n2 = fd->loop.n2;
6259 step = fd->loop.step;
6260 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6262 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6263 OMP_CLAUSE__LOOPTEMP_);
6264 gcc_assert (innerc);
6265 n1 = OMP_CLAUSE_DECL (innerc);
6266 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6267 OMP_CLAUSE__LOOPTEMP_);
6268 gcc_assert (innerc);
6269 n2 = OMP_CLAUSE_DECL (innerc);
6271 n1 = force_gimple_operand_gsi (&si, fold_convert (type, n1),
6272 true, NULL_TREE, true, GSI_SAME_STMT);
6273 n2 = force_gimple_operand_gsi (&si, fold_convert (itype, n2),
6274 true, NULL_TREE, true, GSI_SAME_STMT);
6275 step = force_gimple_operand_gsi (&si, fold_convert (itype, step),
6276 true, NULL_TREE, true, GSI_SAME_STMT);
6277 fd->chunk_size
6278 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
6279 true, NULL_TREE, true, GSI_SAME_STMT);
6281 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6282 t = fold_build2 (PLUS_EXPR, itype, step, t);
6283 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6284 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6285 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6286 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6287 fold_build1 (NEGATE_EXPR, itype, t),
6288 fold_build1 (NEGATE_EXPR, itype, step));
6289 else
6290 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6291 t = fold_convert (itype, t);
6292 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6293 true, GSI_SAME_STMT);
6295 trip_var = create_tmp_reg (itype, ".trip");
6296 if (gimple_in_ssa_p (cfun))
6298 trip_init = make_ssa_name (trip_var, NULL);
6299 trip_main = make_ssa_name (trip_var, NULL);
6300 trip_back = make_ssa_name (trip_var, NULL);
6302 else
6304 trip_init = trip_var;
6305 trip_main = trip_var;
6306 trip_back = trip_var;
6309 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6310 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6312 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6313 t = fold_build2 (MULT_EXPR, itype, t, step);
6314 if (POINTER_TYPE_P (type))
6315 t = fold_build_pointer_plus (n1, t);
6316 else
6317 t = fold_build2 (PLUS_EXPR, type, t, n1);
6318 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6319 true, GSI_SAME_STMT);
6321 /* Remove the GIMPLE_OMP_FOR. */
6322 gsi_remove (&si, true);
6324 /* Iteration space partitioning goes in ITER_PART_BB. */
6325 si = gsi_last_bb (iter_part_bb);
6327 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6328 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6329 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6330 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6331 false, GSI_CONTINUE_LINKING);
6333 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6334 t = fold_build2 (MIN_EXPR, itype, t, n);
6335 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6336 false, GSI_CONTINUE_LINKING);
6338 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6339 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6341 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6342 si = gsi_start_bb (seq_start_bb);
6344 tree startvar = fd->loop.v;
6345 tree endvar = NULL_TREE;
6347 if (gimple_omp_for_combined_p (fd->for_stmt))
6349 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6350 ? gimple_omp_parallel_clauses (inner_stmt)
6351 : gimple_omp_for_clauses (inner_stmt);
6352 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6353 gcc_assert (innerc);
6354 startvar = OMP_CLAUSE_DECL (innerc);
6355 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6356 OMP_CLAUSE__LOOPTEMP_);
6357 gcc_assert (innerc);
6358 endvar = OMP_CLAUSE_DECL (innerc);
6361 t = fold_convert (itype, s0);
6362 t = fold_build2 (MULT_EXPR, itype, t, step);
6363 if (POINTER_TYPE_P (type))
6364 t = fold_build_pointer_plus (n1, t);
6365 else
6366 t = fold_build2 (PLUS_EXPR, type, t, n1);
6367 t = fold_convert (TREE_TYPE (startvar), t);
6368 t = force_gimple_operand_gsi (&si, t,
6369 DECL_P (startvar)
6370 && TREE_ADDRESSABLE (startvar),
6371 NULL_TREE, false, GSI_CONTINUE_LINKING);
6372 stmt = gimple_build_assign (startvar, t);
6373 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6375 t = fold_convert (itype, e0);
6376 t = fold_build2 (MULT_EXPR, itype, t, step);
6377 if (POINTER_TYPE_P (type))
6378 t = fold_build_pointer_plus (n1, t);
6379 else
6380 t = fold_build2 (PLUS_EXPR, type, t, n1);
6381 t = fold_convert (TREE_TYPE (startvar), t);
6382 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6383 false, GSI_CONTINUE_LINKING);
6384 if (endvar)
6386 stmt = gimple_build_assign (endvar, e);
6387 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6389 if (fd->collapse > 1)
6390 expand_omp_for_init_vars (fd, &si, counts, inner_stmt, startvar);
6392 if (!broken_loop)
6394 /* The code controlling the sequential loop goes in CONT_BB,
6395 replacing the GIMPLE_OMP_CONTINUE. */
6396 si = gsi_last_bb (cont_bb);
6397 stmt = gsi_stmt (si);
6398 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6399 v_main = gimple_omp_continue_control_use (stmt);
6400 v_back = gimple_omp_continue_control_def (stmt);
6402 if (!gimple_omp_for_combined_p (fd->for_stmt))
6404 if (POINTER_TYPE_P (type))
6405 t = fold_build_pointer_plus (v_main, step);
6406 else
6407 t = fold_build2 (PLUS_EXPR, type, v_main, step);
6408 if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
6409 t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6410 true, GSI_SAME_STMT);
6411 stmt = gimple_build_assign (v_back, t);
6412 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6414 t = build2 (fd->loop.cond_code, boolean_type_node,
6415 DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
6416 ? t : v_back, e);
6417 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
6420 /* Remove GIMPLE_OMP_CONTINUE. */
6421 gsi_remove (&si, true);
6423 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6424 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6426 /* Trip update code goes into TRIP_UPDATE_BB. */
6427 si = gsi_start_bb (trip_update_bb);
6429 t = build_int_cst (itype, 1);
6430 t = build2 (PLUS_EXPR, itype, trip_main, t);
6431 stmt = gimple_build_assign (trip_back, t);
6432 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6435 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6436 si = gsi_last_bb (exit_bb);
6437 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
6439 t = gimple_omp_return_lhs (gsi_stmt (si));
6440 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
6442 gsi_remove (&si, true);
6444 /* Connect the new blocks. */
6445 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6446 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6448 if (!broken_loop)
6450 se = find_edge (cont_bb, body_bb);
6451 if (gimple_omp_for_combined_p (fd->for_stmt))
6453 remove_edge (se);
6454 se = NULL;
6456 else if (fd->collapse > 1)
6458 remove_edge (se);
6459 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6461 else
6462 se->flags = EDGE_TRUE_VALUE;
6463 find_edge (cont_bb, trip_update_bb)->flags
6464 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6466 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6469 if (gimple_in_ssa_p (cfun))
6471 gimple_stmt_iterator psi;
6472 gimple phi;
6473 edge re, ene;
6474 edge_var_map_vector *head;
6475 edge_var_map *vm;
6476 size_t i;
6478 gcc_assert (fd->collapse == 1 && !broken_loop);
6480 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6481 remove arguments of the phi nodes in fin_bb. We need to create
6482 appropriate phi nodes in iter_part_bb instead. */
6483 se = single_pred_edge (fin_bb);
6484 re = single_succ_edge (trip_update_bb);
6485 head = redirect_edge_var_map_vector (re);
6486 ene = single_succ_edge (entry_bb);
6488 psi = gsi_start_phis (fin_bb);
6489 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6490 gsi_next (&psi), ++i)
6492 gimple nphi;
6493 source_location locus;
6495 phi = gsi_stmt (psi);
6496 t = gimple_phi_result (phi);
6497 gcc_assert (t == redirect_edge_var_map_result (vm));
6498 nphi = create_phi_node (t, iter_part_bb);
6500 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6501 locus = gimple_phi_arg_location_from_edge (phi, se);
6503 /* A special case -- fd->loop.v is not yet computed in
6504 iter_part_bb, we need to use v_extra instead. */
6505 if (t == fd->loop.v)
6506 t = v_extra;
6507 add_phi_arg (nphi, t, ene, locus);
6508 locus = redirect_edge_var_map_location (vm);
6509 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6511 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6512 redirect_edge_var_map_clear (re);
6513 while (1)
6515 psi = gsi_start_phis (fin_bb);
6516 if (gsi_end_p (psi))
6517 break;
6518 remove_phi_node (&psi, false);
6521 /* Make phi node for trip. */
6522 phi = create_phi_node (trip_main, iter_part_bb);
6523 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6524 UNKNOWN_LOCATION);
6525 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6526 UNKNOWN_LOCATION);
6529 if (!broken_loop)
6530 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6531 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6532 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6533 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6534 recompute_dominator (CDI_DOMINATORS, fin_bb));
6535 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6536 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6537 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6538 recompute_dominator (CDI_DOMINATORS, body_bb));
6540 if (!broken_loop)
6542 struct loop *trip_loop = alloc_loop ();
6543 trip_loop->header = iter_part_bb;
6544 trip_loop->latch = trip_update_bb;
6545 add_loop (trip_loop, iter_part_bb->loop_father);
6547 if (!gimple_omp_for_combined_p (fd->for_stmt))
6549 struct loop *loop = alloc_loop ();
6550 loop->header = body_bb;
6551 if (collapse_bb == NULL)
6552 loop->latch = cont_bb;
6553 add_loop (loop, trip_loop);
6559 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6560 loop. Given parameters:
6562 for (V = N1; V cond N2; V += STEP) BODY;
6564 where COND is "<" or ">", we generate pseudocode
6566 V = N1;
6567 goto L1;
6569 BODY;
6570 V += STEP;
6572 if (V cond N2) goto L0; else goto L2;
6575 For collapsed loops, given parameters:
6576 collapse(3)
6577 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6578 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6579 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6580 BODY;
6582 we generate pseudocode
6584 if (cond3 is <)
6585 adj = STEP3 - 1;
6586 else
6587 adj = STEP3 + 1;
6588 count3 = (adj + N32 - N31) / STEP3;
6589 if (cond2 is <)
6590 adj = STEP2 - 1;
6591 else
6592 adj = STEP2 + 1;
6593 count2 = (adj + N22 - N21) / STEP2;
6594 if (cond1 is <)
6595 adj = STEP1 - 1;
6596 else
6597 adj = STEP1 + 1;
6598 count1 = (adj + N12 - N11) / STEP1;
6599 count = count1 * count2 * count3;
6600 V = 0;
6601 V1 = N11;
6602 V2 = N21;
6603 V3 = N31;
6604 goto L1;
6606 BODY;
6607 V += 1;
6608 V3 += STEP3;
6609 V2 += (V3 cond3 N32) ? 0 : STEP2;
6610 V3 = (V3 cond3 N32) ? V3 : N31;
6611 V1 += (V2 cond2 N22) ? 0 : STEP1;
6612 V2 = (V2 cond2 N22) ? V2 : N21;
6614 if (V < count) goto L0; else goto L2;
6619 static void
6620 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
6622 tree type, t;
6623 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
6624 gimple_stmt_iterator gsi;
6625 gimple stmt;
6626 bool broken_loop = region->cont == NULL;
6627 edge e, ne;
6628 tree *counts = NULL;
6629 int i;
6630 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6631 OMP_CLAUSE_SAFELEN);
6632 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6633 OMP_CLAUSE__SIMDUID_);
6634 tree n1, n2;
6636 type = TREE_TYPE (fd->loop.v);
6637 entry_bb = region->entry;
6638 cont_bb = region->cont;
6639 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6640 gcc_assert (broken_loop
6641 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6642 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6643 if (!broken_loop)
6645 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6646 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6647 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6648 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6650 else
6652 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6653 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6654 l2_bb = single_succ (l1_bb);
6656 exit_bb = region->exit;
6657 l2_dom_bb = NULL;
6659 gsi = gsi_last_bb (entry_bb);
6661 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6662 /* Not needed in SSA form right now. */
6663 gcc_assert (!gimple_in_ssa_p (cfun));
6664 if (fd->collapse > 1)
6666 int first_zero_iter = -1;
6667 basic_block zero_iter_bb = l2_bb;
6669 counts = XALLOCAVEC (tree, fd->collapse);
6670 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6671 zero_iter_bb, first_zero_iter,
6672 l2_dom_bb);
6674 if (l2_dom_bb == NULL)
6675 l2_dom_bb = l1_bb;
6677 n1 = fd->loop.n1;
6678 n2 = fd->loop.n2;
6679 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6681 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6682 OMP_CLAUSE__LOOPTEMP_);
6683 gcc_assert (innerc);
6684 n1 = OMP_CLAUSE_DECL (innerc);
6685 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6686 OMP_CLAUSE__LOOPTEMP_);
6687 gcc_assert (innerc);
6688 n2 = OMP_CLAUSE_DECL (innerc);
6689 expand_omp_build_assign (&gsi, fd->loop.v,
6690 fold_convert (type, n1));
6691 if (fd->collapse > 1)
6693 gsi_prev (&gsi);
6694 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
6695 gsi_next (&gsi);
6698 else
6700 expand_omp_build_assign (&gsi, fd->loop.v,
6701 fold_convert (type, fd->loop.n1));
6702 if (fd->collapse > 1)
6703 for (i = 0; i < fd->collapse; i++)
6705 tree itype = TREE_TYPE (fd->loops[i].v);
6706 if (POINTER_TYPE_P (itype))
6707 itype = signed_type_for (itype);
6708 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
6709 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6713 /* Remove the GIMPLE_OMP_FOR statement. */
6714 gsi_remove (&gsi, true);
6716 if (!broken_loop)
6718 /* Code to control the increment goes in the CONT_BB. */
6719 gsi = gsi_last_bb (cont_bb);
6720 stmt = gsi_stmt (gsi);
6721 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6723 if (POINTER_TYPE_P (type))
6724 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
6725 else
6726 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
6727 expand_omp_build_assign (&gsi, fd->loop.v, t);
6729 if (fd->collapse > 1)
6731 i = fd->collapse - 1;
6732 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
6734 t = fold_convert (sizetype, fd->loops[i].step);
6735 t = fold_build_pointer_plus (fd->loops[i].v, t);
6737 else
6739 t = fold_convert (TREE_TYPE (fd->loops[i].v),
6740 fd->loops[i].step);
6741 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
6742 fd->loops[i].v, t);
6744 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6746 for (i = fd->collapse - 1; i > 0; i--)
6748 tree itype = TREE_TYPE (fd->loops[i].v);
6749 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
6750 if (POINTER_TYPE_P (itype2))
6751 itype2 = signed_type_for (itype2);
6752 t = build3 (COND_EXPR, itype2,
6753 build2 (fd->loops[i].cond_code, boolean_type_node,
6754 fd->loops[i].v,
6755 fold_convert (itype, fd->loops[i].n2)),
6756 build_int_cst (itype2, 0),
6757 fold_convert (itype2, fd->loops[i - 1].step));
6758 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
6759 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
6760 else
6761 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
6762 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
6764 t = build3 (COND_EXPR, itype,
6765 build2 (fd->loops[i].cond_code, boolean_type_node,
6766 fd->loops[i].v,
6767 fold_convert (itype, fd->loops[i].n2)),
6768 fd->loops[i].v,
6769 fold_convert (itype, fd->loops[i].n1));
6770 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6774 /* Remove GIMPLE_OMP_CONTINUE. */
6775 gsi_remove (&gsi, true);
6778 /* Emit the condition in L1_BB. */
6779 gsi = gsi_start_bb (l1_bb);
6781 t = fold_convert (type, n2);
6782 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6783 false, GSI_CONTINUE_LINKING);
6784 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
6785 stmt = gimple_build_cond_empty (t);
6786 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6787 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
6788 NULL, NULL)
6789 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
6790 NULL, NULL))
6792 gsi = gsi_for_stmt (stmt);
6793 gimple_regimplify_operands (stmt, &gsi);
6796 /* Remove GIMPLE_OMP_RETURN. */
6797 gsi = gsi_last_bb (exit_bb);
6798 gsi_remove (&gsi, true);
6800 /* Connect the new blocks. */
6801 remove_edge (FALLTHRU_EDGE (entry_bb));
6803 if (!broken_loop)
6805 remove_edge (BRANCH_EDGE (entry_bb));
6806 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6808 e = BRANCH_EDGE (l1_bb);
6809 ne = FALLTHRU_EDGE (l1_bb);
6810 e->flags = EDGE_TRUE_VALUE;
6812 else
6814 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6816 ne = single_succ_edge (l1_bb);
6817 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6820 ne->flags = EDGE_FALSE_VALUE;
6821 e->probability = REG_BR_PROB_BASE * 7 / 8;
6822 ne->probability = REG_BR_PROB_BASE / 8;
6824 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6825 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6826 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6828 if (!broken_loop)
6830 struct loop *loop = alloc_loop ();
6831 loop->header = l1_bb;
6832 loop->latch = cont_bb;
6833 add_loop (loop, l1_bb->loop_father);
6834 if (safelen == NULL_TREE)
6835 loop->safelen = INT_MAX;
6836 else
6838 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
6839 if (!tree_fits_uhwi_p (safelen)
6840 || tree_to_uhwi (safelen) > INT_MAX)
6841 loop->safelen = INT_MAX;
6842 else
6843 loop->safelen = tree_to_uhwi (safelen);
6844 if (loop->safelen == 1)
6845 loop->safelen = 0;
6847 if (simduid)
6849 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
6850 cfun->has_simduid_loops = true;
6852 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
6853 the loop. */
6854 if ((flag_tree_loop_vectorize
6855 || (!global_options_set.x_flag_tree_loop_vectorize
6856 && !global_options_set.x_flag_tree_vectorize))
6857 && flag_tree_loop_optimize
6858 && loop->safelen > 1)
6860 loop->force_vectorize = true;
6861 cfun->has_force_vectorize_loops = true;
6867 /* Expand the OpenMP loop defined by REGION. */
6869 static void
6870 expand_omp_for (struct omp_region *region, gimple inner_stmt)
6872 struct omp_for_data fd;
6873 struct omp_for_data_loop *loops;
6875 loops
6876 = (struct omp_for_data_loop *)
6877 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
6878 * sizeof (struct omp_for_data_loop));
6879 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
6880 region->sched_kind = fd.sched_kind;
6882 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
6883 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6884 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6885 if (region->cont)
6887 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
6888 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6889 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6891 else
6892 /* If there isn't a continue then this is a degerate case where
6893 the introduction of abnormal edges during lowering will prevent
6894 original loops from being detected. Fix that up. */
6895 loops_state_set (LOOPS_NEED_FIXUP);
6897 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_KIND_SIMD)
6898 expand_omp_simd (region, &fd);
6899 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
6900 && !fd.have_ordered)
6902 if (fd.chunk_size == NULL)
6903 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
6904 else
6905 expand_omp_for_static_chunk (region, &fd, inner_stmt);
6907 else
6909 int fn_index, start_ix, next_ix;
6911 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
6912 == GF_OMP_FOR_KIND_FOR);
6913 if (fd.chunk_size == NULL
6914 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
6915 fd.chunk_size = integer_zero_node;
6916 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6917 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
6918 ? 3 : fd.sched_kind;
6919 fn_index += fd.have_ordered * 4;
6920 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
6921 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
6922 if (fd.iter_type == long_long_unsigned_type_node)
6924 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
6925 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
6926 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
6927 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
6929 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
6930 (enum built_in_function) next_ix, inner_stmt);
6933 if (gimple_in_ssa_p (cfun))
6934 update_ssa (TODO_update_ssa_only_virtuals);
6938 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
6940 v = GOMP_sections_start (n);
6942 switch (v)
6944 case 0:
6945 goto L2;
6946 case 1:
6947 section 1;
6948 goto L1;
6949 case 2:
6951 case n:
6953 default:
6954 abort ();
6957 v = GOMP_sections_next ();
6958 goto L0;
6960 reduction;
6962 If this is a combined parallel sections, replace the call to
6963 GOMP_sections_start with call to GOMP_sections_next. */
6965 static void
6966 expand_omp_sections (struct omp_region *region)
6968 tree t, u, vin = NULL, vmain, vnext, l2;
6969 unsigned len;
6970 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
6971 gimple_stmt_iterator si, switch_si;
6972 gimple sections_stmt, stmt, cont;
6973 edge_iterator ei;
6974 edge e;
6975 struct omp_region *inner;
6976 unsigned i, casei;
6977 bool exit_reachable = region->cont != NULL;
6979 gcc_assert (region->exit != NULL);
6980 entry_bb = region->entry;
6981 l0_bb = single_succ (entry_bb);
6982 l1_bb = region->cont;
6983 l2_bb = region->exit;
6984 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
6985 l2 = gimple_block_label (l2_bb);
6986 else
6988 /* This can happen if there are reductions. */
6989 len = EDGE_COUNT (l0_bb->succs);
6990 gcc_assert (len > 0);
6991 e = EDGE_SUCC (l0_bb, len - 1);
6992 si = gsi_last_bb (e->dest);
6993 l2 = NULL_TREE;
6994 if (gsi_end_p (si)
6995 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
6996 l2 = gimple_block_label (e->dest);
6997 else
6998 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7000 si = gsi_last_bb (e->dest);
7001 if (gsi_end_p (si)
7002 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7004 l2 = gimple_block_label (e->dest);
7005 break;
7009 if (exit_reachable)
7010 default_bb = create_empty_bb (l1_bb->prev_bb);
7011 else
7012 default_bb = create_empty_bb (l0_bb);
7014 /* We will build a switch() with enough cases for all the
7015 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7016 and a default case to abort if something goes wrong. */
7017 len = EDGE_COUNT (l0_bb->succs);
7019 /* Use vec::quick_push on label_vec throughout, since we know the size
7020 in advance. */
7021 auto_vec<tree> label_vec (len);
7023 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7024 GIMPLE_OMP_SECTIONS statement. */
7025 si = gsi_last_bb (entry_bb);
7026 sections_stmt = gsi_stmt (si);
7027 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7028 vin = gimple_omp_sections_control (sections_stmt);
7029 if (!is_combined_parallel (region))
7031 /* If we are not inside a combined parallel+sections region,
7032 call GOMP_sections_start. */
7033 t = build_int_cst (unsigned_type_node, len - 1);
7034 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7035 stmt = gimple_build_call (u, 1, t);
7037 else
7039 /* Otherwise, call GOMP_sections_next. */
7040 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7041 stmt = gimple_build_call (u, 0);
7043 gimple_call_set_lhs (stmt, vin);
7044 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7045 gsi_remove (&si, true);
7047 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7048 L0_BB. */
7049 switch_si = gsi_last_bb (l0_bb);
7050 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7051 if (exit_reachable)
7053 cont = last_stmt (l1_bb);
7054 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7055 vmain = gimple_omp_continue_control_use (cont);
7056 vnext = gimple_omp_continue_control_def (cont);
7058 else
7060 vmain = vin;
7061 vnext = NULL_TREE;
7064 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7065 label_vec.quick_push (t);
7066 i = 1;
7068 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7069 for (inner = region->inner, casei = 1;
7070 inner;
7071 inner = inner->next, i++, casei++)
7073 basic_block s_entry_bb, s_exit_bb;
7075 /* Skip optional reduction region. */
7076 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7078 --i;
7079 --casei;
7080 continue;
7083 s_entry_bb = inner->entry;
7084 s_exit_bb = inner->exit;
7086 t = gimple_block_label (s_entry_bb);
7087 u = build_int_cst (unsigned_type_node, casei);
7088 u = build_case_label (u, NULL, t);
7089 label_vec.quick_push (u);
7091 si = gsi_last_bb (s_entry_bb);
7092 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7093 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7094 gsi_remove (&si, true);
7095 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7097 if (s_exit_bb == NULL)
7098 continue;
7100 si = gsi_last_bb (s_exit_bb);
7101 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7102 gsi_remove (&si, true);
7104 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7107 /* Error handling code goes in DEFAULT_BB. */
7108 t = gimple_block_label (default_bb);
7109 u = build_case_label (NULL, NULL, t);
7110 make_edge (l0_bb, default_bb, 0);
7111 if (current_loops)
7112 add_bb_to_loop (default_bb, current_loops->tree_root);
7114 stmt = gimple_build_switch (vmain, u, label_vec);
7115 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7116 gsi_remove (&switch_si, true);
7118 si = gsi_start_bb (default_bb);
7119 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7120 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7122 if (exit_reachable)
7124 tree bfn_decl;
7126 /* Code to get the next section goes in L1_BB. */
7127 si = gsi_last_bb (l1_bb);
7128 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7130 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7131 stmt = gimple_build_call (bfn_decl, 0);
7132 gimple_call_set_lhs (stmt, vnext);
7133 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7134 gsi_remove (&si, true);
7136 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7139 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7140 si = gsi_last_bb (l2_bb);
7141 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7142 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7143 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7144 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7145 else
7146 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7147 stmt = gimple_build_call (t, 0);
7148 if (gimple_omp_return_lhs (gsi_stmt (si)))
7149 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7150 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7151 gsi_remove (&si, true);
7153 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7157 /* Expand code for an OpenMP single directive. We've already expanded
7158 much of the code, here we simply place the GOMP_barrier call. */
7160 static void
7161 expand_omp_single (struct omp_region *region)
7163 basic_block entry_bb, exit_bb;
7164 gimple_stmt_iterator si;
7166 entry_bb = region->entry;
7167 exit_bb = region->exit;
7169 si = gsi_last_bb (entry_bb);
7170 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7171 gsi_remove (&si, true);
7172 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7174 si = gsi_last_bb (exit_bb);
7175 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7177 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7178 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7180 gsi_remove (&si, true);
7181 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7185 /* Generic expansion for OpenMP synchronization directives: master,
7186 ordered and critical. All we need to do here is remove the entry
7187 and exit markers for REGION. */
7189 static void
7190 expand_omp_synch (struct omp_region *region)
7192 basic_block entry_bb, exit_bb;
7193 gimple_stmt_iterator si;
7195 entry_bb = region->entry;
7196 exit_bb = region->exit;
7198 si = gsi_last_bb (entry_bb);
7199 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7200 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7201 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7202 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7203 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7204 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7205 gsi_remove (&si, true);
7206 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7208 if (exit_bb)
7210 si = gsi_last_bb (exit_bb);
7211 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7212 gsi_remove (&si, true);
7213 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7217 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7218 operation as a normal volatile load. */
7220 static bool
7221 expand_omp_atomic_load (basic_block load_bb, tree addr,
7222 tree loaded_val, int index)
7224 enum built_in_function tmpbase;
7225 gimple_stmt_iterator gsi;
7226 basic_block store_bb;
7227 location_t loc;
7228 gimple stmt;
7229 tree decl, call, type, itype;
7231 gsi = gsi_last_bb (load_bb);
7232 stmt = gsi_stmt (gsi);
7233 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7234 loc = gimple_location (stmt);
7236 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7237 is smaller than word size, then expand_atomic_load assumes that the load
7238 is atomic. We could avoid the builtin entirely in this case. */
7240 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7241 decl = builtin_decl_explicit (tmpbase);
7242 if (decl == NULL_TREE)
7243 return false;
7245 type = TREE_TYPE (loaded_val);
7246 itype = TREE_TYPE (TREE_TYPE (decl));
7248 call = build_call_expr_loc (loc, decl, 2, addr,
7249 build_int_cst (NULL,
7250 gimple_omp_atomic_seq_cst_p (stmt)
7251 ? MEMMODEL_SEQ_CST
7252 : MEMMODEL_RELAXED));
7253 if (!useless_type_conversion_p (type, itype))
7254 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7255 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7257 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7258 gsi_remove (&gsi, true);
7260 store_bb = single_succ (load_bb);
7261 gsi = gsi_last_bb (store_bb);
7262 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7263 gsi_remove (&gsi, true);
7265 if (gimple_in_ssa_p (cfun))
7266 update_ssa (TODO_update_ssa_no_phi);
7268 return true;
7271 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7272 operation as a normal volatile store. */
7274 static bool
7275 expand_omp_atomic_store (basic_block load_bb, tree addr,
7276 tree loaded_val, tree stored_val, int index)
7278 enum built_in_function tmpbase;
7279 gimple_stmt_iterator gsi;
7280 basic_block store_bb = single_succ (load_bb);
7281 location_t loc;
7282 gimple stmt;
7283 tree decl, call, type, itype;
7284 enum machine_mode imode;
7285 bool exchange;
7287 gsi = gsi_last_bb (load_bb);
7288 stmt = gsi_stmt (gsi);
7289 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7291 /* If the load value is needed, then this isn't a store but an exchange. */
7292 exchange = gimple_omp_atomic_need_value_p (stmt);
7294 gsi = gsi_last_bb (store_bb);
7295 stmt = gsi_stmt (gsi);
7296 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7297 loc = gimple_location (stmt);
7299 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7300 is smaller than word size, then expand_atomic_store assumes that the store
7301 is atomic. We could avoid the builtin entirely in this case. */
7303 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7304 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7305 decl = builtin_decl_explicit (tmpbase);
7306 if (decl == NULL_TREE)
7307 return false;
7309 type = TREE_TYPE (stored_val);
7311 /* Dig out the type of the function's second argument. */
7312 itype = TREE_TYPE (decl);
7313 itype = TYPE_ARG_TYPES (itype);
7314 itype = TREE_CHAIN (itype);
7315 itype = TREE_VALUE (itype);
7316 imode = TYPE_MODE (itype);
7318 if (exchange && !can_atomic_exchange_p (imode, true))
7319 return false;
7321 if (!useless_type_conversion_p (itype, type))
7322 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7323 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7324 build_int_cst (NULL,
7325 gimple_omp_atomic_seq_cst_p (stmt)
7326 ? MEMMODEL_SEQ_CST
7327 : MEMMODEL_RELAXED));
7328 if (exchange)
7330 if (!useless_type_conversion_p (type, itype))
7331 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7332 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7335 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7336 gsi_remove (&gsi, true);
7338 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7339 gsi = gsi_last_bb (load_bb);
7340 gsi_remove (&gsi, true);
7342 if (gimple_in_ssa_p (cfun))
7343 update_ssa (TODO_update_ssa_no_phi);
7345 return true;
7348 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7349 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7350 size of the data type, and thus usable to find the index of the builtin
7351 decl. Returns false if the expression is not of the proper form. */
7353 static bool
7354 expand_omp_atomic_fetch_op (basic_block load_bb,
7355 tree addr, tree loaded_val,
7356 tree stored_val, int index)
7358 enum built_in_function oldbase, newbase, tmpbase;
7359 tree decl, itype, call;
7360 tree lhs, rhs;
7361 basic_block store_bb = single_succ (load_bb);
7362 gimple_stmt_iterator gsi;
7363 gimple stmt;
7364 location_t loc;
7365 enum tree_code code;
7366 bool need_old, need_new;
7367 enum machine_mode imode;
7368 bool seq_cst;
7370 /* We expect to find the following sequences:
7372 load_bb:
7373 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7375 store_bb:
7376 val = tmp OP something; (or: something OP tmp)
7377 GIMPLE_OMP_STORE (val)
7379 ???FIXME: Allow a more flexible sequence.
7380 Perhaps use data flow to pick the statements.
7384 gsi = gsi_after_labels (store_bb);
7385 stmt = gsi_stmt (gsi);
7386 loc = gimple_location (stmt);
7387 if (!is_gimple_assign (stmt))
7388 return false;
7389 gsi_next (&gsi);
7390 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7391 return false;
7392 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7393 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7394 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7395 gcc_checking_assert (!need_old || !need_new);
7397 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7398 return false;
7400 /* Check for one of the supported fetch-op operations. */
7401 code = gimple_assign_rhs_code (stmt);
7402 switch (code)
7404 case PLUS_EXPR:
7405 case POINTER_PLUS_EXPR:
7406 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7407 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7408 break;
7409 case MINUS_EXPR:
7410 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7411 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7412 break;
7413 case BIT_AND_EXPR:
7414 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7415 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7416 break;
7417 case BIT_IOR_EXPR:
7418 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7419 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7420 break;
7421 case BIT_XOR_EXPR:
7422 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7423 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7424 break;
7425 default:
7426 return false;
7429 /* Make sure the expression is of the proper form. */
7430 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7431 rhs = gimple_assign_rhs2 (stmt);
7432 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7433 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7434 rhs = gimple_assign_rhs1 (stmt);
7435 else
7436 return false;
7438 tmpbase = ((enum built_in_function)
7439 ((need_new ? newbase : oldbase) + index + 1));
7440 decl = builtin_decl_explicit (tmpbase);
7441 if (decl == NULL_TREE)
7442 return false;
7443 itype = TREE_TYPE (TREE_TYPE (decl));
7444 imode = TYPE_MODE (itype);
7446 /* We could test all of the various optabs involved, but the fact of the
7447 matter is that (with the exception of i486 vs i586 and xadd) all targets
7448 that support any atomic operaton optab also implements compare-and-swap.
7449 Let optabs.c take care of expanding any compare-and-swap loop. */
7450 if (!can_compare_and_swap_p (imode, true))
7451 return false;
7453 gsi = gsi_last_bb (load_bb);
7454 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7456 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7457 It only requires that the operation happen atomically. Thus we can
7458 use the RELAXED memory model. */
7459 call = build_call_expr_loc (loc, decl, 3, addr,
7460 fold_convert_loc (loc, itype, rhs),
7461 build_int_cst (NULL,
7462 seq_cst ? MEMMODEL_SEQ_CST
7463 : MEMMODEL_RELAXED));
7465 if (need_old || need_new)
7467 lhs = need_old ? loaded_val : stored_val;
7468 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7469 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7471 else
7472 call = fold_convert_loc (loc, void_type_node, call);
7473 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7474 gsi_remove (&gsi, true);
7476 gsi = gsi_last_bb (store_bb);
7477 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7478 gsi_remove (&gsi, true);
7479 gsi = gsi_last_bb (store_bb);
7480 gsi_remove (&gsi, true);
7482 if (gimple_in_ssa_p (cfun))
7483 update_ssa (TODO_update_ssa_no_phi);
7485 return true;
7488 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7490 oldval = *addr;
7491 repeat:
7492 newval = rhs; // with oldval replacing *addr in rhs
7493 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7494 if (oldval != newval)
7495 goto repeat;
7497 INDEX is log2 of the size of the data type, and thus usable to find the
7498 index of the builtin decl. */
7500 static bool
7501 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7502 tree addr, tree loaded_val, tree stored_val,
7503 int index)
7505 tree loadedi, storedi, initial, new_storedi, old_vali;
7506 tree type, itype, cmpxchg, iaddr;
7507 gimple_stmt_iterator si;
7508 basic_block loop_header = single_succ (load_bb);
7509 gimple phi, stmt;
7510 edge e;
7511 enum built_in_function fncode;
7513 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7514 order to use the RELAXED memory model effectively. */
7515 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7516 + index + 1);
7517 cmpxchg = builtin_decl_explicit (fncode);
7518 if (cmpxchg == NULL_TREE)
7519 return false;
7520 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7521 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7523 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7524 return false;
7526 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7527 si = gsi_last_bb (load_bb);
7528 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7530 /* For floating-point values, we'll need to view-convert them to integers
7531 so that we can perform the atomic compare and swap. Simplify the
7532 following code by always setting up the "i"ntegral variables. */
7533 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7535 tree iaddr_val;
7537 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7538 true), NULL);
7539 iaddr_val
7540 = force_gimple_operand_gsi (&si,
7541 fold_convert (TREE_TYPE (iaddr), addr),
7542 false, NULL_TREE, true, GSI_SAME_STMT);
7543 stmt = gimple_build_assign (iaddr, iaddr_val);
7544 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7545 loadedi = create_tmp_var (itype, NULL);
7546 if (gimple_in_ssa_p (cfun))
7547 loadedi = make_ssa_name (loadedi, NULL);
7549 else
7551 iaddr = addr;
7552 loadedi = loaded_val;
7555 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7556 tree loaddecl = builtin_decl_explicit (fncode);
7557 if (loaddecl)
7558 initial
7559 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
7560 build_call_expr (loaddecl, 2, iaddr,
7561 build_int_cst (NULL_TREE,
7562 MEMMODEL_RELAXED)));
7563 else
7564 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
7565 build_int_cst (TREE_TYPE (iaddr), 0));
7567 initial
7568 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
7569 GSI_SAME_STMT);
7571 /* Move the value to the LOADEDI temporary. */
7572 if (gimple_in_ssa_p (cfun))
7574 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
7575 phi = create_phi_node (loadedi, loop_header);
7576 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
7577 initial);
7579 else
7580 gsi_insert_before (&si,
7581 gimple_build_assign (loadedi, initial),
7582 GSI_SAME_STMT);
7583 if (loadedi != loaded_val)
7585 gimple_stmt_iterator gsi2;
7586 tree x;
7588 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
7589 gsi2 = gsi_start_bb (loop_header);
7590 if (gimple_in_ssa_p (cfun))
7592 gimple stmt;
7593 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7594 true, GSI_SAME_STMT);
7595 stmt = gimple_build_assign (loaded_val, x);
7596 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
7598 else
7600 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
7601 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7602 true, GSI_SAME_STMT);
7605 gsi_remove (&si, true);
7607 si = gsi_last_bb (store_bb);
7608 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7610 if (iaddr == addr)
7611 storedi = stored_val;
7612 else
7613 storedi =
7614 force_gimple_operand_gsi (&si,
7615 build1 (VIEW_CONVERT_EXPR, itype,
7616 stored_val), true, NULL_TREE, true,
7617 GSI_SAME_STMT);
7619 /* Build the compare&swap statement. */
7620 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
7621 new_storedi = force_gimple_operand_gsi (&si,
7622 fold_convert (TREE_TYPE (loadedi),
7623 new_storedi),
7624 true, NULL_TREE,
7625 true, GSI_SAME_STMT);
7627 if (gimple_in_ssa_p (cfun))
7628 old_vali = loadedi;
7629 else
7631 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
7632 stmt = gimple_build_assign (old_vali, loadedi);
7633 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7635 stmt = gimple_build_assign (loadedi, new_storedi);
7636 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7639 /* Note that we always perform the comparison as an integer, even for
7640 floating point. This allows the atomic operation to properly
7641 succeed even with NaNs and -0.0. */
7642 stmt = gimple_build_cond_empty
7643 (build2 (NE_EXPR, boolean_type_node,
7644 new_storedi, old_vali));
7645 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7647 /* Update cfg. */
7648 e = single_succ_edge (store_bb);
7649 e->flags &= ~EDGE_FALLTHRU;
7650 e->flags |= EDGE_FALSE_VALUE;
7652 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
7654 /* Copy the new value to loadedi (we already did that before the condition
7655 if we are not in SSA). */
7656 if (gimple_in_ssa_p (cfun))
7658 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
7659 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
7662 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
7663 gsi_remove (&si, true);
7665 struct loop *loop = alloc_loop ();
7666 loop->header = loop_header;
7667 loop->latch = store_bb;
7668 add_loop (loop, loop_header->loop_father);
7670 if (gimple_in_ssa_p (cfun))
7671 update_ssa (TODO_update_ssa_no_phi);
7673 return true;
7676 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7678 GOMP_atomic_start ();
7679 *addr = rhs;
7680 GOMP_atomic_end ();
7682 The result is not globally atomic, but works so long as all parallel
7683 references are within #pragma omp atomic directives. According to
7684 responses received from omp@openmp.org, appears to be within spec.
7685 Which makes sense, since that's how several other compilers handle
7686 this situation as well.
7687 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
7688 expanding. STORED_VAL is the operand of the matching
7689 GIMPLE_OMP_ATOMIC_STORE.
7691 We replace
7692 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
7693 loaded_val = *addr;
7695 and replace
7696 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
7697 *addr = stored_val;
7700 static bool
7701 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
7702 tree addr, tree loaded_val, tree stored_val)
7704 gimple_stmt_iterator si;
7705 gimple stmt;
7706 tree t;
7708 si = gsi_last_bb (load_bb);
7709 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7711 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
7712 t = build_call_expr (t, 0);
7713 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7715 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
7716 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7717 gsi_remove (&si, true);
7719 si = gsi_last_bb (store_bb);
7720 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7722 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
7723 stored_val);
7724 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7726 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
7727 t = build_call_expr (t, 0);
7728 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7729 gsi_remove (&si, true);
7731 if (gimple_in_ssa_p (cfun))
7732 update_ssa (TODO_update_ssa_no_phi);
7733 return true;
7736 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
7737 using expand_omp_atomic_fetch_op. If it failed, we try to
7738 call expand_omp_atomic_pipeline, and if it fails too, the
7739 ultimate fallback is wrapping the operation in a mutex
7740 (expand_omp_atomic_mutex). REGION is the atomic region built
7741 by build_omp_regions_1(). */
7743 static void
7744 expand_omp_atomic (struct omp_region *region)
7746 basic_block load_bb = region->entry, store_bb = region->exit;
7747 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
7748 tree loaded_val = gimple_omp_atomic_load_lhs (load);
7749 tree addr = gimple_omp_atomic_load_rhs (load);
7750 tree stored_val = gimple_omp_atomic_store_val (store);
7751 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7752 HOST_WIDE_INT index;
7754 /* Make sure the type is one of the supported sizes. */
7755 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
7756 index = exact_log2 (index);
7757 if (index >= 0 && index <= 4)
7759 unsigned int align = TYPE_ALIGN_UNIT (type);
7761 /* __sync builtins require strict data alignment. */
7762 if (exact_log2 (align) >= index)
7764 /* Atomic load. */
7765 if (loaded_val == stored_val
7766 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7767 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7768 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7769 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
7770 return;
7772 /* Atomic store. */
7773 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7774 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7775 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7776 && store_bb == single_succ (load_bb)
7777 && first_stmt (store_bb) == store
7778 && expand_omp_atomic_store (load_bb, addr, loaded_val,
7779 stored_val, index))
7780 return;
7782 /* When possible, use specialized atomic update functions. */
7783 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
7784 && store_bb == single_succ (load_bb)
7785 && expand_omp_atomic_fetch_op (load_bb, addr,
7786 loaded_val, stored_val, index))
7787 return;
7789 /* If we don't have specialized __sync builtins, try and implement
7790 as a compare and swap loop. */
7791 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
7792 loaded_val, stored_val, index))
7793 return;
7797 /* The ultimate fallback is wrapping the operation in a mutex. */
7798 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
7802 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
7804 static void
7805 expand_omp_target (struct omp_region *region)
7807 basic_block entry_bb, exit_bb, new_bb;
7808 struct function *child_cfun = NULL;
7809 tree child_fn = NULL_TREE, block, t;
7810 gimple_stmt_iterator gsi;
7811 gimple entry_stmt, stmt;
7812 edge e;
7814 entry_stmt = last_stmt (region->entry);
7815 new_bb = region->entry;
7816 int kind = gimple_omp_target_kind (entry_stmt);
7817 if (kind == GF_OMP_TARGET_KIND_REGION)
7819 child_fn = gimple_omp_target_child_fn (entry_stmt);
7820 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7823 entry_bb = region->entry;
7824 exit_bb = region->exit;
7826 if (kind == GF_OMP_TARGET_KIND_REGION)
7828 unsigned srcidx, dstidx, num;
7830 /* If the target region needs data sent from the parent
7831 function, then the very first statement (except possible
7832 tree profile counter updates) of the parallel body
7833 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7834 &.OMP_DATA_O is passed as an argument to the child function,
7835 we need to replace it with the argument as seen by the child
7836 function.
7838 In most cases, this will end up being the identity assignment
7839 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7840 a function call that has been inlined, the original PARM_DECL
7841 .OMP_DATA_I may have been converted into a different local
7842 variable. In which case, we need to keep the assignment. */
7843 if (gimple_omp_target_data_arg (entry_stmt))
7845 basic_block entry_succ_bb = single_succ (entry_bb);
7846 gimple_stmt_iterator gsi;
7847 tree arg;
7848 gimple tgtcopy_stmt = NULL;
7849 tree sender
7850 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
7852 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7854 gcc_assert (!gsi_end_p (gsi));
7855 stmt = gsi_stmt (gsi);
7856 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7857 continue;
7859 if (gimple_num_ops (stmt) == 2)
7861 tree arg = gimple_assign_rhs1 (stmt);
7863 /* We're ignoring the subcode because we're
7864 effectively doing a STRIP_NOPS. */
7866 if (TREE_CODE (arg) == ADDR_EXPR
7867 && TREE_OPERAND (arg, 0) == sender)
7869 tgtcopy_stmt = stmt;
7870 break;
7875 gcc_assert (tgtcopy_stmt != NULL);
7876 arg = DECL_ARGUMENTS (child_fn);
7878 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
7879 gsi_remove (&gsi, true);
7882 /* Declare local variables needed in CHILD_CFUN. */
7883 block = DECL_INITIAL (child_fn);
7884 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7885 /* The gimplifier could record temporaries in target block
7886 rather than in containing function's local_decls chain,
7887 which would mean cgraph missed finalizing them. Do it now. */
7888 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7889 if (TREE_CODE (t) == VAR_DECL
7890 && TREE_STATIC (t)
7891 && !DECL_EXTERNAL (t))
7892 varpool_finalize_decl (t);
7893 DECL_SAVED_TREE (child_fn) = NULL;
7894 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7895 gimple_set_body (child_fn, NULL);
7896 TREE_USED (block) = 1;
7898 /* Reset DECL_CONTEXT on function arguments. */
7899 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7900 DECL_CONTEXT (t) = child_fn;
7902 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
7903 so that it can be moved to the child function. */
7904 gsi = gsi_last_bb (entry_bb);
7905 stmt = gsi_stmt (gsi);
7906 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
7907 && gimple_omp_target_kind (stmt)
7908 == GF_OMP_TARGET_KIND_REGION);
7909 gsi_remove (&gsi, true);
7910 e = split_block (entry_bb, stmt);
7911 entry_bb = e->dest;
7912 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7914 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
7915 if (exit_bb)
7917 gsi = gsi_last_bb (exit_bb);
7918 gcc_assert (!gsi_end_p (gsi)
7919 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7920 stmt = gimple_build_return (NULL);
7921 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7922 gsi_remove (&gsi, true);
7925 /* Move the target region into CHILD_CFUN. */
7927 block = gimple_block (entry_stmt);
7929 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7930 if (exit_bb)
7931 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7932 /* When the OMP expansion process cannot guarantee an up-to-date
7933 loop tree arrange for the child function to fixup loops. */
7934 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7935 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7937 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7938 num = vec_safe_length (child_cfun->local_decls);
7939 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7941 t = (*child_cfun->local_decls)[srcidx];
7942 if (DECL_CONTEXT (t) == cfun->decl)
7943 continue;
7944 if (srcidx != dstidx)
7945 (*child_cfun->local_decls)[dstidx] = t;
7946 dstidx++;
7948 if (dstidx != num)
7949 vec_safe_truncate (child_cfun->local_decls, dstidx);
7951 /* Inform the callgraph about the new function. */
7952 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
7953 cgraph_add_new_function (child_fn, true);
7955 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7956 fixed in a following pass. */
7957 push_cfun (child_cfun);
7958 rebuild_cgraph_edges ();
7960 /* Some EH regions might become dead, see PR34608. If
7961 pass_cleanup_cfg isn't the first pass to happen with the
7962 new child, these dead EH edges might cause problems.
7963 Clean them up now. */
7964 if (flag_exceptions)
7966 basic_block bb;
7967 bool changed = false;
7969 FOR_EACH_BB_FN (bb, cfun)
7970 changed |= gimple_purge_dead_eh_edges (bb);
7971 if (changed)
7972 cleanup_tree_cfg ();
7974 pop_cfun ();
7977 /* Emit a library call to launch the target region, or do data
7978 transfers. */
7979 tree t1, t2, t3, t4, device, cond, c, clauses;
7980 enum built_in_function start_ix;
7981 location_t clause_loc;
7983 clauses = gimple_omp_target_clauses (entry_stmt);
7985 if (kind == GF_OMP_TARGET_KIND_REGION)
7986 start_ix = BUILT_IN_GOMP_TARGET;
7987 else if (kind == GF_OMP_TARGET_KIND_DATA)
7988 start_ix = BUILT_IN_GOMP_TARGET_DATA;
7989 else
7990 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
7992 /* By default, the value of DEVICE is -1 (let runtime library choose)
7993 and there is no conditional. */
7994 cond = NULL_TREE;
7995 device = build_int_cst (integer_type_node, -1);
7997 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
7998 if (c)
7999 cond = OMP_CLAUSE_IF_EXPR (c);
8001 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8002 if (c)
8004 device = OMP_CLAUSE_DEVICE_ID (c);
8005 clause_loc = OMP_CLAUSE_LOCATION (c);
8007 else
8008 clause_loc = gimple_location (entry_stmt);
8010 /* Ensure 'device' is of the correct type. */
8011 device = fold_convert_loc (clause_loc, integer_type_node, device);
8013 /* If we found the clause 'if (cond)', build
8014 (cond ? device : -2). */
8015 if (cond)
8017 cond = gimple_boolify (cond);
8019 basic_block cond_bb, then_bb, else_bb;
8020 edge e;
8021 tree tmp_var;
8023 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8024 if (kind != GF_OMP_TARGET_KIND_REGION)
8026 gsi = gsi_last_bb (new_bb);
8027 gsi_prev (&gsi);
8028 e = split_block (new_bb, gsi_stmt (gsi));
8030 else
8031 e = split_block (new_bb, NULL);
8032 cond_bb = e->src;
8033 new_bb = e->dest;
8034 remove_edge (e);
8036 then_bb = create_empty_bb (cond_bb);
8037 else_bb = create_empty_bb (then_bb);
8038 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8039 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8041 stmt = gimple_build_cond_empty (cond);
8042 gsi = gsi_last_bb (cond_bb);
8043 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8045 gsi = gsi_start_bb (then_bb);
8046 stmt = gimple_build_assign (tmp_var, device);
8047 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8049 gsi = gsi_start_bb (else_bb);
8050 stmt = gimple_build_assign (tmp_var,
8051 build_int_cst (integer_type_node, -2));
8052 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8054 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8055 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8056 if (current_loops)
8058 add_bb_to_loop (then_bb, cond_bb->loop_father);
8059 add_bb_to_loop (else_bb, cond_bb->loop_father);
8061 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8062 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8064 device = tmp_var;
8067 gsi = gsi_last_bb (new_bb);
8068 t = gimple_omp_target_data_arg (entry_stmt);
8069 if (t == NULL)
8071 t1 = size_zero_node;
8072 t2 = build_zero_cst (ptr_type_node);
8073 t3 = t2;
8074 t4 = t2;
8076 else
8078 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8079 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8080 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8081 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8082 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8085 gimple g;
8086 /* FIXME: This will be address of
8087 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8088 symbol, as soon as the linker plugin is able to create it for us. */
8089 tree openmp_target = build_zero_cst (ptr_type_node);
8090 if (kind == GF_OMP_TARGET_KIND_REGION)
8092 tree fnaddr = build_fold_addr_expr (child_fn);
8093 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8094 device, fnaddr, openmp_target, t1, t2, t3, t4);
8096 else
8097 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8098 device, openmp_target, t1, t2, t3, t4);
8099 gimple_set_location (g, gimple_location (entry_stmt));
8100 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8101 if (kind != GF_OMP_TARGET_KIND_REGION)
8103 g = gsi_stmt (gsi);
8104 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8105 gsi_remove (&gsi, true);
8107 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8109 gsi = gsi_last_bb (region->exit);
8110 g = gsi_stmt (gsi);
8111 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8112 gsi_remove (&gsi, true);
8117 /* Expand the parallel region tree rooted at REGION. Expansion
8118 proceeds in depth-first order. Innermost regions are expanded
8119 first. This way, parallel regions that require a new function to
8120 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8121 internal dependencies in their body. */
8123 static void
8124 expand_omp (struct omp_region *region)
8126 while (region)
8128 location_t saved_location;
8129 gimple inner_stmt = NULL;
8131 /* First, determine whether this is a combined parallel+workshare
8132 region. */
8133 if (region->type == GIMPLE_OMP_PARALLEL)
8134 determine_parallel_type (region);
8136 if (region->type == GIMPLE_OMP_FOR
8137 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8138 inner_stmt = last_stmt (region->inner->entry);
8140 if (region->inner)
8141 expand_omp (region->inner);
8143 saved_location = input_location;
8144 if (gimple_has_location (last_stmt (region->entry)))
8145 input_location = gimple_location (last_stmt (region->entry));
8147 switch (region->type)
8149 case GIMPLE_OMP_PARALLEL:
8150 case GIMPLE_OMP_TASK:
8151 expand_omp_taskreg (region);
8152 break;
8154 case GIMPLE_OMP_FOR:
8155 expand_omp_for (region, inner_stmt);
8156 break;
8158 case GIMPLE_OMP_SECTIONS:
8159 expand_omp_sections (region);
8160 break;
8162 case GIMPLE_OMP_SECTION:
8163 /* Individual omp sections are handled together with their
8164 parent GIMPLE_OMP_SECTIONS region. */
8165 break;
8167 case GIMPLE_OMP_SINGLE:
8168 expand_omp_single (region);
8169 break;
8171 case GIMPLE_OMP_MASTER:
8172 case GIMPLE_OMP_TASKGROUP:
8173 case GIMPLE_OMP_ORDERED:
8174 case GIMPLE_OMP_CRITICAL:
8175 case GIMPLE_OMP_TEAMS:
8176 expand_omp_synch (region);
8177 break;
8179 case GIMPLE_OMP_ATOMIC_LOAD:
8180 expand_omp_atomic (region);
8181 break;
8183 case GIMPLE_OMP_TARGET:
8184 expand_omp_target (region);
8185 break;
8187 default:
8188 gcc_unreachable ();
8191 input_location = saved_location;
8192 region = region->next;
8197 /* Helper for build_omp_regions. Scan the dominator tree starting at
8198 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8199 true, the function ends once a single tree is built (otherwise, whole
8200 forest of OMP constructs may be built). */
8202 static void
8203 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8204 bool single_tree)
8206 gimple_stmt_iterator gsi;
8207 gimple stmt;
8208 basic_block son;
8210 gsi = gsi_last_bb (bb);
8211 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8213 struct omp_region *region;
8214 enum gimple_code code;
8216 stmt = gsi_stmt (gsi);
8217 code = gimple_code (stmt);
8218 if (code == GIMPLE_OMP_RETURN)
8220 /* STMT is the return point out of region PARENT. Mark it
8221 as the exit point and make PARENT the immediately
8222 enclosing region. */
8223 gcc_assert (parent);
8224 region = parent;
8225 region->exit = bb;
8226 parent = parent->outer;
8228 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8230 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8231 GIMPLE_OMP_RETURN, but matches with
8232 GIMPLE_OMP_ATOMIC_LOAD. */
8233 gcc_assert (parent);
8234 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8235 region = parent;
8236 region->exit = bb;
8237 parent = parent->outer;
8240 else if (code == GIMPLE_OMP_CONTINUE)
8242 gcc_assert (parent);
8243 parent->cont = bb;
8245 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8247 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8248 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8251 else if (code == GIMPLE_OMP_TARGET
8252 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8253 new_omp_region (bb, code, parent);
8254 else
8256 /* Otherwise, this directive becomes the parent for a new
8257 region. */
8258 region = new_omp_region (bb, code, parent);
8259 parent = region;
8263 if (single_tree && !parent)
8264 return;
8266 for (son = first_dom_son (CDI_DOMINATORS, bb);
8267 son;
8268 son = next_dom_son (CDI_DOMINATORS, son))
8269 build_omp_regions_1 (son, parent, single_tree);
8272 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8273 root_omp_region. */
8275 static void
8276 build_omp_regions_root (basic_block root)
8278 gcc_assert (root_omp_region == NULL);
8279 build_omp_regions_1 (root, NULL, true);
8280 gcc_assert (root_omp_region != NULL);
8283 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8285 void
8286 omp_expand_local (basic_block head)
8288 build_omp_regions_root (head);
8289 if (dump_file && (dump_flags & TDF_DETAILS))
8291 fprintf (dump_file, "\nOMP region tree\n\n");
8292 dump_omp_region (dump_file, root_omp_region, 0);
8293 fprintf (dump_file, "\n");
8296 remove_exit_barriers (root_omp_region);
8297 expand_omp (root_omp_region);
8299 free_omp_regions ();
8302 /* Scan the CFG and build a tree of OMP regions. Return the root of
8303 the OMP region tree. */
8305 static void
8306 build_omp_regions (void)
8308 gcc_assert (root_omp_region == NULL);
8309 calculate_dominance_info (CDI_DOMINATORS);
8310 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8313 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8315 static unsigned int
8316 execute_expand_omp (void)
8318 build_omp_regions ();
8320 if (!root_omp_region)
8321 return 0;
8323 if (dump_file)
8325 fprintf (dump_file, "\nOMP region tree\n\n");
8326 dump_omp_region (dump_file, root_omp_region, 0);
8327 fprintf (dump_file, "\n");
8330 remove_exit_barriers (root_omp_region);
8332 expand_omp (root_omp_region);
8334 cleanup_tree_cfg ();
8336 free_omp_regions ();
8338 return 0;
8341 /* OMP expansion -- the default pass, run before creation of SSA form. */
8343 namespace {
8345 const pass_data pass_data_expand_omp =
8347 GIMPLE_PASS, /* type */
8348 "ompexp", /* name */
8349 OPTGROUP_NONE, /* optinfo_flags */
8350 true, /* has_execute */
8351 TV_NONE, /* tv_id */
8352 PROP_gimple_any, /* properties_required */
8353 0, /* properties_provided */
8354 0, /* properties_destroyed */
8355 0, /* todo_flags_start */
8356 0, /* todo_flags_finish */
8359 class pass_expand_omp : public gimple_opt_pass
8361 public:
8362 pass_expand_omp (gcc::context *ctxt)
8363 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8366 /* opt_pass methods: */
8367 virtual bool gate (function *)
8369 return ((flag_openmp != 0 || flag_openmp_simd != 0
8370 || flag_cilkplus != 0) && !seen_error ());
8373 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8375 }; // class pass_expand_omp
8377 } // anon namespace
8379 gimple_opt_pass *
8380 make_pass_expand_omp (gcc::context *ctxt)
8382 return new pass_expand_omp (ctxt);
8385 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8387 /* If ctx is a worksharing context inside of a cancellable parallel
8388 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8389 and conditional branch to parallel's cancel_label to handle
8390 cancellation in the implicit barrier. */
8392 static void
8393 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8395 gimple omp_return = gimple_seq_last_stmt (*body);
8396 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8397 if (gimple_omp_return_nowait_p (omp_return))
8398 return;
8399 if (ctx->outer
8400 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8401 && ctx->outer->cancellable)
8403 tree lhs = create_tmp_var (boolean_type_node, NULL);
8404 gimple_omp_return_set_lhs (omp_return, lhs);
8405 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8406 gimple g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
8407 ctx->outer->cancel_label, fallthru_label);
8408 gimple_seq_add_stmt (body, g);
8409 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8413 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8414 CTX is the enclosing OMP context for the current statement. */
8416 static void
8417 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8419 tree block, control;
8420 gimple_stmt_iterator tgsi;
8421 gimple stmt, new_stmt, bind, t;
8422 gimple_seq ilist, dlist, olist, new_body;
8424 stmt = gsi_stmt (*gsi_p);
8426 push_gimplify_context ();
8428 dlist = NULL;
8429 ilist = NULL;
8430 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8431 &ilist, &dlist, ctx, NULL);
8433 new_body = gimple_omp_body (stmt);
8434 gimple_omp_set_body (stmt, NULL);
8435 tgsi = gsi_start (new_body);
8436 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8438 omp_context *sctx;
8439 gimple sec_start;
8441 sec_start = gsi_stmt (tgsi);
8442 sctx = maybe_lookup_ctx (sec_start);
8443 gcc_assert (sctx);
8445 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8446 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8447 GSI_CONTINUE_LINKING);
8448 gimple_omp_set_body (sec_start, NULL);
8450 if (gsi_one_before_end_p (tgsi))
8452 gimple_seq l = NULL;
8453 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8454 &l, ctx);
8455 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8456 gimple_omp_section_set_last (sec_start);
8459 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8460 GSI_CONTINUE_LINKING);
8463 block = make_node (BLOCK);
8464 bind = gimple_build_bind (NULL, new_body, block);
8466 olist = NULL;
8467 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8469 block = make_node (BLOCK);
8470 new_stmt = gimple_build_bind (NULL, NULL, block);
8471 gsi_replace (gsi_p, new_stmt, true);
8473 pop_gimplify_context (new_stmt);
8474 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8475 BLOCK_VARS (block) = gimple_bind_vars (bind);
8476 if (BLOCK_VARS (block))
8477 TREE_USED (block) = 1;
8479 new_body = NULL;
8480 gimple_seq_add_seq (&new_body, ilist);
8481 gimple_seq_add_stmt (&new_body, stmt);
8482 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8483 gimple_seq_add_stmt (&new_body, bind);
8485 control = create_tmp_var (unsigned_type_node, ".section");
8486 t = gimple_build_omp_continue (control, control);
8487 gimple_omp_sections_set_control (stmt, control);
8488 gimple_seq_add_stmt (&new_body, t);
8490 gimple_seq_add_seq (&new_body, olist);
8491 if (ctx->cancellable)
8492 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8493 gimple_seq_add_seq (&new_body, dlist);
8495 new_body = maybe_catch_exception (new_body);
8497 t = gimple_build_omp_return
8498 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8499 OMP_CLAUSE_NOWAIT));
8500 gimple_seq_add_stmt (&new_body, t);
8501 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8503 gimple_bind_set_body (new_stmt, new_body);
8507 /* A subroutine of lower_omp_single. Expand the simple form of
8508 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8510 if (GOMP_single_start ())
8511 BODY;
8512 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8514 FIXME. It may be better to delay expanding the logic of this until
8515 pass_expand_omp. The expanded logic may make the job more difficult
8516 to a synchronization analysis pass. */
8518 static void
8519 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8521 location_t loc = gimple_location (single_stmt);
8522 tree tlabel = create_artificial_label (loc);
8523 tree flabel = create_artificial_label (loc);
8524 gimple call, cond;
8525 tree lhs, decl;
8527 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8528 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8529 call = gimple_build_call (decl, 0);
8530 gimple_call_set_lhs (call, lhs);
8531 gimple_seq_add_stmt (pre_p, call);
8533 cond = gimple_build_cond (EQ_EXPR, lhs,
8534 fold_convert_loc (loc, TREE_TYPE (lhs),
8535 boolean_true_node),
8536 tlabel, flabel);
8537 gimple_seq_add_stmt (pre_p, cond);
8538 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8539 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8540 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8544 /* A subroutine of lower_omp_single. Expand the simple form of
8545 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8547 #pragma omp single copyprivate (a, b, c)
8549 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8552 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8554 BODY;
8555 copyout.a = a;
8556 copyout.b = b;
8557 copyout.c = c;
8558 GOMP_single_copy_end (&copyout);
8560 else
8562 a = copyout_p->a;
8563 b = copyout_p->b;
8564 c = copyout_p->c;
8566 GOMP_barrier ();
8569 FIXME. It may be better to delay expanding the logic of this until
8570 pass_expand_omp. The expanded logic may make the job more difficult
8571 to a synchronization analysis pass. */
8573 static void
8574 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
8576 tree ptr_type, t, l0, l1, l2, bfn_decl;
8577 gimple_seq copyin_seq;
8578 location_t loc = gimple_location (single_stmt);
8580 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8582 ptr_type = build_pointer_type (ctx->record_type);
8583 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8585 l0 = create_artificial_label (loc);
8586 l1 = create_artificial_label (loc);
8587 l2 = create_artificial_label (loc);
8589 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8590 t = build_call_expr_loc (loc, bfn_decl, 0);
8591 t = fold_convert_loc (loc, ptr_type, t);
8592 gimplify_assign (ctx->receiver_decl, t, pre_p);
8594 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8595 build_int_cst (ptr_type, 0));
8596 t = build3 (COND_EXPR, void_type_node, t,
8597 build_and_jump (&l0), build_and_jump (&l1));
8598 gimplify_and_add (t, pre_p);
8600 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8602 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8604 copyin_seq = NULL;
8605 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8606 &copyin_seq, ctx);
8608 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8609 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8610 t = build_call_expr_loc (loc, bfn_decl, 1, t);
8611 gimplify_and_add (t, pre_p);
8613 t = build_and_jump (&l2);
8614 gimplify_and_add (t, pre_p);
8616 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8618 gimple_seq_add_seq (pre_p, copyin_seq);
8620 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8624 /* Expand code for an OpenMP single directive. */
8626 static void
8627 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8629 tree block;
8630 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
8631 gimple_seq bind_body, bind_body_tail = NULL, dlist;
8633 push_gimplify_context ();
8635 block = make_node (BLOCK);
8636 bind = gimple_build_bind (NULL, NULL, block);
8637 gsi_replace (gsi_p, bind, true);
8638 bind_body = NULL;
8639 dlist = NULL;
8640 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8641 &bind_body, &dlist, ctx, NULL);
8642 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8644 gimple_seq_add_stmt (&bind_body, single_stmt);
8646 if (ctx->record_type)
8647 lower_omp_single_copy (single_stmt, &bind_body, ctx);
8648 else
8649 lower_omp_single_simple (single_stmt, &bind_body);
8651 gimple_omp_set_body (single_stmt, NULL);
8653 gimple_seq_add_seq (&bind_body, dlist);
8655 bind_body = maybe_catch_exception (bind_body);
8657 t = gimple_build_omp_return
8658 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
8659 OMP_CLAUSE_NOWAIT));
8660 gimple_seq_add_stmt (&bind_body_tail, t);
8661 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
8662 if (ctx->record_type)
8664 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8665 tree clobber = build_constructor (ctx->record_type, NULL);
8666 TREE_THIS_VOLATILE (clobber) = 1;
8667 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8668 clobber), GSI_SAME_STMT);
8670 gimple_seq_add_seq (&bind_body, bind_body_tail);
8671 gimple_bind_set_body (bind, bind_body);
8673 pop_gimplify_context (bind);
8675 gimple_bind_append_vars (bind, ctx->block_vars);
8676 BLOCK_VARS (block) = ctx->block_vars;
8677 if (BLOCK_VARS (block))
8678 TREE_USED (block) = 1;
8682 /* Expand code for an OpenMP master directive. */
8684 static void
8685 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8687 tree block, lab = NULL, x, bfn_decl;
8688 gimple stmt = gsi_stmt (*gsi_p), bind;
8689 location_t loc = gimple_location (stmt);
8690 gimple_seq tseq;
8692 push_gimplify_context ();
8694 block = make_node (BLOCK);
8695 bind = gimple_build_bind (NULL, NULL, block);
8696 gsi_replace (gsi_p, bind, true);
8697 gimple_bind_add_stmt (bind, stmt);
8699 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8700 x = build_call_expr_loc (loc, bfn_decl, 0);
8701 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
8702 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
8703 tseq = NULL;
8704 gimplify_and_add (x, &tseq);
8705 gimple_bind_add_seq (bind, tseq);
8707 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8708 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8709 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8710 gimple_omp_set_body (stmt, NULL);
8712 gimple_bind_add_stmt (bind, gimple_build_label (lab));
8714 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8716 pop_gimplify_context (bind);
8718 gimple_bind_append_vars (bind, ctx->block_vars);
8719 BLOCK_VARS (block) = ctx->block_vars;
8723 /* Expand code for an OpenMP taskgroup directive. */
8725 static void
8726 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8728 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8729 tree block = make_node (BLOCK);
8731 bind = gimple_build_bind (NULL, NULL, block);
8732 gsi_replace (gsi_p, bind, true);
8733 gimple_bind_add_stmt (bind, stmt);
8735 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
8737 gimple_bind_add_stmt (bind, x);
8739 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8740 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8741 gimple_omp_set_body (stmt, NULL);
8743 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8745 gimple_bind_append_vars (bind, ctx->block_vars);
8746 BLOCK_VARS (block) = ctx->block_vars;
8750 /* Expand code for an OpenMP ordered directive. */
8752 static void
8753 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8755 tree block;
8756 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8758 push_gimplify_context ();
8760 block = make_node (BLOCK);
8761 bind = gimple_build_bind (NULL, NULL, block);
8762 gsi_replace (gsi_p, bind, true);
8763 gimple_bind_add_stmt (bind, stmt);
8765 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
8767 gimple_bind_add_stmt (bind, x);
8769 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8770 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8771 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8772 gimple_omp_set_body (stmt, NULL);
8774 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
8775 gimple_bind_add_stmt (bind, x);
8777 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8779 pop_gimplify_context (bind);
8781 gimple_bind_append_vars (bind, ctx->block_vars);
8782 BLOCK_VARS (block) = gimple_bind_vars (bind);
8786 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
8787 substitution of a couple of function calls. But in the NAMED case,
8788 requires that languages coordinate a symbol name. It is therefore
8789 best put here in common code. */
8791 static GTY((param1_is (tree), param2_is (tree)))
8792 splay_tree critical_name_mutexes;
8794 static void
8795 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8797 tree block;
8798 tree name, lock, unlock;
8799 gimple stmt = gsi_stmt (*gsi_p), bind;
8800 location_t loc = gimple_location (stmt);
8801 gimple_seq tbody;
8803 name = gimple_omp_critical_name (stmt);
8804 if (name)
8806 tree decl;
8807 splay_tree_node n;
8809 if (!critical_name_mutexes)
8810 critical_name_mutexes
8811 = splay_tree_new_ggc (splay_tree_compare_pointers,
8812 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
8813 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
8815 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
8816 if (n == NULL)
8818 char *new_str;
8820 decl = create_tmp_var_raw (ptr_type_node, NULL);
8822 new_str = ACONCAT ((".gomp_critical_user_",
8823 IDENTIFIER_POINTER (name), NULL));
8824 DECL_NAME (decl) = get_identifier (new_str);
8825 TREE_PUBLIC (decl) = 1;
8826 TREE_STATIC (decl) = 1;
8827 DECL_COMMON (decl) = 1;
8828 DECL_ARTIFICIAL (decl) = 1;
8829 DECL_IGNORED_P (decl) = 1;
8830 varpool_finalize_decl (decl);
8832 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
8833 (splay_tree_value) decl);
8835 else
8836 decl = (tree) n->value;
8838 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
8839 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
8841 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
8842 unlock = build_call_expr_loc (loc, unlock, 1,
8843 build_fold_addr_expr_loc (loc, decl));
8845 else
8847 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
8848 lock = build_call_expr_loc (loc, lock, 0);
8850 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
8851 unlock = build_call_expr_loc (loc, unlock, 0);
8854 push_gimplify_context ();
8856 block = make_node (BLOCK);
8857 bind = gimple_build_bind (NULL, NULL, block);
8858 gsi_replace (gsi_p, bind, true);
8859 gimple_bind_add_stmt (bind, stmt);
8861 tbody = gimple_bind_body (bind);
8862 gimplify_and_add (lock, &tbody);
8863 gimple_bind_set_body (bind, tbody);
8865 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8866 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8867 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8868 gimple_omp_set_body (stmt, NULL);
8870 tbody = gimple_bind_body (bind);
8871 gimplify_and_add (unlock, &tbody);
8872 gimple_bind_set_body (bind, tbody);
8874 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8876 pop_gimplify_context (bind);
8877 gimple_bind_append_vars (bind, ctx->block_vars);
8878 BLOCK_VARS (block) = gimple_bind_vars (bind);
8882 /* A subroutine of lower_omp_for. Generate code to emit the predicate
8883 for a lastprivate clause. Given a loop control predicate of (V
8884 cond N2), we gate the clause on (!(V cond N2)). The lowered form
8885 is appended to *DLIST, iterator initialization is appended to
8886 *BODY_P. */
8888 static void
8889 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
8890 gimple_seq *dlist, struct omp_context *ctx)
8892 tree clauses, cond, vinit;
8893 enum tree_code cond_code;
8894 gimple_seq stmts;
8896 cond_code = fd->loop.cond_code;
8897 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
8899 /* When possible, use a strict equality expression. This can let VRP
8900 type optimizations deduce the value and remove a copy. */
8901 if (tree_fits_shwi_p (fd->loop.step))
8903 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
8904 if (step == 1 || step == -1)
8905 cond_code = EQ_EXPR;
8908 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
8910 clauses = gimple_omp_for_clauses (fd->for_stmt);
8911 stmts = NULL;
8912 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
8913 if (!gimple_seq_empty_p (stmts))
8915 gimple_seq_add_seq (&stmts, *dlist);
8916 *dlist = stmts;
8918 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
8919 vinit = fd->loop.n1;
8920 if (cond_code == EQ_EXPR
8921 && tree_fits_shwi_p (fd->loop.n2)
8922 && ! integer_zerop (fd->loop.n2))
8923 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
8924 else
8925 vinit = unshare_expr (vinit);
8927 /* Initialize the iterator variable, so that threads that don't execute
8928 any iterations don't execute the lastprivate clauses by accident. */
8929 gimplify_assign (fd->loop.v, vinit, body_p);
8934 /* Lower code for an OpenMP loop directive. */
8936 static void
8937 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8939 tree *rhs_p, block;
8940 struct omp_for_data fd, *fdp = NULL;
8941 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
8942 gimple_seq omp_for_body, body, dlist;
8943 size_t i;
8945 push_gimplify_context ();
8947 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
8949 block = make_node (BLOCK);
8950 new_stmt = gimple_build_bind (NULL, NULL, block);
8951 /* Replace at gsi right away, so that 'stmt' is no member
8952 of a sequence anymore as we're going to add to to a different
8953 one below. */
8954 gsi_replace (gsi_p, new_stmt, true);
8956 /* Move declaration of temporaries in the loop body before we make
8957 it go away. */
8958 omp_for_body = gimple_omp_body (stmt);
8959 if (!gimple_seq_empty_p (omp_for_body)
8960 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
8962 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
8963 tree vars = gimple_bind_vars (inner_bind);
8964 gimple_bind_append_vars (new_stmt, vars);
8965 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
8966 keep them on the inner_bind and it's block. */
8967 gimple_bind_set_vars (inner_bind, NULL_TREE);
8968 if (gimple_bind_block (inner_bind))
8969 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
8972 if (gimple_omp_for_combined_into_p (stmt))
8974 extract_omp_for_data (stmt, &fd, NULL);
8975 fdp = &fd;
8977 /* We need two temporaries with fd.loop.v type (istart/iend)
8978 and then (fd.collapse - 1) temporaries with the same
8979 type for count2 ... countN-1 vars if not constant. */
8980 size_t count = 2;
8981 tree type = fd.iter_type;
8982 if (fd.collapse > 1
8983 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
8984 count += fd.collapse - 1;
8985 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
8986 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
8987 tree clauses = *pc;
8988 if (parallel_for)
8989 outerc
8990 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
8991 OMP_CLAUSE__LOOPTEMP_);
8992 for (i = 0; i < count; i++)
8994 tree temp;
8995 if (parallel_for)
8997 gcc_assert (outerc);
8998 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
8999 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9000 OMP_CLAUSE__LOOPTEMP_);
9002 else
9003 temp = create_tmp_var (type, NULL);
9004 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9005 OMP_CLAUSE_DECL (*pc) = temp;
9006 pc = &OMP_CLAUSE_CHAIN (*pc);
9008 *pc = clauses;
9011 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9012 dlist = NULL;
9013 body = NULL;
9014 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9015 fdp);
9016 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9018 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9020 /* Lower the header expressions. At this point, we can assume that
9021 the header is of the form:
9023 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9025 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9026 using the .omp_data_s mapping, if needed. */
9027 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9029 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9030 if (!is_gimple_min_invariant (*rhs_p))
9031 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9033 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9034 if (!is_gimple_min_invariant (*rhs_p))
9035 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9037 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9038 if (!is_gimple_min_invariant (*rhs_p))
9039 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9042 /* Once lowered, extract the bounds and clauses. */
9043 extract_omp_for_data (stmt, &fd, NULL);
9045 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9047 gimple_seq_add_stmt (&body, stmt);
9048 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9050 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9051 fd.loop.v));
9053 /* After the loop, add exit clauses. */
9054 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9056 if (ctx->cancellable)
9057 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9059 gimple_seq_add_seq (&body, dlist);
9061 body = maybe_catch_exception (body);
9063 /* Region exit marker goes at the end of the loop body. */
9064 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9065 maybe_add_implicit_barrier_cancel (ctx, &body);
9066 pop_gimplify_context (new_stmt);
9068 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9069 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9070 if (BLOCK_VARS (block))
9071 TREE_USED (block) = 1;
9073 gimple_bind_set_body (new_stmt, body);
9074 gimple_omp_set_body (stmt, NULL);
9075 gimple_omp_for_set_pre_body (stmt, NULL);
9078 /* Callback for walk_stmts. Check if the current statement only contains
9079 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9081 static tree
9082 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9083 bool *handled_ops_p,
9084 struct walk_stmt_info *wi)
9086 int *info = (int *) wi->info;
9087 gimple stmt = gsi_stmt (*gsi_p);
9089 *handled_ops_p = true;
9090 switch (gimple_code (stmt))
9092 WALK_SUBSTMTS;
9094 case GIMPLE_OMP_FOR:
9095 case GIMPLE_OMP_SECTIONS:
9096 *info = *info == 0 ? 1 : -1;
9097 break;
9098 default:
9099 *info = -1;
9100 break;
9102 return NULL;
9105 struct omp_taskcopy_context
9107 /* This field must be at the beginning, as we do "inheritance": Some
9108 callback functions for tree-inline.c (e.g., omp_copy_decl)
9109 receive a copy_body_data pointer that is up-casted to an
9110 omp_context pointer. */
9111 copy_body_data cb;
9112 omp_context *ctx;
9115 static tree
9116 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9118 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9120 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9121 return create_tmp_var (TREE_TYPE (var), NULL);
9123 return var;
9126 static tree
9127 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9129 tree name, new_fields = NULL, type, f;
9131 type = lang_hooks.types.make_type (RECORD_TYPE);
9132 name = DECL_NAME (TYPE_NAME (orig_type));
9133 name = build_decl (gimple_location (tcctx->ctx->stmt),
9134 TYPE_DECL, name, type);
9135 TYPE_NAME (type) = name;
9137 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9139 tree new_f = copy_node (f);
9140 DECL_CONTEXT (new_f) = type;
9141 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9142 TREE_CHAIN (new_f) = new_fields;
9143 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9144 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9145 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9146 &tcctx->cb, NULL);
9147 new_fields = new_f;
9148 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
9150 TYPE_FIELDS (type) = nreverse (new_fields);
9151 layout_type (type);
9152 return type;
9155 /* Create task copyfn. */
9157 static void
9158 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9160 struct function *child_cfun;
9161 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9162 tree record_type, srecord_type, bind, list;
9163 bool record_needs_remap = false, srecord_needs_remap = false;
9164 splay_tree_node n;
9165 struct omp_taskcopy_context tcctx;
9166 location_t loc = gimple_location (task_stmt);
9168 child_fn = gimple_omp_task_copy_fn (task_stmt);
9169 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9170 gcc_assert (child_cfun->cfg == NULL);
9171 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9173 /* Reset DECL_CONTEXT on function arguments. */
9174 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9175 DECL_CONTEXT (t) = child_fn;
9177 /* Populate the function. */
9178 push_gimplify_context ();
9179 push_cfun (child_cfun);
9181 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9182 TREE_SIDE_EFFECTS (bind) = 1;
9183 list = NULL;
9184 DECL_SAVED_TREE (child_fn) = bind;
9185 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9187 /* Remap src and dst argument types if needed. */
9188 record_type = ctx->record_type;
9189 srecord_type = ctx->srecord_type;
9190 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9191 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9193 record_needs_remap = true;
9194 break;
9196 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9197 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9199 srecord_needs_remap = true;
9200 break;
9203 if (record_needs_remap || srecord_needs_remap)
9205 memset (&tcctx, '\0', sizeof (tcctx));
9206 tcctx.cb.src_fn = ctx->cb.src_fn;
9207 tcctx.cb.dst_fn = child_fn;
9208 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
9209 gcc_checking_assert (tcctx.cb.src_node);
9210 tcctx.cb.dst_node = tcctx.cb.src_node;
9211 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9212 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9213 tcctx.cb.eh_lp_nr = 0;
9214 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9215 tcctx.cb.decl_map = pointer_map_create ();
9216 tcctx.ctx = ctx;
9218 if (record_needs_remap)
9219 record_type = task_copyfn_remap_type (&tcctx, record_type);
9220 if (srecord_needs_remap)
9221 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9223 else
9224 tcctx.cb.decl_map = NULL;
9226 arg = DECL_ARGUMENTS (child_fn);
9227 TREE_TYPE (arg) = build_pointer_type (record_type);
9228 sarg = DECL_CHAIN (arg);
9229 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9231 /* First pass: initialize temporaries used in record_type and srecord_type
9232 sizes and field offsets. */
9233 if (tcctx.cb.decl_map)
9234 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9235 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9237 tree *p;
9239 decl = OMP_CLAUSE_DECL (c);
9240 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
9241 if (p == NULL)
9242 continue;
9243 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9244 sf = (tree) n->value;
9245 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9246 src = build_simple_mem_ref_loc (loc, sarg);
9247 src = omp_build_component_ref (src, sf);
9248 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9249 append_to_statement_list (t, &list);
9252 /* Second pass: copy shared var pointers and copy construct non-VLA
9253 firstprivate vars. */
9254 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9255 switch (OMP_CLAUSE_CODE (c))
9257 case OMP_CLAUSE_SHARED:
9258 decl = OMP_CLAUSE_DECL (c);
9259 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9260 if (n == NULL)
9261 break;
9262 f = (tree) n->value;
9263 if (tcctx.cb.decl_map)
9264 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9265 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9266 sf = (tree) n->value;
9267 if (tcctx.cb.decl_map)
9268 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9269 src = build_simple_mem_ref_loc (loc, sarg);
9270 src = omp_build_component_ref (src, sf);
9271 dst = build_simple_mem_ref_loc (loc, arg);
9272 dst = omp_build_component_ref (dst, f);
9273 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9274 append_to_statement_list (t, &list);
9275 break;
9276 case OMP_CLAUSE_FIRSTPRIVATE:
9277 decl = OMP_CLAUSE_DECL (c);
9278 if (is_variable_sized (decl))
9279 break;
9280 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9281 if (n == NULL)
9282 break;
9283 f = (tree) n->value;
9284 if (tcctx.cb.decl_map)
9285 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9286 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9287 if (n != NULL)
9289 sf = (tree) n->value;
9290 if (tcctx.cb.decl_map)
9291 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9292 src = build_simple_mem_ref_loc (loc, sarg);
9293 src = omp_build_component_ref (src, sf);
9294 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9295 src = build_simple_mem_ref_loc (loc, src);
9297 else
9298 src = decl;
9299 dst = build_simple_mem_ref_loc (loc, arg);
9300 dst = omp_build_component_ref (dst, f);
9301 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9302 append_to_statement_list (t, &list);
9303 break;
9304 case OMP_CLAUSE_PRIVATE:
9305 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9306 break;
9307 decl = OMP_CLAUSE_DECL (c);
9308 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9309 f = (tree) n->value;
9310 if (tcctx.cb.decl_map)
9311 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9312 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9313 if (n != NULL)
9315 sf = (tree) n->value;
9316 if (tcctx.cb.decl_map)
9317 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9318 src = build_simple_mem_ref_loc (loc, sarg);
9319 src = omp_build_component_ref (src, sf);
9320 if (use_pointer_for_field (decl, NULL))
9321 src = build_simple_mem_ref_loc (loc, src);
9323 else
9324 src = decl;
9325 dst = build_simple_mem_ref_loc (loc, arg);
9326 dst = omp_build_component_ref (dst, f);
9327 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9328 append_to_statement_list (t, &list);
9329 break;
9330 default:
9331 break;
9334 /* Last pass: handle VLA firstprivates. */
9335 if (tcctx.cb.decl_map)
9336 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9337 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9339 tree ind, ptr, df;
9341 decl = OMP_CLAUSE_DECL (c);
9342 if (!is_variable_sized (decl))
9343 continue;
9344 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9345 if (n == NULL)
9346 continue;
9347 f = (tree) n->value;
9348 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9349 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9350 ind = DECL_VALUE_EXPR (decl);
9351 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9352 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9353 n = splay_tree_lookup (ctx->sfield_map,
9354 (splay_tree_key) TREE_OPERAND (ind, 0));
9355 sf = (tree) n->value;
9356 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9357 src = build_simple_mem_ref_loc (loc, sarg);
9358 src = omp_build_component_ref (src, sf);
9359 src = build_simple_mem_ref_loc (loc, src);
9360 dst = build_simple_mem_ref_loc (loc, arg);
9361 dst = omp_build_component_ref (dst, f);
9362 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9363 append_to_statement_list (t, &list);
9364 n = splay_tree_lookup (ctx->field_map,
9365 (splay_tree_key) TREE_OPERAND (ind, 0));
9366 df = (tree) n->value;
9367 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
9368 ptr = build_simple_mem_ref_loc (loc, arg);
9369 ptr = omp_build_component_ref (ptr, df);
9370 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9371 build_fold_addr_expr_loc (loc, dst));
9372 append_to_statement_list (t, &list);
9375 t = build1 (RETURN_EXPR, void_type_node, NULL);
9376 append_to_statement_list (t, &list);
9378 if (tcctx.cb.decl_map)
9379 pointer_map_destroy (tcctx.cb.decl_map);
9380 pop_gimplify_context (NULL);
9381 BIND_EXPR_BODY (bind) = list;
9382 pop_cfun ();
9385 static void
9386 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9388 tree c, clauses;
9389 gimple g;
9390 size_t n_in = 0, n_out = 0, idx = 2, i;
9392 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9393 OMP_CLAUSE_DEPEND);
9394 gcc_assert (clauses);
9395 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9396 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9397 switch (OMP_CLAUSE_DEPEND_KIND (c))
9399 case OMP_CLAUSE_DEPEND_IN:
9400 n_in++;
9401 break;
9402 case OMP_CLAUSE_DEPEND_OUT:
9403 case OMP_CLAUSE_DEPEND_INOUT:
9404 n_out++;
9405 break;
9406 default:
9407 gcc_unreachable ();
9409 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9410 tree array = create_tmp_var (type, NULL);
9411 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9412 NULL_TREE);
9413 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9414 gimple_seq_add_stmt (iseq, g);
9415 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9416 NULL_TREE);
9417 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9418 gimple_seq_add_stmt (iseq, g);
9419 for (i = 0; i < 2; i++)
9421 if ((i ? n_in : n_out) == 0)
9422 continue;
9423 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9424 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9425 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9427 tree t = OMP_CLAUSE_DECL (c);
9428 t = fold_convert (ptr_type_node, t);
9429 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9430 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9431 NULL_TREE, NULL_TREE);
9432 g = gimple_build_assign (r, t);
9433 gimple_seq_add_stmt (iseq, g);
9436 tree *p = gimple_omp_task_clauses_ptr (stmt);
9437 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9438 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9439 OMP_CLAUSE_CHAIN (c) = *p;
9440 *p = c;
9441 tree clobber = build_constructor (type, NULL);
9442 TREE_THIS_VOLATILE (clobber) = 1;
9443 g = gimple_build_assign (array, clobber);
9444 gimple_seq_add_stmt (oseq, g);
9447 /* Lower the OpenMP parallel or task directive in the current statement
9448 in GSI_P. CTX holds context information for the directive. */
9450 static void
9451 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9453 tree clauses;
9454 tree child_fn, t;
9455 gimple stmt = gsi_stmt (*gsi_p);
9456 gimple par_bind, bind, dep_bind = NULL;
9457 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9458 location_t loc = gimple_location (stmt);
9460 clauses = gimple_omp_taskreg_clauses (stmt);
9461 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9462 par_body = gimple_bind_body (par_bind);
9463 child_fn = ctx->cb.dst_fn;
9464 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9465 && !gimple_omp_parallel_combined_p (stmt))
9467 struct walk_stmt_info wi;
9468 int ws_num = 0;
9470 memset (&wi, 0, sizeof (wi));
9471 wi.info = &ws_num;
9472 wi.val_only = true;
9473 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9474 if (ws_num == 1)
9475 gimple_omp_parallel_set_combined_p (stmt, true);
9477 gimple_seq dep_ilist = NULL;
9478 gimple_seq dep_olist = NULL;
9479 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9480 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9482 push_gimplify_context ();
9483 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9484 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9487 if (ctx->srecord_type)
9488 create_task_copyfn (stmt, ctx);
9490 push_gimplify_context ();
9492 par_olist = NULL;
9493 par_ilist = NULL;
9494 par_rlist = NULL;
9495 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9496 lower_omp (&par_body, ctx);
9497 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9498 lower_reduction_clauses (clauses, &par_rlist, ctx);
9500 /* Declare all the variables created by mapping and the variables
9501 declared in the scope of the parallel body. */
9502 record_vars_into (ctx->block_vars, child_fn);
9503 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9505 if (ctx->record_type)
9507 ctx->sender_decl
9508 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9509 : ctx->record_type, ".omp_data_o");
9510 DECL_NAMELESS (ctx->sender_decl) = 1;
9511 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9512 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9515 olist = NULL;
9516 ilist = NULL;
9517 lower_send_clauses (clauses, &ilist, &olist, ctx);
9518 lower_send_shared_vars (&ilist, &olist, ctx);
9520 if (ctx->record_type)
9522 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9523 TREE_THIS_VOLATILE (clobber) = 1;
9524 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9525 clobber));
9528 /* Once all the expansions are done, sequence all the different
9529 fragments inside gimple_omp_body. */
9531 new_body = NULL;
9533 if (ctx->record_type)
9535 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9536 /* fixup_child_record_type might have changed receiver_decl's type. */
9537 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9538 gimple_seq_add_stmt (&new_body,
9539 gimple_build_assign (ctx->receiver_decl, t));
9542 gimple_seq_add_seq (&new_body, par_ilist);
9543 gimple_seq_add_seq (&new_body, par_body);
9544 gimple_seq_add_seq (&new_body, par_rlist);
9545 if (ctx->cancellable)
9546 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9547 gimple_seq_add_seq (&new_body, par_olist);
9548 new_body = maybe_catch_exception (new_body);
9549 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9550 gimple_omp_set_body (stmt, new_body);
9552 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9553 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
9554 gimple_bind_add_seq (bind, ilist);
9555 gimple_bind_add_stmt (bind, stmt);
9556 gimple_bind_add_seq (bind, olist);
9558 pop_gimplify_context (NULL);
9560 if (dep_bind)
9562 gimple_bind_add_seq (dep_bind, dep_ilist);
9563 gimple_bind_add_stmt (dep_bind, bind);
9564 gimple_bind_add_seq (dep_bind, dep_olist);
9565 pop_gimplify_context (dep_bind);
9569 /* Lower the OpenMP target directive in the current statement
9570 in GSI_P. CTX holds context information for the directive. */
9572 static void
9573 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9575 tree clauses;
9576 tree child_fn, t, c;
9577 gimple stmt = gsi_stmt (*gsi_p);
9578 gimple tgt_bind = NULL, bind;
9579 gimple_seq tgt_body = NULL, olist, ilist, new_body;
9580 location_t loc = gimple_location (stmt);
9581 int kind = gimple_omp_target_kind (stmt);
9582 unsigned int map_cnt = 0;
9584 clauses = gimple_omp_target_clauses (stmt);
9585 if (kind == GF_OMP_TARGET_KIND_REGION)
9587 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9588 tgt_body = gimple_bind_body (tgt_bind);
9590 else if (kind == GF_OMP_TARGET_KIND_DATA)
9591 tgt_body = gimple_omp_body (stmt);
9592 child_fn = ctx->cb.dst_fn;
9594 push_gimplify_context ();
9596 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9597 switch (OMP_CLAUSE_CODE (c))
9599 tree var, x;
9601 default:
9602 break;
9603 case OMP_CLAUSE_MAP:
9604 case OMP_CLAUSE_TO:
9605 case OMP_CLAUSE_FROM:
9606 var = OMP_CLAUSE_DECL (c);
9607 if (!DECL_P (var))
9609 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
9610 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9611 map_cnt++;
9612 continue;
9615 if (DECL_SIZE (var)
9616 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
9618 tree var2 = DECL_VALUE_EXPR (var);
9619 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
9620 var2 = TREE_OPERAND (var2, 0);
9621 gcc_assert (DECL_P (var2));
9622 var = var2;
9625 if (!maybe_lookup_field (var, ctx))
9626 continue;
9628 if (kind == GF_OMP_TARGET_KIND_REGION)
9630 x = build_receiver_ref (var, true, ctx);
9631 tree new_var = lookup_decl (var, ctx);
9632 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9633 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9634 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9635 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
9636 x = build_simple_mem_ref (x);
9637 SET_DECL_VALUE_EXPR (new_var, x);
9638 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
9640 map_cnt++;
9643 if (kind == GF_OMP_TARGET_KIND_REGION)
9645 target_nesting_level++;
9646 lower_omp (&tgt_body, ctx);
9647 target_nesting_level--;
9649 else if (kind == GF_OMP_TARGET_KIND_DATA)
9650 lower_omp (&tgt_body, ctx);
9652 if (kind == GF_OMP_TARGET_KIND_REGION)
9654 /* Declare all the variables created by mapping and the variables
9655 declared in the scope of the target body. */
9656 record_vars_into (ctx->block_vars, child_fn);
9657 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
9660 olist = NULL;
9661 ilist = NULL;
9662 if (ctx->record_type)
9664 ctx->sender_decl
9665 = create_tmp_var (ctx->record_type, ".omp_data_arr");
9666 DECL_NAMELESS (ctx->sender_decl) = 1;
9667 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9668 t = make_tree_vec (3);
9669 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
9670 TREE_VEC_ELT (t, 1)
9671 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
9672 ".omp_data_sizes");
9673 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
9674 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
9675 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
9676 TREE_VEC_ELT (t, 2)
9677 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
9678 map_cnt),
9679 ".omp_data_kinds");
9680 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
9681 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
9682 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
9683 gimple_omp_target_set_data_arg (stmt, t);
9685 vec<constructor_elt, va_gc> *vsize;
9686 vec<constructor_elt, va_gc> *vkind;
9687 vec_alloc (vsize, map_cnt);
9688 vec_alloc (vkind, map_cnt);
9689 unsigned int map_idx = 0;
9691 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9692 switch (OMP_CLAUSE_CODE (c))
9694 tree ovar, nc;
9696 default:
9697 break;
9698 case OMP_CLAUSE_MAP:
9699 case OMP_CLAUSE_TO:
9700 case OMP_CLAUSE_FROM:
9701 nc = c;
9702 ovar = OMP_CLAUSE_DECL (c);
9703 if (!DECL_P (ovar))
9705 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9706 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9708 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
9709 == get_base_address (ovar));
9710 nc = OMP_CLAUSE_CHAIN (c);
9711 ovar = OMP_CLAUSE_DECL (nc);
9713 else
9715 tree x = build_sender_ref (ovar, ctx);
9716 tree v
9717 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
9718 gimplify_assign (x, v, &ilist);
9719 nc = NULL_TREE;
9722 else
9724 if (DECL_SIZE (ovar)
9725 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
9727 tree ovar2 = DECL_VALUE_EXPR (ovar);
9728 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
9729 ovar2 = TREE_OPERAND (ovar2, 0);
9730 gcc_assert (DECL_P (ovar2));
9731 ovar = ovar2;
9733 if (!maybe_lookup_field (ovar, ctx))
9734 continue;
9737 if (nc)
9739 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
9740 tree x = build_sender_ref (ovar, ctx);
9741 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9742 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9743 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9744 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
9746 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9747 tree avar
9748 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
9749 mark_addressable (avar);
9750 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
9751 avar = build_fold_addr_expr (avar);
9752 gimplify_assign (x, avar, &ilist);
9754 else if (is_gimple_reg (var))
9756 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9757 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
9758 mark_addressable (avar);
9759 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
9760 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
9761 gimplify_assign (avar, var, &ilist);
9762 avar = build_fold_addr_expr (avar);
9763 gimplify_assign (x, avar, &ilist);
9764 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
9765 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
9766 && !TYPE_READONLY (TREE_TYPE (var)))
9768 x = build_sender_ref (ovar, ctx);
9769 x = build_simple_mem_ref (x);
9770 gimplify_assign (var, x, &olist);
9773 else
9775 var = build_fold_addr_expr (var);
9776 gimplify_assign (x, var, &ilist);
9779 tree s = OMP_CLAUSE_SIZE (c);
9780 if (s == NULL_TREE)
9781 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
9782 s = fold_convert (size_type_node, s);
9783 tree purpose = size_int (map_idx++);
9784 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
9785 if (TREE_CODE (s) != INTEGER_CST)
9786 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
9788 unsigned char tkind = 0;
9789 switch (OMP_CLAUSE_CODE (c))
9791 case OMP_CLAUSE_MAP:
9792 tkind = OMP_CLAUSE_MAP_KIND (c);
9793 break;
9794 case OMP_CLAUSE_TO:
9795 tkind = OMP_CLAUSE_MAP_TO;
9796 break;
9797 case OMP_CLAUSE_FROM:
9798 tkind = OMP_CLAUSE_MAP_FROM;
9799 break;
9800 default:
9801 gcc_unreachable ();
9803 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
9804 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
9805 talign = DECL_ALIGN_UNIT (ovar);
9806 talign = ceil_log2 (talign);
9807 tkind |= talign << 3;
9808 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
9809 build_int_cst (unsigned_char_type_node,
9810 tkind));
9811 if (nc && nc != c)
9812 c = nc;
9815 gcc_assert (map_idx == map_cnt);
9817 DECL_INITIAL (TREE_VEC_ELT (t, 1))
9818 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
9819 DECL_INITIAL (TREE_VEC_ELT (t, 2))
9820 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
9821 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
9823 gimple_seq initlist = NULL;
9824 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
9825 TREE_VEC_ELT (t, 1)),
9826 &initlist, true, NULL_TREE);
9827 gimple_seq_add_seq (&ilist, initlist);
9829 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
9830 NULL);
9831 TREE_THIS_VOLATILE (clobber) = 1;
9832 gimple_seq_add_stmt (&olist,
9833 gimple_build_assign (TREE_VEC_ELT (t, 1),
9834 clobber));
9837 tree clobber = build_constructor (ctx->record_type, NULL);
9838 TREE_THIS_VOLATILE (clobber) = 1;
9839 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9840 clobber));
9843 /* Once all the expansions are done, sequence all the different
9844 fragments inside gimple_omp_body. */
9846 new_body = NULL;
9848 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
9850 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9851 /* fixup_child_record_type might have changed receiver_decl's type. */
9852 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9853 gimple_seq_add_stmt (&new_body,
9854 gimple_build_assign (ctx->receiver_decl, t));
9857 if (kind == GF_OMP_TARGET_KIND_REGION)
9859 gimple_seq_add_seq (&new_body, tgt_body);
9860 new_body = maybe_catch_exception (new_body);
9862 else if (kind == GF_OMP_TARGET_KIND_DATA)
9863 new_body = tgt_body;
9864 if (kind != GF_OMP_TARGET_KIND_UPDATE)
9866 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9867 gimple_omp_set_body (stmt, new_body);
9870 bind = gimple_build_bind (NULL, NULL,
9871 tgt_bind ? gimple_bind_block (tgt_bind)
9872 : NULL_TREE);
9873 gsi_replace (gsi_p, bind, true);
9874 gimple_bind_add_seq (bind, ilist);
9875 gimple_bind_add_stmt (bind, stmt);
9876 gimple_bind_add_seq (bind, olist);
9878 pop_gimplify_context (NULL);
9881 /* Expand code for an OpenMP teams directive. */
9883 static void
9884 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9886 gimple teams_stmt = gsi_stmt (*gsi_p);
9887 push_gimplify_context ();
9889 tree block = make_node (BLOCK);
9890 gimple bind = gimple_build_bind (NULL, NULL, block);
9891 gsi_replace (gsi_p, bind, true);
9892 gimple_seq bind_body = NULL;
9893 gimple_seq dlist = NULL;
9894 gimple_seq olist = NULL;
9896 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9897 OMP_CLAUSE_NUM_TEAMS);
9898 if (num_teams == NULL_TREE)
9899 num_teams = build_int_cst (unsigned_type_node, 0);
9900 else
9902 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
9903 num_teams = fold_convert (unsigned_type_node, num_teams);
9904 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
9906 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9907 OMP_CLAUSE_THREAD_LIMIT);
9908 if (thread_limit == NULL_TREE)
9909 thread_limit = build_int_cst (unsigned_type_node, 0);
9910 else
9912 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
9913 thread_limit = fold_convert (unsigned_type_node, thread_limit);
9914 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
9915 fb_rvalue);
9918 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
9919 &bind_body, &dlist, ctx, NULL);
9920 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
9921 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
9922 gimple_seq_add_stmt (&bind_body, teams_stmt);
9924 location_t loc = gimple_location (teams_stmt);
9925 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
9926 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
9927 gimple_set_location (call, loc);
9928 gimple_seq_add_stmt (&bind_body, call);
9930 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
9931 gimple_omp_set_body (teams_stmt, NULL);
9932 gimple_seq_add_seq (&bind_body, olist);
9933 gimple_seq_add_seq (&bind_body, dlist);
9934 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
9935 gimple_bind_set_body (bind, bind_body);
9937 pop_gimplify_context (bind);
9939 gimple_bind_append_vars (bind, ctx->block_vars);
9940 BLOCK_VARS (block) = ctx->block_vars;
9941 if (BLOCK_VARS (block))
9942 TREE_USED (block) = 1;
9946 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
9947 regimplified. If DATA is non-NULL, lower_omp_1 is outside
9948 of OpenMP context, but with task_shared_vars set. */
9950 static tree
9951 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
9952 void *data)
9954 tree t = *tp;
9956 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
9957 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9958 return t;
9960 if (task_shared_vars
9961 && DECL_P (t)
9962 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
9963 return t;
9965 /* If a global variable has been privatized, TREE_CONSTANT on
9966 ADDR_EXPR might be wrong. */
9967 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
9968 recompute_tree_invariant_for_addr_expr (t);
9970 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
9971 return NULL_TREE;
9974 static void
9975 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9977 gimple stmt = gsi_stmt (*gsi_p);
9978 struct walk_stmt_info wi;
9980 if (gimple_has_location (stmt))
9981 input_location = gimple_location (stmt);
9983 if (task_shared_vars)
9984 memset (&wi, '\0', sizeof (wi));
9986 /* If we have issued syntax errors, avoid doing any heavy lifting.
9987 Just replace the OpenMP directives with a NOP to avoid
9988 confusing RTL expansion. */
9989 if (seen_error () && is_gimple_omp (stmt))
9991 gsi_replace (gsi_p, gimple_build_nop (), true);
9992 return;
9995 switch (gimple_code (stmt))
9997 case GIMPLE_COND:
9998 if ((ctx || task_shared_vars)
9999 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
10000 ctx ? NULL : &wi, NULL)
10001 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
10002 ctx ? NULL : &wi, NULL)))
10003 gimple_regimplify_operands (stmt, gsi_p);
10004 break;
10005 case GIMPLE_CATCH:
10006 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
10007 break;
10008 case GIMPLE_EH_FILTER:
10009 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10010 break;
10011 case GIMPLE_TRY:
10012 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10013 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10014 break;
10015 case GIMPLE_TRANSACTION:
10016 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
10017 break;
10018 case GIMPLE_BIND:
10019 lower_omp (gimple_bind_body_ptr (stmt), ctx);
10020 break;
10021 case GIMPLE_OMP_PARALLEL:
10022 case GIMPLE_OMP_TASK:
10023 ctx = maybe_lookup_ctx (stmt);
10024 gcc_assert (ctx);
10025 if (ctx->cancellable)
10026 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10027 lower_omp_taskreg (gsi_p, ctx);
10028 break;
10029 case GIMPLE_OMP_FOR:
10030 ctx = maybe_lookup_ctx (stmt);
10031 gcc_assert (ctx);
10032 if (ctx->cancellable)
10033 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10034 lower_omp_for (gsi_p, ctx);
10035 break;
10036 case GIMPLE_OMP_SECTIONS:
10037 ctx = maybe_lookup_ctx (stmt);
10038 gcc_assert (ctx);
10039 if (ctx->cancellable)
10040 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10041 lower_omp_sections (gsi_p, ctx);
10042 break;
10043 case GIMPLE_OMP_SINGLE:
10044 ctx = maybe_lookup_ctx (stmt);
10045 gcc_assert (ctx);
10046 lower_omp_single (gsi_p, ctx);
10047 break;
10048 case GIMPLE_OMP_MASTER:
10049 ctx = maybe_lookup_ctx (stmt);
10050 gcc_assert (ctx);
10051 lower_omp_master (gsi_p, ctx);
10052 break;
10053 case GIMPLE_OMP_TASKGROUP:
10054 ctx = maybe_lookup_ctx (stmt);
10055 gcc_assert (ctx);
10056 lower_omp_taskgroup (gsi_p, ctx);
10057 break;
10058 case GIMPLE_OMP_ORDERED:
10059 ctx = maybe_lookup_ctx (stmt);
10060 gcc_assert (ctx);
10061 lower_omp_ordered (gsi_p, ctx);
10062 break;
10063 case GIMPLE_OMP_CRITICAL:
10064 ctx = maybe_lookup_ctx (stmt);
10065 gcc_assert (ctx);
10066 lower_omp_critical (gsi_p, ctx);
10067 break;
10068 case GIMPLE_OMP_ATOMIC_LOAD:
10069 if ((ctx || task_shared_vars)
10070 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
10071 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10072 gimple_regimplify_operands (stmt, gsi_p);
10073 break;
10074 case GIMPLE_OMP_TARGET:
10075 ctx = maybe_lookup_ctx (stmt);
10076 gcc_assert (ctx);
10077 lower_omp_target (gsi_p, ctx);
10078 break;
10079 case GIMPLE_OMP_TEAMS:
10080 ctx = maybe_lookup_ctx (stmt);
10081 gcc_assert (ctx);
10082 lower_omp_teams (gsi_p, ctx);
10083 break;
10084 case GIMPLE_CALL:
10085 tree fndecl;
10086 fndecl = gimple_call_fndecl (stmt);
10087 if (fndecl
10088 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10089 switch (DECL_FUNCTION_CODE (fndecl))
10091 case BUILT_IN_GOMP_BARRIER:
10092 if (ctx == NULL)
10093 break;
10094 /* FALLTHRU */
10095 case BUILT_IN_GOMP_CANCEL:
10096 case BUILT_IN_GOMP_CANCELLATION_POINT:
10097 omp_context *cctx;
10098 cctx = ctx;
10099 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10100 cctx = cctx->outer;
10101 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10102 if (!cctx->cancellable)
10104 if (DECL_FUNCTION_CODE (fndecl)
10105 == BUILT_IN_GOMP_CANCELLATION_POINT)
10107 stmt = gimple_build_nop ();
10108 gsi_replace (gsi_p, stmt, false);
10110 break;
10112 tree lhs;
10113 lhs = create_tmp_var (boolean_type_node, NULL);
10114 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10116 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10117 gimple_call_set_fndecl (stmt, fndecl);
10118 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10120 gimple_call_set_lhs (stmt, lhs);
10121 tree fallthru_label;
10122 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10123 gimple g;
10124 g = gimple_build_label (fallthru_label);
10125 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10126 g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
10127 cctx->cancel_label, fallthru_label);
10128 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10129 break;
10130 default:
10131 break;
10133 /* FALLTHRU */
10134 default:
10135 if ((ctx || task_shared_vars)
10136 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10137 ctx ? NULL : &wi))
10139 /* Just remove clobbers, this should happen only if we have
10140 "privatized" local addressable variables in SIMD regions,
10141 the clobber isn't needed in that case and gimplifying address
10142 of the ARRAY_REF into a pointer and creating MEM_REF based
10143 clobber would create worse code than we get with the clobber
10144 dropped. */
10145 if (gimple_clobber_p (stmt))
10147 gsi_replace (gsi_p, gimple_build_nop (), true);
10148 break;
10150 gimple_regimplify_operands (stmt, gsi_p);
10152 break;
10156 static void
10157 lower_omp (gimple_seq *body, omp_context *ctx)
10159 location_t saved_location = input_location;
10160 gimple_stmt_iterator gsi;
10161 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10162 lower_omp_1 (&gsi, ctx);
10163 /* During gimplification, we have not always invoked fold_stmt
10164 (gimplify.c:maybe_fold_stmt); call it now. */
10165 if (target_nesting_level)
10166 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10167 fold_stmt (&gsi);
10168 input_location = saved_location;
10171 /* Main entry point. */
10173 static unsigned int
10174 execute_lower_omp (void)
10176 gimple_seq body;
10178 /* This pass always runs, to provide PROP_gimple_lomp.
10179 But there is nothing to do unless -fopenmp is given. */
10180 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10181 return 0;
10183 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10184 delete_omp_context);
10186 body = gimple_body (current_function_decl);
10187 scan_omp (&body, NULL);
10188 gcc_assert (taskreg_nesting_level == 0);
10190 if (all_contexts->root)
10192 if (task_shared_vars)
10193 push_gimplify_context ();
10194 lower_omp (&body, NULL);
10195 if (task_shared_vars)
10196 pop_gimplify_context (NULL);
10199 if (all_contexts)
10201 splay_tree_delete (all_contexts);
10202 all_contexts = NULL;
10204 BITMAP_FREE (task_shared_vars);
10205 return 0;
10208 namespace {
10210 const pass_data pass_data_lower_omp =
10212 GIMPLE_PASS, /* type */
10213 "omplower", /* name */
10214 OPTGROUP_NONE, /* optinfo_flags */
10215 true, /* has_execute */
10216 TV_NONE, /* tv_id */
10217 PROP_gimple_any, /* properties_required */
10218 PROP_gimple_lomp, /* properties_provided */
10219 0, /* properties_destroyed */
10220 0, /* todo_flags_start */
10221 0, /* todo_flags_finish */
10224 class pass_lower_omp : public gimple_opt_pass
10226 public:
10227 pass_lower_omp (gcc::context *ctxt)
10228 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10231 /* opt_pass methods: */
10232 virtual unsigned int execute (function *) { return execute_lower_omp (); }
10234 }; // class pass_lower_omp
10236 } // anon namespace
10238 gimple_opt_pass *
10239 make_pass_lower_omp (gcc::context *ctxt)
10241 return new pass_lower_omp (ctxt);
10244 /* The following is a utility to diagnose OpenMP structured block violations.
10245 It is not part of the "omplower" pass, as that's invoked too late. It
10246 should be invoked by the respective front ends after gimplification. */
10248 static splay_tree all_labels;
10250 /* Check for mismatched contexts and generate an error if needed. Return
10251 true if an error is detected. */
10253 static bool
10254 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10255 gimple branch_ctx, gimple label_ctx)
10257 if (label_ctx == branch_ctx)
10258 return false;
10262 Previously we kept track of the label's entire context in diagnose_sb_[12]
10263 so we could traverse it and issue a correct "exit" or "enter" error
10264 message upon a structured block violation.
10266 We built the context by building a list with tree_cons'ing, but there is
10267 no easy counterpart in gimple tuples. It seems like far too much work
10268 for issuing exit/enter error messages. If someone really misses the
10269 distinct error message... patches welcome.
10272 #if 0
10273 /* Try to avoid confusing the user by producing and error message
10274 with correct "exit" or "enter" verbiage. We prefer "exit"
10275 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10276 if (branch_ctx == NULL)
10277 exit_p = false;
10278 else
10280 while (label_ctx)
10282 if (TREE_VALUE (label_ctx) == branch_ctx)
10284 exit_p = false;
10285 break;
10287 label_ctx = TREE_CHAIN (label_ctx);
10291 if (exit_p)
10292 error ("invalid exit from OpenMP structured block");
10293 else
10294 error ("invalid entry to OpenMP structured block");
10295 #endif
10297 bool cilkplus_block = false;
10298 if (flag_cilkplus)
10300 if ((branch_ctx
10301 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10302 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10303 || (label_ctx
10304 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10305 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10306 cilkplus_block = true;
10309 /* If it's obvious we have an invalid entry, be specific about the error. */
10310 if (branch_ctx == NULL)
10312 if (cilkplus_block)
10313 error ("invalid entry to Cilk Plus structured block");
10314 else
10315 error ("invalid entry to OpenMP structured block");
10317 else
10319 /* Otherwise, be vague and lazy, but efficient. */
10320 if (cilkplus_block)
10321 error ("invalid branch to/from a Cilk Plus structured block");
10322 else
10323 error ("invalid branch to/from an OpenMP structured block");
10326 gsi_replace (gsi_p, gimple_build_nop (), false);
10327 return true;
10330 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10331 where each label is found. */
10333 static tree
10334 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10335 struct walk_stmt_info *wi)
10337 gimple context = (gimple) wi->info;
10338 gimple inner_context;
10339 gimple stmt = gsi_stmt (*gsi_p);
10341 *handled_ops_p = true;
10343 switch (gimple_code (stmt))
10345 WALK_SUBSTMTS;
10347 case GIMPLE_OMP_PARALLEL:
10348 case GIMPLE_OMP_TASK:
10349 case GIMPLE_OMP_SECTIONS:
10350 case GIMPLE_OMP_SINGLE:
10351 case GIMPLE_OMP_SECTION:
10352 case GIMPLE_OMP_MASTER:
10353 case GIMPLE_OMP_ORDERED:
10354 case GIMPLE_OMP_CRITICAL:
10355 case GIMPLE_OMP_TARGET:
10356 case GIMPLE_OMP_TEAMS:
10357 case GIMPLE_OMP_TASKGROUP:
10358 /* The minimal context here is just the current OMP construct. */
10359 inner_context = stmt;
10360 wi->info = inner_context;
10361 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10362 wi->info = context;
10363 break;
10365 case GIMPLE_OMP_FOR:
10366 inner_context = stmt;
10367 wi->info = inner_context;
10368 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10369 walk them. */
10370 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10371 diagnose_sb_1, NULL, wi);
10372 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10373 wi->info = context;
10374 break;
10376 case GIMPLE_LABEL:
10377 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10378 (splay_tree_value) context);
10379 break;
10381 default:
10382 break;
10385 return NULL_TREE;
10388 /* Pass 2: Check each branch and see if its context differs from that of
10389 the destination label's context. */
10391 static tree
10392 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10393 struct walk_stmt_info *wi)
10395 gimple context = (gimple) wi->info;
10396 splay_tree_node n;
10397 gimple stmt = gsi_stmt (*gsi_p);
10399 *handled_ops_p = true;
10401 switch (gimple_code (stmt))
10403 WALK_SUBSTMTS;
10405 case GIMPLE_OMP_PARALLEL:
10406 case GIMPLE_OMP_TASK:
10407 case GIMPLE_OMP_SECTIONS:
10408 case GIMPLE_OMP_SINGLE:
10409 case GIMPLE_OMP_SECTION:
10410 case GIMPLE_OMP_MASTER:
10411 case GIMPLE_OMP_ORDERED:
10412 case GIMPLE_OMP_CRITICAL:
10413 case GIMPLE_OMP_TARGET:
10414 case GIMPLE_OMP_TEAMS:
10415 case GIMPLE_OMP_TASKGROUP:
10416 wi->info = stmt;
10417 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10418 wi->info = context;
10419 break;
10421 case GIMPLE_OMP_FOR:
10422 wi->info = stmt;
10423 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10424 walk them. */
10425 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10426 diagnose_sb_2, NULL, wi);
10427 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10428 wi->info = context;
10429 break;
10431 case GIMPLE_COND:
10433 tree lab = gimple_cond_true_label (stmt);
10434 if (lab)
10436 n = splay_tree_lookup (all_labels,
10437 (splay_tree_key) lab);
10438 diagnose_sb_0 (gsi_p, context,
10439 n ? (gimple) n->value : NULL);
10441 lab = gimple_cond_false_label (stmt);
10442 if (lab)
10444 n = splay_tree_lookup (all_labels,
10445 (splay_tree_key) lab);
10446 diagnose_sb_0 (gsi_p, context,
10447 n ? (gimple) n->value : NULL);
10450 break;
10452 case GIMPLE_GOTO:
10454 tree lab = gimple_goto_dest (stmt);
10455 if (TREE_CODE (lab) != LABEL_DECL)
10456 break;
10458 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10459 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10461 break;
10463 case GIMPLE_SWITCH:
10465 unsigned int i;
10466 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10468 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10469 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10470 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10471 break;
10474 break;
10476 case GIMPLE_RETURN:
10477 diagnose_sb_0 (gsi_p, context, NULL);
10478 break;
10480 default:
10481 break;
10484 return NULL_TREE;
10487 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10488 codes. */
10489 bool
10490 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
10491 int *region_idx)
10493 gimple last = last_stmt (bb);
10494 enum gimple_code code = gimple_code (last);
10495 struct omp_region *cur_region = *region;
10496 bool fallthru = false;
10498 switch (code)
10500 case GIMPLE_OMP_PARALLEL:
10501 case GIMPLE_OMP_TASK:
10502 case GIMPLE_OMP_FOR:
10503 case GIMPLE_OMP_SINGLE:
10504 case GIMPLE_OMP_TEAMS:
10505 case GIMPLE_OMP_MASTER:
10506 case GIMPLE_OMP_TASKGROUP:
10507 case GIMPLE_OMP_ORDERED:
10508 case GIMPLE_OMP_CRITICAL:
10509 case GIMPLE_OMP_SECTION:
10510 cur_region = new_omp_region (bb, code, cur_region);
10511 fallthru = true;
10512 break;
10514 case GIMPLE_OMP_TARGET:
10515 cur_region = new_omp_region (bb, code, cur_region);
10516 fallthru = true;
10517 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10518 cur_region = cur_region->outer;
10519 break;
10521 case GIMPLE_OMP_SECTIONS:
10522 cur_region = new_omp_region (bb, code, cur_region);
10523 fallthru = true;
10524 break;
10526 case GIMPLE_OMP_SECTIONS_SWITCH:
10527 fallthru = false;
10528 break;
10530 case GIMPLE_OMP_ATOMIC_LOAD:
10531 case GIMPLE_OMP_ATOMIC_STORE:
10532 fallthru = true;
10533 break;
10535 case GIMPLE_OMP_RETURN:
10536 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10537 somewhere other than the next block. This will be
10538 created later. */
10539 cur_region->exit = bb;
10540 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
10541 cur_region = cur_region->outer;
10542 break;
10544 case GIMPLE_OMP_CONTINUE:
10545 cur_region->cont = bb;
10546 switch (cur_region->type)
10548 case GIMPLE_OMP_FOR:
10549 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
10550 succs edges as abnormal to prevent splitting
10551 them. */
10552 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
10553 /* Make the loopback edge. */
10554 make_edge (bb, single_succ (cur_region->entry),
10555 EDGE_ABNORMAL);
10557 /* Create an edge from GIMPLE_OMP_FOR to exit, which
10558 corresponds to the case that the body of the loop
10559 is not executed at all. */
10560 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
10561 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
10562 fallthru = false;
10563 break;
10565 case GIMPLE_OMP_SECTIONS:
10566 /* Wire up the edges into and out of the nested sections. */
10568 basic_block switch_bb = single_succ (cur_region->entry);
10570 struct omp_region *i;
10571 for (i = cur_region->inner; i ; i = i->next)
10573 gcc_assert (i->type == GIMPLE_OMP_SECTION);
10574 make_edge (switch_bb, i->entry, 0);
10575 make_edge (i->exit, bb, EDGE_FALLTHRU);
10578 /* Make the loopback edge to the block with
10579 GIMPLE_OMP_SECTIONS_SWITCH. */
10580 make_edge (bb, switch_bb, 0);
10582 /* Make the edge from the switch to exit. */
10583 make_edge (switch_bb, bb->next_bb, 0);
10584 fallthru = false;
10586 break;
10588 default:
10589 gcc_unreachable ();
10591 break;
10593 default:
10594 gcc_unreachable ();
10597 if (*region != cur_region)
10599 *region = cur_region;
10600 if (cur_region)
10601 *region_idx = cur_region->entry->index;
10602 else
10603 *region_idx = 0;
10606 return fallthru;
10609 static unsigned int
10610 diagnose_omp_structured_block_errors (void)
10612 struct walk_stmt_info wi;
10613 gimple_seq body = gimple_body (current_function_decl);
10615 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
10617 memset (&wi, 0, sizeof (wi));
10618 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
10620 memset (&wi, 0, sizeof (wi));
10621 wi.want_locations = true;
10622 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
10624 gimple_set_body (current_function_decl, body);
10626 splay_tree_delete (all_labels);
10627 all_labels = NULL;
10629 return 0;
10632 namespace {
10634 const pass_data pass_data_diagnose_omp_blocks =
10636 GIMPLE_PASS, /* type */
10637 "*diagnose_omp_blocks", /* name */
10638 OPTGROUP_NONE, /* optinfo_flags */
10639 true, /* has_execute */
10640 TV_NONE, /* tv_id */
10641 PROP_gimple_any, /* properties_required */
10642 0, /* properties_provided */
10643 0, /* properties_destroyed */
10644 0, /* todo_flags_start */
10645 0, /* todo_flags_finish */
10648 class pass_diagnose_omp_blocks : public gimple_opt_pass
10650 public:
10651 pass_diagnose_omp_blocks (gcc::context *ctxt)
10652 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
10655 /* opt_pass methods: */
10656 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
10657 virtual unsigned int execute (function *)
10659 return diagnose_omp_structured_block_errors ();
10662 }; // class pass_diagnose_omp_blocks
10664 } // anon namespace
10666 gimple_opt_pass *
10667 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
10669 return new pass_diagnose_omp_blocks (ctxt);
10672 /* SIMD clone supporting code. */
10674 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
10675 of arguments to reserve space for. */
10677 static struct cgraph_simd_clone *
10678 simd_clone_struct_alloc (int nargs)
10680 struct cgraph_simd_clone *clone_info;
10681 size_t len = (sizeof (struct cgraph_simd_clone)
10682 + nargs * sizeof (struct cgraph_simd_clone_arg));
10683 clone_info = (struct cgraph_simd_clone *)
10684 ggc_internal_cleared_alloc (len);
10685 return clone_info;
10688 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
10690 static inline void
10691 simd_clone_struct_copy (struct cgraph_simd_clone *to,
10692 struct cgraph_simd_clone *from)
10694 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
10695 + ((from->nargs - from->inbranch)
10696 * sizeof (struct cgraph_simd_clone_arg))));
10699 /* Return vector of parameter types of function FNDECL. This uses
10700 TYPE_ARG_TYPES if available, otherwise falls back to types of
10701 DECL_ARGUMENTS types. */
10703 vec<tree>
10704 simd_clone_vector_of_formal_parm_types (tree fndecl)
10706 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
10707 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
10708 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
10709 unsigned int i;
10710 tree arg;
10711 FOR_EACH_VEC_ELT (args, i, arg)
10712 args[i] = TREE_TYPE (args[i]);
10713 return args;
10716 /* Given a simd function in NODE, extract the simd specific
10717 information from the OMP clauses passed in CLAUSES, and return
10718 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
10719 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
10720 otherwise set to FALSE. */
10722 static struct cgraph_simd_clone *
10723 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
10724 bool *inbranch_specified)
10726 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
10727 tree t;
10728 int n;
10729 *inbranch_specified = false;
10731 n = args.length ();
10732 if (n > 0 && args.last () == void_type_node)
10733 n--;
10735 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
10736 be cloned have a distinctive artificial label in addition to "omp
10737 declare simd". */
10738 bool cilk_clone
10739 = (flag_cilkplus
10740 && lookup_attribute ("cilk simd function",
10741 DECL_ATTRIBUTES (node->decl)));
10743 /* Allocate one more than needed just in case this is an in-branch
10744 clone which will require a mask argument. */
10745 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
10746 clone_info->nargs = n;
10747 clone_info->cilk_elemental = cilk_clone;
10749 if (!clauses)
10751 args.release ();
10752 return clone_info;
10754 clauses = TREE_VALUE (clauses);
10755 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
10756 return clone_info;
10758 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
10760 switch (OMP_CLAUSE_CODE (t))
10762 case OMP_CLAUSE_INBRANCH:
10763 clone_info->inbranch = 1;
10764 *inbranch_specified = true;
10765 break;
10766 case OMP_CLAUSE_NOTINBRANCH:
10767 clone_info->inbranch = 0;
10768 *inbranch_specified = true;
10769 break;
10770 case OMP_CLAUSE_SIMDLEN:
10771 clone_info->simdlen
10772 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
10773 break;
10774 case OMP_CLAUSE_LINEAR:
10776 tree decl = OMP_CLAUSE_DECL (t);
10777 tree step = OMP_CLAUSE_LINEAR_STEP (t);
10778 int argno = TREE_INT_CST_LOW (decl);
10779 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
10781 clone_info->args[argno].arg_type
10782 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
10783 clone_info->args[argno].linear_step = tree_to_shwi (step);
10784 gcc_assert (clone_info->args[argno].linear_step >= 0
10785 && clone_info->args[argno].linear_step < n);
10787 else
10789 if (POINTER_TYPE_P (args[argno]))
10790 step = fold_convert (ssizetype, step);
10791 if (!tree_fits_shwi_p (step))
10793 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10794 "ignoring large linear step");
10795 args.release ();
10796 return NULL;
10798 else if (integer_zerop (step))
10800 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10801 "ignoring zero linear step");
10802 args.release ();
10803 return NULL;
10805 else
10807 clone_info->args[argno].arg_type
10808 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
10809 clone_info->args[argno].linear_step = tree_to_shwi (step);
10812 break;
10814 case OMP_CLAUSE_UNIFORM:
10816 tree decl = OMP_CLAUSE_DECL (t);
10817 int argno = tree_to_uhwi (decl);
10818 clone_info->args[argno].arg_type
10819 = SIMD_CLONE_ARG_TYPE_UNIFORM;
10820 break;
10822 case OMP_CLAUSE_ALIGNED:
10824 tree decl = OMP_CLAUSE_DECL (t);
10825 int argno = tree_to_uhwi (decl);
10826 clone_info->args[argno].alignment
10827 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
10828 break;
10830 default:
10831 break;
10834 args.release ();
10835 return clone_info;
10838 /* Given a SIMD clone in NODE, calculate the characteristic data
10839 type and return the coresponding type. The characteristic data
10840 type is computed as described in the Intel Vector ABI. */
10842 static tree
10843 simd_clone_compute_base_data_type (struct cgraph_node *node,
10844 struct cgraph_simd_clone *clone_info)
10846 tree type = integer_type_node;
10847 tree fndecl = node->decl;
10849 /* a) For non-void function, the characteristic data type is the
10850 return type. */
10851 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
10852 type = TREE_TYPE (TREE_TYPE (fndecl));
10854 /* b) If the function has any non-uniform, non-linear parameters,
10855 then the characteristic data type is the type of the first
10856 such parameter. */
10857 else
10859 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
10860 for (unsigned int i = 0; i < clone_info->nargs; ++i)
10861 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
10863 type = map[i];
10864 break;
10866 map.release ();
10869 /* c) If the characteristic data type determined by a) or b) above
10870 is struct, union, or class type which is pass-by-value (except
10871 for the type that maps to the built-in complex data type), the
10872 characteristic data type is int. */
10873 if (RECORD_OR_UNION_TYPE_P (type)
10874 && !aggregate_value_p (type, NULL)
10875 && TREE_CODE (type) != COMPLEX_TYPE)
10876 return integer_type_node;
10878 /* d) If none of the above three classes is applicable, the
10879 characteristic data type is int. */
10881 return type;
10883 /* e) For Intel Xeon Phi native and offload compilation, if the
10884 resulting characteristic data type is 8-bit or 16-bit integer
10885 data type, the characteristic data type is int. */
10886 /* Well, we don't handle Xeon Phi yet. */
10889 static tree
10890 simd_clone_mangle (struct cgraph_node *node,
10891 struct cgraph_simd_clone *clone_info)
10893 char vecsize_mangle = clone_info->vecsize_mangle;
10894 char mask = clone_info->inbranch ? 'M' : 'N';
10895 unsigned int simdlen = clone_info->simdlen;
10896 unsigned int n;
10897 pretty_printer pp;
10899 gcc_assert (vecsize_mangle && simdlen);
10901 pp_string (&pp, "_ZGV");
10902 pp_character (&pp, vecsize_mangle);
10903 pp_character (&pp, mask);
10904 pp_decimal_int (&pp, simdlen);
10906 for (n = 0; n < clone_info->nargs; ++n)
10908 struct cgraph_simd_clone_arg arg = clone_info->args[n];
10910 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
10911 pp_character (&pp, 'u');
10912 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
10914 gcc_assert (arg.linear_step != 0);
10915 pp_character (&pp, 'l');
10916 if (arg.linear_step > 1)
10917 pp_unsigned_wide_integer (&pp, arg.linear_step);
10918 else if (arg.linear_step < 0)
10920 pp_character (&pp, 'n');
10921 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
10922 arg.linear_step));
10925 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
10927 pp_character (&pp, 's');
10928 pp_unsigned_wide_integer (&pp, arg.linear_step);
10930 else
10931 pp_character (&pp, 'v');
10932 if (arg.alignment)
10934 pp_character (&pp, 'a');
10935 pp_decimal_int (&pp, arg.alignment);
10939 pp_underscore (&pp);
10940 pp_string (&pp,
10941 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
10942 const char *str = pp_formatted_text (&pp);
10944 /* If there already is a SIMD clone with the same mangled name, don't
10945 add another one. This can happen e.g. for
10946 #pragma omp declare simd
10947 #pragma omp declare simd simdlen(8)
10948 int foo (int, int);
10949 if the simdlen is assumed to be 8 for the first one, etc. */
10950 for (struct cgraph_node *clone = node->simd_clones; clone;
10951 clone = clone->simdclone->next_clone)
10952 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
10953 str) == 0)
10954 return NULL_TREE;
10956 return get_identifier (str);
10959 /* Create a simd clone of OLD_NODE and return it. */
10961 static struct cgraph_node *
10962 simd_clone_create (struct cgraph_node *old_node)
10964 struct cgraph_node *new_node;
10965 if (old_node->definition)
10967 if (!cgraph_function_with_gimple_body_p (old_node))
10968 return NULL;
10969 cgraph_get_body (old_node);
10970 new_node = cgraph_function_versioning (old_node, vNULL, NULL, NULL,
10971 false, NULL, NULL, "simdclone");
10973 else
10975 tree old_decl = old_node->decl;
10976 tree new_decl = copy_node (old_node->decl);
10977 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
10978 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
10979 SET_DECL_RTL (new_decl, NULL);
10980 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
10981 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
10982 new_node
10983 = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL);
10984 cgraph_call_function_insertion_hooks (new_node);
10986 if (new_node == NULL)
10987 return new_node;
10989 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
10991 /* The function cgraph_function_versioning () will force the new
10992 symbol local. Undo this, and inherit external visability from
10993 the old node. */
10994 new_node->local.local = old_node->local.local;
10995 new_node->externally_visible = old_node->externally_visible;
10997 return new_node;
11000 /* Adjust the return type of the given function to its appropriate
11001 vector counterpart. Returns a simd array to be used throughout the
11002 function as a return value. */
11004 static tree
11005 simd_clone_adjust_return_type (struct cgraph_node *node)
11007 tree fndecl = node->decl;
11008 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11009 unsigned int veclen;
11010 tree t;
11012 /* Adjust the function return type. */
11013 if (orig_rettype == void_type_node)
11014 return NULL_TREE;
11015 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11016 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11017 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11018 veclen = node->simdclone->vecsize_int;
11019 else
11020 veclen = node->simdclone->vecsize_float;
11021 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11022 if (veclen > node->simdclone->simdlen)
11023 veclen = node->simdclone->simdlen;
11024 if (veclen == node->simdclone->simdlen)
11025 TREE_TYPE (TREE_TYPE (fndecl))
11026 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11027 node->simdclone->simdlen);
11028 else
11030 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11031 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11032 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11034 if (!node->definition)
11035 return NULL_TREE;
11037 t = DECL_RESULT (fndecl);
11038 /* Adjust the DECL_RESULT. */
11039 gcc_assert (TREE_TYPE (t) != void_type_node);
11040 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11041 relayout_decl (t);
11043 tree atype = build_array_type_nelts (orig_rettype,
11044 node->simdclone->simdlen);
11045 if (veclen != node->simdclone->simdlen)
11046 return build1 (VIEW_CONVERT_EXPR, atype, t);
11048 /* Set up a SIMD array to use as the return value. */
11049 tree retval = create_tmp_var_raw (atype, "retval");
11050 gimple_add_tmp_var (retval);
11051 return retval;
11054 /* Each vector argument has a corresponding array to be used locally
11055 as part of the eventual loop. Create such temporary array and
11056 return it.
11058 PREFIX is the prefix to be used for the temporary.
11060 TYPE is the inner element type.
11062 SIMDLEN is the number of elements. */
11064 static tree
11065 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11067 tree atype = build_array_type_nelts (type, simdlen);
11068 tree avar = create_tmp_var_raw (atype, prefix);
11069 gimple_add_tmp_var (avar);
11070 return avar;
11073 /* Modify the function argument types to their corresponding vector
11074 counterparts if appropriate. Also, create one array for each simd
11075 argument to be used locally when using the function arguments as
11076 part of the loop.
11078 NODE is the function whose arguments are to be adjusted.
11080 Returns an adjustment vector that will be filled describing how the
11081 argument types will be adjusted. */
11083 static ipa_parm_adjustment_vec
11084 simd_clone_adjust_argument_types (struct cgraph_node *node)
11086 vec<tree> args;
11087 ipa_parm_adjustment_vec adjustments;
11089 if (node->definition)
11090 args = ipa_get_vector_of_formal_parms (node->decl);
11091 else
11092 args = simd_clone_vector_of_formal_parm_types (node->decl);
11093 adjustments.create (args.length ());
11094 unsigned i, j, veclen;
11095 struct ipa_parm_adjustment adj;
11096 for (i = 0; i < node->simdclone->nargs; ++i)
11098 memset (&adj, 0, sizeof (adj));
11099 tree parm = args[i];
11100 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11101 adj.base_index = i;
11102 adj.base = parm;
11104 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11105 node->simdclone->args[i].orig_type = parm_type;
11107 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11109 /* No adjustment necessary for scalar arguments. */
11110 adj.op = IPA_PARM_OP_COPY;
11112 else
11114 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11115 veclen = node->simdclone->vecsize_int;
11116 else
11117 veclen = node->simdclone->vecsize_float;
11118 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11119 if (veclen > node->simdclone->simdlen)
11120 veclen = node->simdclone->simdlen;
11121 adj.arg_prefix = "simd";
11122 adj.type = build_vector_type (parm_type, veclen);
11123 node->simdclone->args[i].vector_type = adj.type;
11124 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11126 adjustments.safe_push (adj);
11127 if (j == veclen)
11129 memset (&adj, 0, sizeof (adj));
11130 adj.op = IPA_PARM_OP_NEW;
11131 adj.arg_prefix = "simd";
11132 adj.base_index = i;
11133 adj.type = node->simdclone->args[i].vector_type;
11137 if (node->definition)
11138 node->simdclone->args[i].simd_array
11139 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11140 parm_type, node->simdclone->simdlen);
11142 adjustments.safe_push (adj);
11145 if (node->simdclone->inbranch)
11147 tree base_type
11148 = simd_clone_compute_base_data_type (node->simdclone->origin,
11149 node->simdclone);
11151 memset (&adj, 0, sizeof (adj));
11152 adj.op = IPA_PARM_OP_NEW;
11153 adj.arg_prefix = "mask";
11155 adj.base_index = i;
11156 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11157 veclen = node->simdclone->vecsize_int;
11158 else
11159 veclen = node->simdclone->vecsize_float;
11160 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11161 if (veclen > node->simdclone->simdlen)
11162 veclen = node->simdclone->simdlen;
11163 adj.type = build_vector_type (base_type, veclen);
11164 adjustments.safe_push (adj);
11166 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11167 adjustments.safe_push (adj);
11169 /* We have previously allocated one extra entry for the mask. Use
11170 it and fill it. */
11171 struct cgraph_simd_clone *sc = node->simdclone;
11172 sc->nargs++;
11173 if (node->definition)
11175 sc->args[i].orig_arg
11176 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11177 sc->args[i].simd_array
11178 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11180 sc->args[i].orig_type = base_type;
11181 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11184 if (node->definition)
11185 ipa_modify_formal_parameters (node->decl, adjustments);
11186 else
11188 tree new_arg_types = NULL_TREE, new_reversed;
11189 bool last_parm_void = false;
11190 if (args.length () > 0 && args.last () == void_type_node)
11191 last_parm_void = true;
11193 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11194 j = adjustments.length ();
11195 for (i = 0; i < j; i++)
11197 struct ipa_parm_adjustment *adj = &adjustments[i];
11198 tree ptype;
11199 if (adj->op == IPA_PARM_OP_COPY)
11200 ptype = args[adj->base_index];
11201 else
11202 ptype = adj->type;
11203 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11205 new_reversed = nreverse (new_arg_types);
11206 if (last_parm_void)
11208 if (new_reversed)
11209 TREE_CHAIN (new_arg_types) = void_list_node;
11210 else
11211 new_reversed = void_list_node;
11214 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11215 TYPE_ARG_TYPES (new_type) = new_reversed;
11216 TREE_TYPE (node->decl) = new_type;
11218 adjustments.release ();
11220 args.release ();
11221 return adjustments;
11224 /* Initialize and copy the function arguments in NODE to their
11225 corresponding local simd arrays. Returns a fresh gimple_seq with
11226 the instruction sequence generated. */
11228 static gimple_seq
11229 simd_clone_init_simd_arrays (struct cgraph_node *node,
11230 ipa_parm_adjustment_vec adjustments)
11232 gimple_seq seq = NULL;
11233 unsigned i = 0, j = 0, k;
11235 for (tree arg = DECL_ARGUMENTS (node->decl);
11236 arg;
11237 arg = DECL_CHAIN (arg), i++, j++)
11239 if (adjustments[j].op == IPA_PARM_OP_COPY)
11240 continue;
11242 node->simdclone->args[i].vector_arg = arg;
11244 tree array = node->simdclone->args[i].simd_array;
11245 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11247 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11248 tree ptr = build_fold_addr_expr (array);
11249 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11250 build_int_cst (ptype, 0));
11251 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11252 gimplify_and_add (t, &seq);
11254 else
11256 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11257 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11258 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11260 tree ptr = build_fold_addr_expr (array);
11261 int elemsize;
11262 if (k)
11264 arg = DECL_CHAIN (arg);
11265 j++;
11267 elemsize
11268 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11269 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11270 build_int_cst (ptype, k * elemsize));
11271 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11272 gimplify_and_add (t, &seq);
11276 return seq;
11279 /* Callback info for ipa_simd_modify_stmt_ops below. */
11281 struct modify_stmt_info {
11282 ipa_parm_adjustment_vec adjustments;
11283 gimple stmt;
11284 /* True if the parent statement was modified by
11285 ipa_simd_modify_stmt_ops. */
11286 bool modified;
11289 /* Callback for walk_gimple_op.
11291 Adjust operands from a given statement as specified in the
11292 adjustments vector in the callback data. */
11294 static tree
11295 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11297 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11298 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11299 tree *orig_tp = tp;
11300 if (TREE_CODE (*tp) == ADDR_EXPR)
11301 tp = &TREE_OPERAND (*tp, 0);
11302 struct ipa_parm_adjustment *cand = NULL;
11303 if (TREE_CODE (*tp) == PARM_DECL)
11304 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11305 else
11307 if (TYPE_P (*tp))
11308 *walk_subtrees = 0;
11311 tree repl = NULL_TREE;
11312 if (cand)
11313 repl = unshare_expr (cand->new_decl);
11314 else
11316 if (tp != orig_tp)
11318 *walk_subtrees = 0;
11319 bool modified = info->modified;
11320 info->modified = false;
11321 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11322 if (!info->modified)
11324 info->modified = modified;
11325 return NULL_TREE;
11327 info->modified = modified;
11328 repl = *tp;
11330 else
11331 return NULL_TREE;
11334 if (tp != orig_tp)
11336 repl = build_fold_addr_expr (repl);
11337 gimple stmt
11338 = gimple_build_assign (make_ssa_name (TREE_TYPE (repl), NULL), repl);
11339 repl = gimple_assign_lhs (stmt);
11340 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11341 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11342 *orig_tp = repl;
11344 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11346 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11347 *tp = vce;
11349 else
11350 *tp = repl;
11352 info->modified = true;
11353 return NULL_TREE;
11356 /* Traverse the function body and perform all modifications as
11357 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11358 modified such that the replacement/reduction value will now be an
11359 offset into the corresponding simd_array.
11361 This function will replace all function argument uses with their
11362 corresponding simd array elements, and ajust the return values
11363 accordingly. */
11365 static void
11366 ipa_simd_modify_function_body (struct cgraph_node *node,
11367 ipa_parm_adjustment_vec adjustments,
11368 tree retval_array, tree iter)
11370 basic_block bb;
11371 unsigned int i, j, l;
11373 /* Re-use the adjustments array, but this time use it to replace
11374 every function argument use to an offset into the corresponding
11375 simd_array. */
11376 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11378 if (!node->simdclone->args[i].vector_arg)
11379 continue;
11381 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11382 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11383 adjustments[j].new_decl
11384 = build4 (ARRAY_REF,
11385 basetype,
11386 node->simdclone->args[i].simd_array,
11387 iter,
11388 NULL_TREE, NULL_TREE);
11389 if (adjustments[j].op == IPA_PARM_OP_NONE
11390 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11391 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11394 l = adjustments.length ();
11395 for (i = 1; i < num_ssa_names; i++)
11397 tree name = ssa_name (i);
11398 if (name
11399 && SSA_NAME_VAR (name)
11400 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11402 for (j = 0; j < l; j++)
11403 if (SSA_NAME_VAR (name) == adjustments[j].base
11404 && adjustments[j].new_decl)
11406 tree base_var;
11407 if (adjustments[j].new_ssa_base == NULL_TREE)
11409 base_var
11410 = copy_var_decl (adjustments[j].base,
11411 DECL_NAME (adjustments[j].base),
11412 TREE_TYPE (adjustments[j].base));
11413 adjustments[j].new_ssa_base = base_var;
11415 else
11416 base_var = adjustments[j].new_ssa_base;
11417 if (SSA_NAME_IS_DEFAULT_DEF (name))
11419 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11420 gimple_stmt_iterator gsi = gsi_after_labels (bb);
11421 tree new_decl = unshare_expr (adjustments[j].new_decl);
11422 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
11423 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11424 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
11425 gimple stmt = gimple_build_assign (name, new_decl);
11426 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11428 else
11429 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11434 struct modify_stmt_info info;
11435 info.adjustments = adjustments;
11437 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
11439 gimple_stmt_iterator gsi;
11441 gsi = gsi_start_bb (bb);
11442 while (!gsi_end_p (gsi))
11444 gimple stmt = gsi_stmt (gsi);
11445 info.stmt = stmt;
11446 struct walk_stmt_info wi;
11448 memset (&wi, 0, sizeof (wi));
11449 info.modified = false;
11450 wi.info = &info;
11451 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
11453 if (gimple_code (stmt) == GIMPLE_RETURN)
11455 tree retval = gimple_return_retval (stmt);
11456 if (!retval)
11458 gsi_remove (&gsi, true);
11459 continue;
11462 /* Replace `return foo' with `retval_array[iter] = foo'. */
11463 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
11464 retval_array, iter, NULL, NULL);
11465 stmt = gimple_build_assign (ref, retval);
11466 gsi_replace (&gsi, stmt, true);
11467 info.modified = true;
11470 if (info.modified)
11472 update_stmt (stmt);
11473 if (maybe_clean_eh_stmt (stmt))
11474 gimple_purge_dead_eh_edges (gimple_bb (stmt));
11476 gsi_next (&gsi);
11481 /* Adjust the argument types in NODE to their appropriate vector
11482 counterparts. */
11484 static void
11485 simd_clone_adjust (struct cgraph_node *node)
11487 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
11489 targetm.simd_clone.adjust (node);
11491 tree retval = simd_clone_adjust_return_type (node);
11492 ipa_parm_adjustment_vec adjustments
11493 = simd_clone_adjust_argument_types (node);
11495 push_gimplify_context ();
11497 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
11499 /* Adjust all uses of vector arguments accordingly. Adjust all
11500 return values accordingly. */
11501 tree iter = create_tmp_var (unsigned_type_node, "iter");
11502 tree iter1 = make_ssa_name (iter, NULL);
11503 tree iter2 = make_ssa_name (iter, NULL);
11504 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
11506 /* Initialize the iteration variable. */
11507 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11508 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
11509 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
11510 /* Insert the SIMD array and iv initialization at function
11511 entry. */
11512 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
11514 pop_gimplify_context (NULL);
11516 /* Create a new BB right before the original exit BB, to hold the
11517 iteration increment and the condition/branch. */
11518 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
11519 basic_block incr_bb = create_empty_bb (orig_exit);
11520 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11521 flag. Set it now to be a FALLTHRU_EDGE. */
11522 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
11523 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
11524 for (unsigned i = 0;
11525 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
11527 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
11528 redirect_edge_succ (e, incr_bb);
11530 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
11531 e->probability = REG_BR_PROB_BASE;
11532 gsi = gsi_last_bb (incr_bb);
11533 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
11534 build_int_cst (unsigned_type_node,
11535 1));
11536 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11538 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
11539 struct loop *loop = alloc_loop ();
11540 cfun->has_force_vectorize_loops = true;
11541 loop->safelen = node->simdclone->simdlen;
11542 loop->force_vectorize = true;
11543 loop->header = body_bb;
11544 add_bb_to_loop (incr_bb, loop);
11546 /* Branch around the body if the mask applies. */
11547 if (node->simdclone->inbranch)
11549 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
11550 tree mask_array
11551 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
11552 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
11553 tree aref = build4 (ARRAY_REF,
11554 TREE_TYPE (TREE_TYPE (mask_array)),
11555 mask_array, iter1,
11556 NULL, NULL);
11557 g = gimple_build_assign (mask, aref);
11558 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11559 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
11560 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
11562 aref = build1 (VIEW_CONVERT_EXPR,
11563 build_nonstandard_integer_type (bitsize, 0), mask);
11564 mask = make_ssa_name (TREE_TYPE (aref), NULL);
11565 g = gimple_build_assign (mask, aref);
11566 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11569 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
11570 NULL, NULL);
11571 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11572 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
11573 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
11576 /* Generate the condition. */
11577 g = gimple_build_cond (LT_EXPR,
11578 iter2,
11579 build_int_cst (unsigned_type_node,
11580 node->simdclone->simdlen),
11581 NULL, NULL);
11582 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11583 e = split_block (incr_bb, gsi_stmt (gsi));
11584 basic_block latch_bb = e->dest;
11585 basic_block new_exit_bb = e->dest;
11586 new_exit_bb = split_block (latch_bb, NULL)->dest;
11587 loop->latch = latch_bb;
11589 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
11591 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
11592 /* The successor of incr_bb is already pointing to latch_bb; just
11593 change the flags.
11594 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
11595 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
11597 gimple phi = create_phi_node (iter1, body_bb);
11598 edge preheader_edge = find_edge (entry_bb, body_bb);
11599 edge latch_edge = single_succ_edge (latch_bb);
11600 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
11601 UNKNOWN_LOCATION);
11602 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11604 /* Generate the new return. */
11605 gsi = gsi_last_bb (new_exit_bb);
11606 if (retval
11607 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
11608 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
11609 retval = TREE_OPERAND (retval, 0);
11610 else if (retval)
11612 retval = build1 (VIEW_CONVERT_EXPR,
11613 TREE_TYPE (TREE_TYPE (node->decl)),
11614 retval);
11615 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
11616 false, GSI_CONTINUE_LINKING);
11618 g = gimple_build_return (retval);
11619 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11621 /* Handle aligned clauses by replacing default defs of the aligned
11622 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
11623 lhs. Handle linear by adding PHIs. */
11624 for (unsigned i = 0; i < node->simdclone->nargs; i++)
11625 if (node->simdclone->args[i].alignment
11626 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
11627 && (node->simdclone->args[i].alignment
11628 & (node->simdclone->args[i].alignment - 1)) == 0
11629 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
11630 == POINTER_TYPE)
11632 unsigned int alignment = node->simdclone->args[i].alignment;
11633 tree orig_arg = node->simdclone->args[i].orig_arg;
11634 tree def = ssa_default_def (cfun, orig_arg);
11635 if (def && !has_zero_uses (def))
11637 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
11638 gimple_seq seq = NULL;
11639 bool need_cvt = false;
11640 gimple call
11641 = gimple_build_call (fn, 2, def, size_int (alignment));
11642 g = call;
11643 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
11644 ptr_type_node))
11645 need_cvt = true;
11646 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
11647 gimple_call_set_lhs (g, t);
11648 gimple_seq_add_stmt_without_update (&seq, g);
11649 if (need_cvt)
11651 t = make_ssa_name (orig_arg, NULL);
11652 g = gimple_build_assign_with_ops (NOP_EXPR, t,
11653 gimple_call_lhs (g),
11654 NULL_TREE);
11655 gimple_seq_add_stmt_without_update (&seq, g);
11657 gsi_insert_seq_on_edge_immediate
11658 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
11660 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11661 int freq = compute_call_stmt_bb_frequency (current_function_decl,
11662 entry_bb);
11663 cgraph_create_edge (node, cgraph_get_create_node (fn),
11664 call, entry_bb->count, freq);
11666 imm_use_iterator iter;
11667 use_operand_p use_p;
11668 gimple use_stmt;
11669 tree repl = gimple_get_lhs (g);
11670 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11671 if (is_gimple_debug (use_stmt) || use_stmt == call)
11672 continue;
11673 else
11674 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11675 SET_USE (use_p, repl);
11678 else if (node->simdclone->args[i].arg_type
11679 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11681 tree orig_arg = node->simdclone->args[i].orig_arg;
11682 tree def = ssa_default_def (cfun, orig_arg);
11683 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11684 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
11685 if (def && !has_zero_uses (def))
11687 iter1 = make_ssa_name (orig_arg, NULL);
11688 iter2 = make_ssa_name (orig_arg, NULL);
11689 phi = create_phi_node (iter1, body_bb);
11690 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
11691 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11692 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11693 ? PLUS_EXPR : POINTER_PLUS_EXPR;
11694 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11695 ? TREE_TYPE (orig_arg) : sizetype;
11696 tree addcst
11697 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
11698 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
11699 gsi = gsi_last_bb (incr_bb);
11700 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
11702 imm_use_iterator iter;
11703 use_operand_p use_p;
11704 gimple use_stmt;
11705 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11706 if (use_stmt == phi)
11707 continue;
11708 else
11709 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11710 SET_USE (use_p, iter1);
11714 calculate_dominance_info (CDI_DOMINATORS);
11715 add_loop (loop, loop->header->loop_father);
11716 update_ssa (TODO_update_ssa);
11718 pop_cfun ();
11721 /* If the function in NODE is tagged as an elemental SIMD function,
11722 create the appropriate SIMD clones. */
11724 static void
11725 expand_simd_clones (struct cgraph_node *node)
11727 tree attr = lookup_attribute ("omp declare simd",
11728 DECL_ATTRIBUTES (node->decl));
11729 if (attr == NULL_TREE
11730 || node->global.inlined_to
11731 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
11732 return;
11734 /* Ignore
11735 #pragma omp declare simd
11736 extern int foo ();
11737 in C, there we don't know the argument types at all. */
11738 if (!node->definition
11739 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
11740 return;
11744 /* Start with parsing the "omp declare simd" attribute(s). */
11745 bool inbranch_clause_specified;
11746 struct cgraph_simd_clone *clone_info
11747 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
11748 &inbranch_clause_specified);
11749 if (clone_info == NULL)
11750 continue;
11752 int orig_simdlen = clone_info->simdlen;
11753 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
11754 /* The target can return 0 (no simd clones should be created),
11755 1 (just one ISA of simd clones should be created) or higher
11756 count of ISA variants. In that case, clone_info is initialized
11757 for the first ISA variant. */
11758 int count
11759 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
11760 base_type, 0);
11761 if (count == 0)
11762 continue;
11764 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
11765 also create one inbranch and one !inbranch clone of it. */
11766 for (int i = 0; i < count * 2; i++)
11768 struct cgraph_simd_clone *clone = clone_info;
11769 if (inbranch_clause_specified && (i & 1) != 0)
11770 continue;
11772 if (i != 0)
11774 clone = simd_clone_struct_alloc (clone_info->nargs
11775 + ((i & 1) != 0));
11776 simd_clone_struct_copy (clone, clone_info);
11777 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
11778 and simd_clone_adjust_argument_types did to the first
11779 clone's info. */
11780 clone->nargs -= clone_info->inbranch;
11781 clone->simdlen = orig_simdlen;
11782 /* And call the target hook again to get the right ISA. */
11783 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
11784 base_type,
11785 i / 2);
11786 if ((i & 1) != 0)
11787 clone->inbranch = 1;
11790 /* simd_clone_mangle might fail if such a clone has been created
11791 already. */
11792 tree id = simd_clone_mangle (node, clone);
11793 if (id == NULL_TREE)
11794 continue;
11796 /* Only when we are sure we want to create the clone actually
11797 clone the function (or definitions) or create another
11798 extern FUNCTION_DECL (for prototypes without definitions). */
11799 struct cgraph_node *n = simd_clone_create (node);
11800 if (n == NULL)
11801 continue;
11803 n->simdclone = clone;
11804 clone->origin = node;
11805 clone->next_clone = NULL;
11806 if (node->simd_clones == NULL)
11808 clone->prev_clone = n;
11809 node->simd_clones = n;
11811 else
11813 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
11814 clone->prev_clone->simdclone->next_clone = n;
11815 node->simd_clones->simdclone->prev_clone = n;
11817 change_decl_assembler_name (n->decl, id);
11818 /* And finally adjust the return type, parameters and for
11819 definitions also function body. */
11820 if (node->definition)
11821 simd_clone_adjust (n);
11822 else
11824 simd_clone_adjust_return_type (n);
11825 simd_clone_adjust_argument_types (n);
11829 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
11832 /* Entry point for IPA simd clone creation pass. */
11834 static unsigned int
11835 ipa_omp_simd_clone (void)
11837 struct cgraph_node *node;
11838 FOR_EACH_FUNCTION (node)
11839 expand_simd_clones (node);
11840 return 0;
11843 namespace {
11845 const pass_data pass_data_omp_simd_clone =
11847 SIMPLE_IPA_PASS, /* type */
11848 "simdclone", /* name */
11849 OPTGROUP_NONE, /* optinfo_flags */
11850 true, /* has_execute */
11851 TV_NONE, /* tv_id */
11852 ( PROP_ssa | PROP_cfg ), /* properties_required */
11853 0, /* properties_provided */
11854 0, /* properties_destroyed */
11855 0, /* todo_flags_start */
11856 0, /* todo_flags_finish */
11859 class pass_omp_simd_clone : public simple_ipa_opt_pass
11861 public:
11862 pass_omp_simd_clone(gcc::context *ctxt)
11863 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
11866 /* opt_pass methods: */
11867 virtual bool gate (function *);
11868 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
11871 bool
11872 pass_omp_simd_clone::gate (function *)
11874 return ((flag_openmp || flag_openmp_simd
11875 || flag_cilkplus
11876 || (in_lto_p && !flag_wpa))
11877 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
11880 } // anon namespace
11882 simple_ipa_opt_pass *
11883 make_pass_omp_simd_clone (gcc::context *ctxt)
11885 return new pass_omp_simd_clone (ctxt);
11888 #include "gt-omp-low.h"