2013-11-27 Kugan Vivekanandarajah <kuganv@linaro.org>
[official-gcc.git] / gcc / omp-low.c
blob71dc81187348367f77b6f313420dc97e75151cbd
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005-2013 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "stringpool.h"
30 #include "stor-layout.h"
31 #include "rtl.h"
32 #include "pointer-set.h"
33 #include "basic-block.h"
34 #include "tree-ssa-alias.h"
35 #include "internal-fn.h"
36 #include "gimple-fold.h"
37 #include "gimple-expr.h"
38 #include "is-a.h"
39 #include "gimple.h"
40 #include "gimplify.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "gimple-walk.h"
44 #include "tree-iterator.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47 #include "diagnostic-core.h"
48 #include "gimple-ssa.h"
49 #include "cgraph.h"
50 #include "tree-cfg.h"
51 #include "tree-phinodes.h"
52 #include "ssa-iterators.h"
53 #include "tree-ssanames.h"
54 #include "tree-into-ssa.h"
55 #include "expr.h"
56 #include "tree-dfa.h"
57 #include "tree-ssa.h"
58 #include "flags.h"
59 #include "function.h"
60 #include "expr.h"
61 #include "tree-pass.h"
62 #include "except.h"
63 #include "splay-tree.h"
64 #include "optabs.h"
65 #include "cfgloop.h"
66 #include "target.h"
67 #include "omp-low.h"
68 #include "gimple-low.h"
69 #include "tree-cfgcleanup.h"
70 #include "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 /* Return the parallel region associated with STMT. */
1225 /* Debugging dumps for parallel regions. */
1226 void dump_omp_region (FILE *, struct omp_region *, int);
1227 void debug_omp_region (struct omp_region *);
1228 void debug_all_omp_regions (void);
1230 /* Dump the parallel region tree rooted at REGION. */
1232 void
1233 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1235 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1236 gimple_code_name[region->type]);
1238 if (region->inner)
1239 dump_omp_region (file, region->inner, indent + 4);
1241 if (region->cont)
1243 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1244 region->cont->index);
1247 if (region->exit)
1248 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1249 region->exit->index);
1250 else
1251 fprintf (file, "%*s[no exit marker]\n", indent, "");
1253 if (region->next)
1254 dump_omp_region (file, region->next, indent);
1257 DEBUG_FUNCTION void
1258 debug_omp_region (struct omp_region *region)
1260 dump_omp_region (stderr, region, 0);
1263 DEBUG_FUNCTION void
1264 debug_all_omp_regions (void)
1266 dump_omp_region (stderr, root_omp_region, 0);
1270 /* Create a new parallel region starting at STMT inside region PARENT. */
1272 static struct omp_region *
1273 new_omp_region (basic_block bb, enum gimple_code type,
1274 struct omp_region *parent)
1276 struct omp_region *region = XCNEW (struct omp_region);
1278 region->outer = parent;
1279 region->entry = bb;
1280 region->type = type;
1282 if (parent)
1284 /* This is a nested region. Add it to the list of inner
1285 regions in PARENT. */
1286 region->next = parent->inner;
1287 parent->inner = region;
1289 else
1291 /* This is a toplevel region. Add it to the list of toplevel
1292 regions in ROOT_OMP_REGION. */
1293 region->next = root_omp_region;
1294 root_omp_region = region;
1297 return region;
1300 /* Release the memory associated with the region tree rooted at REGION. */
1302 static void
1303 free_omp_region_1 (struct omp_region *region)
1305 struct omp_region *i, *n;
1307 for (i = region->inner; i ; i = n)
1309 n = i->next;
1310 free_omp_region_1 (i);
1313 free (region);
1316 /* Release the memory for the entire omp region tree. */
1318 void
1319 free_omp_regions (void)
1321 struct omp_region *r, *n;
1322 for (r = root_omp_region; r ; r = n)
1324 n = r->next;
1325 free_omp_region_1 (r);
1327 root_omp_region = NULL;
1331 /* Create a new context, with OUTER_CTX being the surrounding context. */
1333 static omp_context *
1334 new_omp_context (gimple stmt, omp_context *outer_ctx)
1336 omp_context *ctx = XCNEW (omp_context);
1338 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1339 (splay_tree_value) ctx);
1340 ctx->stmt = stmt;
1342 if (outer_ctx)
1344 ctx->outer = outer_ctx;
1345 ctx->cb = outer_ctx->cb;
1346 ctx->cb.block = NULL;
1347 ctx->depth = outer_ctx->depth + 1;
1349 else
1351 ctx->cb.src_fn = current_function_decl;
1352 ctx->cb.dst_fn = current_function_decl;
1353 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1354 gcc_checking_assert (ctx->cb.src_node);
1355 ctx->cb.dst_node = ctx->cb.src_node;
1356 ctx->cb.src_cfun = cfun;
1357 ctx->cb.copy_decl = omp_copy_decl;
1358 ctx->cb.eh_lp_nr = 0;
1359 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1360 ctx->depth = 1;
1363 ctx->cb.decl_map = pointer_map_create ();
1365 return ctx;
1368 static gimple_seq maybe_catch_exception (gimple_seq);
1370 /* Finalize task copyfn. */
1372 static void
1373 finalize_task_copyfn (gimple task_stmt)
1375 struct function *child_cfun;
1376 tree child_fn;
1377 gimple_seq seq = NULL, new_seq;
1378 gimple bind;
1380 child_fn = gimple_omp_task_copy_fn (task_stmt);
1381 if (child_fn == NULL_TREE)
1382 return;
1384 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1385 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1387 push_cfun (child_cfun);
1388 bind = gimplify_body (child_fn, false);
1389 gimple_seq_add_stmt (&seq, bind);
1390 new_seq = maybe_catch_exception (seq);
1391 if (new_seq != seq)
1393 bind = gimple_build_bind (NULL, new_seq, NULL);
1394 seq = NULL;
1395 gimple_seq_add_stmt (&seq, bind);
1397 gimple_set_body (child_fn, seq);
1398 pop_cfun ();
1400 /* Inform the callgraph about the new function. */
1401 cgraph_add_new_function (child_fn, false);
1404 /* Destroy a omp_context data structures. Called through the splay tree
1405 value delete callback. */
1407 static void
1408 delete_omp_context (splay_tree_value value)
1410 omp_context *ctx = (omp_context *) value;
1412 pointer_map_destroy (ctx->cb.decl_map);
1414 if (ctx->field_map)
1415 splay_tree_delete (ctx->field_map);
1416 if (ctx->sfield_map)
1417 splay_tree_delete (ctx->sfield_map);
1419 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1420 it produces corrupt debug information. */
1421 if (ctx->record_type)
1423 tree t;
1424 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1425 DECL_ABSTRACT_ORIGIN (t) = NULL;
1427 if (ctx->srecord_type)
1429 tree t;
1430 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1431 DECL_ABSTRACT_ORIGIN (t) = NULL;
1434 if (is_task_ctx (ctx))
1435 finalize_task_copyfn (ctx->stmt);
1437 XDELETE (ctx);
1440 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1441 context. */
1443 static void
1444 fixup_child_record_type (omp_context *ctx)
1446 tree f, type = ctx->record_type;
1448 /* ??? It isn't sufficient to just call remap_type here, because
1449 variably_modified_type_p doesn't work the way we expect for
1450 record types. Testing each field for whether it needs remapping
1451 and creating a new record by hand works, however. */
1452 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1453 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1454 break;
1455 if (f)
1457 tree name, new_fields = NULL;
1459 type = lang_hooks.types.make_type (RECORD_TYPE);
1460 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1461 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1462 TYPE_DECL, name, type);
1463 TYPE_NAME (type) = name;
1465 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1467 tree new_f = copy_node (f);
1468 DECL_CONTEXT (new_f) = type;
1469 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1470 DECL_CHAIN (new_f) = new_fields;
1471 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1472 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1473 &ctx->cb, NULL);
1474 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1475 &ctx->cb, NULL);
1476 new_fields = new_f;
1478 /* Arrange to be able to look up the receiver field
1479 given the sender field. */
1480 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1481 (splay_tree_value) new_f);
1483 TYPE_FIELDS (type) = nreverse (new_fields);
1484 layout_type (type);
1487 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1490 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1491 specified by CLAUSES. */
1493 static void
1494 scan_sharing_clauses (tree clauses, omp_context *ctx)
1496 tree c, decl;
1497 bool scan_array_reductions = false;
1499 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1501 bool by_ref;
1503 switch (OMP_CLAUSE_CODE (c))
1505 case OMP_CLAUSE_PRIVATE:
1506 decl = OMP_CLAUSE_DECL (c);
1507 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1508 goto do_private;
1509 else if (!is_variable_sized (decl))
1510 install_var_local (decl, ctx);
1511 break;
1513 case OMP_CLAUSE_SHARED:
1514 /* Ignore shared directives in teams construct. */
1515 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1516 break;
1517 gcc_assert (is_taskreg_ctx (ctx));
1518 decl = OMP_CLAUSE_DECL (c);
1519 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1520 || !is_variable_sized (decl));
1521 /* Global variables don't need to be copied,
1522 the receiver side will use them directly. */
1523 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1524 break;
1525 by_ref = use_pointer_for_field (decl, ctx);
1526 if (! TREE_READONLY (decl)
1527 || TREE_ADDRESSABLE (decl)
1528 || by_ref
1529 || is_reference (decl))
1531 install_var_field (decl, by_ref, 3, ctx);
1532 install_var_local (decl, ctx);
1533 break;
1535 /* We don't need to copy const scalar vars back. */
1536 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1537 goto do_private;
1539 case OMP_CLAUSE_LASTPRIVATE:
1540 /* Let the corresponding firstprivate clause create
1541 the variable. */
1542 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1543 break;
1544 /* FALLTHRU */
1546 case OMP_CLAUSE_FIRSTPRIVATE:
1547 case OMP_CLAUSE_REDUCTION:
1548 case OMP_CLAUSE_LINEAR:
1549 decl = OMP_CLAUSE_DECL (c);
1550 do_private:
1551 if (is_variable_sized (decl))
1553 if (is_task_ctx (ctx))
1554 install_var_field (decl, false, 1, ctx);
1555 break;
1557 else if (is_taskreg_ctx (ctx))
1559 bool global
1560 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1561 by_ref = use_pointer_for_field (decl, NULL);
1563 if (is_task_ctx (ctx)
1564 && (global || by_ref || is_reference (decl)))
1566 install_var_field (decl, false, 1, ctx);
1567 if (!global)
1568 install_var_field (decl, by_ref, 2, ctx);
1570 else if (!global)
1571 install_var_field (decl, by_ref, 3, ctx);
1573 install_var_local (decl, ctx);
1574 break;
1576 case OMP_CLAUSE__LOOPTEMP_:
1577 gcc_assert (is_parallel_ctx (ctx));
1578 decl = OMP_CLAUSE_DECL (c);
1579 install_var_field (decl, false, 3, ctx);
1580 install_var_local (decl, ctx);
1581 break;
1583 case OMP_CLAUSE_COPYPRIVATE:
1584 case OMP_CLAUSE_COPYIN:
1585 decl = OMP_CLAUSE_DECL (c);
1586 by_ref = use_pointer_for_field (decl, NULL);
1587 install_var_field (decl, by_ref, 3, ctx);
1588 break;
1590 case OMP_CLAUSE_DEFAULT:
1591 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1592 break;
1594 case OMP_CLAUSE_FINAL:
1595 case OMP_CLAUSE_IF:
1596 case OMP_CLAUSE_NUM_THREADS:
1597 case OMP_CLAUSE_NUM_TEAMS:
1598 case OMP_CLAUSE_THREAD_LIMIT:
1599 case OMP_CLAUSE_DEVICE:
1600 case OMP_CLAUSE_SCHEDULE:
1601 case OMP_CLAUSE_DIST_SCHEDULE:
1602 case OMP_CLAUSE_DEPEND:
1603 if (ctx->outer)
1604 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1605 break;
1607 case OMP_CLAUSE_TO:
1608 case OMP_CLAUSE_FROM:
1609 case OMP_CLAUSE_MAP:
1610 if (ctx->outer)
1611 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1612 decl = OMP_CLAUSE_DECL (c);
1613 /* Global variables with "omp declare target" attribute
1614 don't need to be copied, the receiver side will use them
1615 directly. */
1616 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1617 && DECL_P (decl)
1618 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1619 && lookup_attribute ("omp declare target",
1620 DECL_ATTRIBUTES (decl)))
1621 break;
1622 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1623 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1625 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1626 #pragma omp target data, there is nothing to map for
1627 those. */
1628 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1629 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1630 break;
1632 if (DECL_P (decl))
1634 if (DECL_SIZE (decl)
1635 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1637 tree decl2 = DECL_VALUE_EXPR (decl);
1638 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1639 decl2 = TREE_OPERAND (decl2, 0);
1640 gcc_assert (DECL_P (decl2));
1641 install_var_field (decl2, true, 3, ctx);
1642 install_var_local (decl2, ctx);
1643 install_var_local (decl, ctx);
1645 else
1647 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1648 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1649 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1650 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1651 install_var_field (decl, true, 7, ctx);
1652 else
1653 install_var_field (decl, true, 3, ctx);
1654 if (gimple_omp_target_kind (ctx->stmt)
1655 == GF_OMP_TARGET_KIND_REGION)
1656 install_var_local (decl, ctx);
1659 else
1661 tree base = get_base_address (decl);
1662 tree nc = OMP_CLAUSE_CHAIN (c);
1663 if (DECL_P (base)
1664 && nc != NULL_TREE
1665 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1666 && OMP_CLAUSE_DECL (nc) == base
1667 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1668 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1670 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1671 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1673 else
1675 gcc_assert (!splay_tree_lookup (ctx->field_map,
1676 (splay_tree_key) decl));
1677 tree field
1678 = build_decl (OMP_CLAUSE_LOCATION (c),
1679 FIELD_DECL, NULL_TREE, ptr_type_node);
1680 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1681 insert_field_into_struct (ctx->record_type, field);
1682 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1683 (splay_tree_value) field);
1686 break;
1688 case OMP_CLAUSE_NOWAIT:
1689 case OMP_CLAUSE_ORDERED:
1690 case OMP_CLAUSE_COLLAPSE:
1691 case OMP_CLAUSE_UNTIED:
1692 case OMP_CLAUSE_MERGEABLE:
1693 case OMP_CLAUSE_PROC_BIND:
1694 case OMP_CLAUSE_SAFELEN:
1695 break;
1697 case OMP_CLAUSE_ALIGNED:
1698 decl = OMP_CLAUSE_DECL (c);
1699 if (is_global_var (decl)
1700 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1701 install_var_local (decl, ctx);
1702 break;
1704 default:
1705 gcc_unreachable ();
1709 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1711 switch (OMP_CLAUSE_CODE (c))
1713 case OMP_CLAUSE_LASTPRIVATE:
1714 /* Let the corresponding firstprivate clause create
1715 the variable. */
1716 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1717 scan_array_reductions = true;
1718 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1719 break;
1720 /* FALLTHRU */
1722 case OMP_CLAUSE_PRIVATE:
1723 case OMP_CLAUSE_FIRSTPRIVATE:
1724 case OMP_CLAUSE_REDUCTION:
1725 case OMP_CLAUSE_LINEAR:
1726 decl = OMP_CLAUSE_DECL (c);
1727 if (is_variable_sized (decl))
1728 install_var_local (decl, ctx);
1729 fixup_remapped_decl (decl, ctx,
1730 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1731 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1732 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1733 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1734 scan_array_reductions = true;
1735 break;
1737 case OMP_CLAUSE_SHARED:
1738 /* Ignore shared directives in teams construct. */
1739 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1740 break;
1741 decl = OMP_CLAUSE_DECL (c);
1742 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1743 fixup_remapped_decl (decl, ctx, false);
1744 break;
1746 case OMP_CLAUSE_MAP:
1747 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1748 break;
1749 decl = OMP_CLAUSE_DECL (c);
1750 if (DECL_P (decl)
1751 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1752 && lookup_attribute ("omp declare target",
1753 DECL_ATTRIBUTES (decl)))
1754 break;
1755 if (DECL_P (decl))
1757 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1758 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1759 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1761 tree new_decl = lookup_decl (decl, ctx);
1762 TREE_TYPE (new_decl)
1763 = remap_type (TREE_TYPE (decl), &ctx->cb);
1765 else if (DECL_SIZE (decl)
1766 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1768 tree decl2 = DECL_VALUE_EXPR (decl);
1769 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1770 decl2 = TREE_OPERAND (decl2, 0);
1771 gcc_assert (DECL_P (decl2));
1772 fixup_remapped_decl (decl2, ctx, false);
1773 fixup_remapped_decl (decl, ctx, true);
1775 else
1776 fixup_remapped_decl (decl, ctx, false);
1778 break;
1780 case OMP_CLAUSE_COPYPRIVATE:
1781 case OMP_CLAUSE_COPYIN:
1782 case OMP_CLAUSE_DEFAULT:
1783 case OMP_CLAUSE_IF:
1784 case OMP_CLAUSE_NUM_THREADS:
1785 case OMP_CLAUSE_NUM_TEAMS:
1786 case OMP_CLAUSE_THREAD_LIMIT:
1787 case OMP_CLAUSE_DEVICE:
1788 case OMP_CLAUSE_SCHEDULE:
1789 case OMP_CLAUSE_DIST_SCHEDULE:
1790 case OMP_CLAUSE_NOWAIT:
1791 case OMP_CLAUSE_ORDERED:
1792 case OMP_CLAUSE_COLLAPSE:
1793 case OMP_CLAUSE_UNTIED:
1794 case OMP_CLAUSE_FINAL:
1795 case OMP_CLAUSE_MERGEABLE:
1796 case OMP_CLAUSE_PROC_BIND:
1797 case OMP_CLAUSE_SAFELEN:
1798 case OMP_CLAUSE_ALIGNED:
1799 case OMP_CLAUSE_DEPEND:
1800 case OMP_CLAUSE__LOOPTEMP_:
1801 case OMP_CLAUSE_TO:
1802 case OMP_CLAUSE_FROM:
1803 break;
1805 default:
1806 gcc_unreachable ();
1810 if (scan_array_reductions)
1811 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1812 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1813 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1815 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1816 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1818 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1819 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1820 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1823 /* Create a new name for omp child function. Returns an identifier. */
1825 static GTY(()) unsigned int tmp_ompfn_id_num;
1827 static tree
1828 create_omp_child_function_name (bool task_copy)
1830 return (clone_function_name (current_function_decl,
1831 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1834 /* Build a decl for the omp child function. It'll not contain a body
1835 yet, just the bare decl. */
1837 static void
1838 create_omp_child_function (omp_context *ctx, bool task_copy)
1840 tree decl, type, name, t;
1842 name = create_omp_child_function_name (task_copy);
1843 if (task_copy)
1844 type = build_function_type_list (void_type_node, ptr_type_node,
1845 ptr_type_node, NULL_TREE);
1846 else
1847 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1849 decl = build_decl (gimple_location (ctx->stmt),
1850 FUNCTION_DECL, name, type);
1852 if (!task_copy)
1853 ctx->cb.dst_fn = decl;
1854 else
1855 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1857 TREE_STATIC (decl) = 1;
1858 TREE_USED (decl) = 1;
1859 DECL_ARTIFICIAL (decl) = 1;
1860 DECL_NAMELESS (decl) = 1;
1861 DECL_IGNORED_P (decl) = 0;
1862 TREE_PUBLIC (decl) = 0;
1863 DECL_UNINLINABLE (decl) = 1;
1864 DECL_EXTERNAL (decl) = 0;
1865 DECL_CONTEXT (decl) = NULL_TREE;
1866 DECL_INITIAL (decl) = make_node (BLOCK);
1867 bool target_p = false;
1868 if (lookup_attribute ("omp declare target",
1869 DECL_ATTRIBUTES (current_function_decl)))
1870 target_p = true;
1871 else
1873 omp_context *octx;
1874 for (octx = ctx; octx; octx = octx->outer)
1875 if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
1876 && gimple_omp_target_kind (octx->stmt)
1877 == GF_OMP_TARGET_KIND_REGION)
1879 target_p = true;
1880 break;
1883 if (target_p)
1884 DECL_ATTRIBUTES (decl)
1885 = tree_cons (get_identifier ("omp declare target"),
1886 NULL_TREE, DECL_ATTRIBUTES (decl));
1888 t = build_decl (DECL_SOURCE_LOCATION (decl),
1889 RESULT_DECL, NULL_TREE, void_type_node);
1890 DECL_ARTIFICIAL (t) = 1;
1891 DECL_IGNORED_P (t) = 1;
1892 DECL_CONTEXT (t) = decl;
1893 DECL_RESULT (decl) = t;
1895 t = build_decl (DECL_SOURCE_LOCATION (decl),
1896 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1897 DECL_ARTIFICIAL (t) = 1;
1898 DECL_NAMELESS (t) = 1;
1899 DECL_ARG_TYPE (t) = ptr_type_node;
1900 DECL_CONTEXT (t) = current_function_decl;
1901 TREE_USED (t) = 1;
1902 DECL_ARGUMENTS (decl) = t;
1903 if (!task_copy)
1904 ctx->receiver_decl = t;
1905 else
1907 t = build_decl (DECL_SOURCE_LOCATION (decl),
1908 PARM_DECL, get_identifier (".omp_data_o"),
1909 ptr_type_node);
1910 DECL_ARTIFICIAL (t) = 1;
1911 DECL_NAMELESS (t) = 1;
1912 DECL_ARG_TYPE (t) = ptr_type_node;
1913 DECL_CONTEXT (t) = current_function_decl;
1914 TREE_USED (t) = 1;
1915 TREE_ADDRESSABLE (t) = 1;
1916 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1917 DECL_ARGUMENTS (decl) = t;
1920 /* Allocate memory for the function structure. The call to
1921 allocate_struct_function clobbers CFUN, so we need to restore
1922 it afterward. */
1923 push_struct_function (decl);
1924 cfun->function_end_locus = gimple_location (ctx->stmt);
1925 pop_cfun ();
1928 /* Callback for walk_gimple_seq. Check if combined parallel
1929 contains gimple_omp_for_combined_into_p OMP_FOR. */
1931 static tree
1932 find_combined_for (gimple_stmt_iterator *gsi_p,
1933 bool *handled_ops_p,
1934 struct walk_stmt_info *wi)
1936 gimple stmt = gsi_stmt (*gsi_p);
1938 *handled_ops_p = true;
1939 switch (gimple_code (stmt))
1941 WALK_SUBSTMTS;
1943 case GIMPLE_OMP_FOR:
1944 if (gimple_omp_for_combined_into_p (stmt)
1945 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
1947 wi->info = stmt;
1948 return integer_zero_node;
1950 break;
1951 default:
1952 break;
1954 return NULL;
1957 /* Scan an OpenMP parallel directive. */
1959 static void
1960 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1962 omp_context *ctx;
1963 tree name;
1964 gimple stmt = gsi_stmt (*gsi);
1966 /* Ignore parallel directives with empty bodies, unless there
1967 are copyin clauses. */
1968 if (optimize > 0
1969 && empty_body_p (gimple_omp_body (stmt))
1970 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1971 OMP_CLAUSE_COPYIN) == NULL)
1973 gsi_replace (gsi, gimple_build_nop (), false);
1974 return;
1977 if (gimple_omp_parallel_combined_p (stmt))
1979 gimple for_stmt;
1980 struct walk_stmt_info wi;
1982 memset (&wi, 0, sizeof (wi));
1983 wi.val_only = true;
1984 walk_gimple_seq (gimple_omp_body (stmt),
1985 find_combined_for, NULL, &wi);
1986 for_stmt = (gimple) wi.info;
1987 if (for_stmt)
1989 struct omp_for_data fd;
1990 extract_omp_for_data (for_stmt, &fd, NULL);
1991 /* We need two temporaries with fd.loop.v type (istart/iend)
1992 and then (fd.collapse - 1) temporaries with the same
1993 type for count2 ... countN-1 vars if not constant. */
1994 size_t count = 2, i;
1995 tree type = fd.iter_type;
1996 if (fd.collapse > 1
1997 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
1998 count += fd.collapse - 1;
1999 for (i = 0; i < count; i++)
2001 tree temp = create_tmp_var (type, NULL);
2002 tree c = build_omp_clause (UNKNOWN_LOCATION,
2003 OMP_CLAUSE__LOOPTEMP_);
2004 OMP_CLAUSE_DECL (c) = temp;
2005 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2006 gimple_omp_parallel_set_clauses (stmt, c);
2011 ctx = new_omp_context (stmt, outer_ctx);
2012 if (taskreg_nesting_level > 1)
2013 ctx->is_nested = true;
2014 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2015 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2016 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2017 name = create_tmp_var_name (".omp_data_s");
2018 name = build_decl (gimple_location (stmt),
2019 TYPE_DECL, name, ctx->record_type);
2020 DECL_ARTIFICIAL (name) = 1;
2021 DECL_NAMELESS (name) = 1;
2022 TYPE_NAME (ctx->record_type) = name;
2023 create_omp_child_function (ctx, false);
2024 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2026 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2027 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2029 if (TYPE_FIELDS (ctx->record_type) == NULL)
2030 ctx->record_type = ctx->receiver_decl = NULL;
2031 else
2033 layout_type (ctx->record_type);
2034 fixup_child_record_type (ctx);
2038 /* Scan an OpenMP task directive. */
2040 static void
2041 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2043 omp_context *ctx;
2044 tree name, t;
2045 gimple stmt = gsi_stmt (*gsi);
2046 location_t loc = gimple_location (stmt);
2048 /* Ignore task directives with empty bodies. */
2049 if (optimize > 0
2050 && empty_body_p (gimple_omp_body (stmt)))
2052 gsi_replace (gsi, gimple_build_nop (), false);
2053 return;
2056 ctx = new_omp_context (stmt, outer_ctx);
2057 if (taskreg_nesting_level > 1)
2058 ctx->is_nested = true;
2059 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2060 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2061 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2062 name = create_tmp_var_name (".omp_data_s");
2063 name = build_decl (gimple_location (stmt),
2064 TYPE_DECL, name, ctx->record_type);
2065 DECL_ARTIFICIAL (name) = 1;
2066 DECL_NAMELESS (name) = 1;
2067 TYPE_NAME (ctx->record_type) = name;
2068 create_omp_child_function (ctx, false);
2069 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2071 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2073 if (ctx->srecord_type)
2075 name = create_tmp_var_name (".omp_data_a");
2076 name = build_decl (gimple_location (stmt),
2077 TYPE_DECL, name, ctx->srecord_type);
2078 DECL_ARTIFICIAL (name) = 1;
2079 DECL_NAMELESS (name) = 1;
2080 TYPE_NAME (ctx->srecord_type) = name;
2081 create_omp_child_function (ctx, true);
2084 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2086 if (TYPE_FIELDS (ctx->record_type) == NULL)
2088 ctx->record_type = ctx->receiver_decl = NULL;
2089 t = build_int_cst (long_integer_type_node, 0);
2090 gimple_omp_task_set_arg_size (stmt, t);
2091 t = build_int_cst (long_integer_type_node, 1);
2092 gimple_omp_task_set_arg_align (stmt, t);
2094 else
2096 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2097 /* Move VLA fields to the end. */
2098 p = &TYPE_FIELDS (ctx->record_type);
2099 while (*p)
2100 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2101 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2103 *q = *p;
2104 *p = TREE_CHAIN (*p);
2105 TREE_CHAIN (*q) = NULL_TREE;
2106 q = &TREE_CHAIN (*q);
2108 else
2109 p = &DECL_CHAIN (*p);
2110 *p = vla_fields;
2111 layout_type (ctx->record_type);
2112 fixup_child_record_type (ctx);
2113 if (ctx->srecord_type)
2114 layout_type (ctx->srecord_type);
2115 t = fold_convert_loc (loc, long_integer_type_node,
2116 TYPE_SIZE_UNIT (ctx->record_type));
2117 gimple_omp_task_set_arg_size (stmt, t);
2118 t = build_int_cst (long_integer_type_node,
2119 TYPE_ALIGN_UNIT (ctx->record_type));
2120 gimple_omp_task_set_arg_align (stmt, t);
2125 /* Scan an OpenMP loop directive. */
2127 static void
2128 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2130 omp_context *ctx;
2131 size_t i;
2133 ctx = new_omp_context (stmt, outer_ctx);
2135 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2137 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2138 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2140 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2141 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2142 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2143 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2145 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2148 /* Scan an OpenMP sections directive. */
2150 static void
2151 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2153 omp_context *ctx;
2155 ctx = new_omp_context (stmt, outer_ctx);
2156 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2157 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2160 /* Scan an OpenMP single directive. */
2162 static void
2163 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2165 omp_context *ctx;
2166 tree name;
2168 ctx = new_omp_context (stmt, outer_ctx);
2169 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2170 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2171 name = create_tmp_var_name (".omp_copy_s");
2172 name = build_decl (gimple_location (stmt),
2173 TYPE_DECL, name, ctx->record_type);
2174 TYPE_NAME (ctx->record_type) = name;
2176 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2177 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2179 if (TYPE_FIELDS (ctx->record_type) == NULL)
2180 ctx->record_type = NULL;
2181 else
2182 layout_type (ctx->record_type);
2185 /* Scan an OpenMP target{, data, update} directive. */
2187 static void
2188 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2190 omp_context *ctx;
2191 tree name;
2192 int kind = gimple_omp_target_kind (stmt);
2194 ctx = new_omp_context (stmt, outer_ctx);
2195 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2196 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2197 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2198 name = create_tmp_var_name (".omp_data_t");
2199 name = build_decl (gimple_location (stmt),
2200 TYPE_DECL, name, ctx->record_type);
2201 DECL_ARTIFICIAL (name) = 1;
2202 DECL_NAMELESS (name) = 1;
2203 TYPE_NAME (ctx->record_type) = name;
2204 if (kind == GF_OMP_TARGET_KIND_REGION)
2206 create_omp_child_function (ctx, false);
2207 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2210 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2211 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2213 if (TYPE_FIELDS (ctx->record_type) == NULL)
2214 ctx->record_type = ctx->receiver_decl = NULL;
2215 else
2217 TYPE_FIELDS (ctx->record_type)
2218 = nreverse (TYPE_FIELDS (ctx->record_type));
2219 #ifdef ENABLE_CHECKING
2220 tree field;
2221 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2222 for (field = TYPE_FIELDS (ctx->record_type);
2223 field;
2224 field = DECL_CHAIN (field))
2225 gcc_assert (DECL_ALIGN (field) == align);
2226 #endif
2227 layout_type (ctx->record_type);
2228 if (kind == GF_OMP_TARGET_KIND_REGION)
2229 fixup_child_record_type (ctx);
2233 /* Scan an OpenMP teams directive. */
2235 static void
2236 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2238 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2239 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2240 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2243 /* Check OpenMP nesting restrictions. */
2244 static bool
2245 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2247 if (ctx != NULL)
2249 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2250 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2252 error_at (gimple_location (stmt),
2253 "OpenMP constructs may not be nested inside simd region");
2254 return false;
2256 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2258 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2259 || (gimple_omp_for_kind (stmt)
2260 != GF_OMP_FOR_KIND_DISTRIBUTE))
2261 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2263 error_at (gimple_location (stmt),
2264 "only distribute or parallel constructs are allowed to "
2265 "be closely nested inside teams construct");
2266 return false;
2270 switch (gimple_code (stmt))
2272 case GIMPLE_OMP_FOR:
2273 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_KIND_SIMD)
2274 return true;
2275 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2277 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2279 error_at (gimple_location (stmt),
2280 "distribute construct must be closely nested inside "
2281 "teams construct");
2282 return false;
2284 return true;
2286 /* FALLTHRU */
2287 case GIMPLE_CALL:
2288 if (is_gimple_call (stmt)
2289 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2290 == BUILT_IN_GOMP_CANCEL
2291 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2292 == BUILT_IN_GOMP_CANCELLATION_POINT))
2294 const char *bad = NULL;
2295 const char *kind = NULL;
2296 if (ctx == NULL)
2298 error_at (gimple_location (stmt), "orphaned %qs construct",
2299 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2300 == BUILT_IN_GOMP_CANCEL
2301 ? "#pragma omp cancel"
2302 : "#pragma omp cancellation point");
2303 return false;
2305 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2306 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2307 : 0)
2309 case 1:
2310 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2311 bad = "#pragma omp parallel";
2312 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2313 == BUILT_IN_GOMP_CANCEL
2314 && !integer_zerop (gimple_call_arg (stmt, 1)))
2315 ctx->cancellable = true;
2316 kind = "parallel";
2317 break;
2318 case 2:
2319 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2320 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2321 bad = "#pragma omp for";
2322 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2323 == BUILT_IN_GOMP_CANCEL
2324 && !integer_zerop (gimple_call_arg (stmt, 1)))
2326 ctx->cancellable = true;
2327 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2328 OMP_CLAUSE_NOWAIT))
2329 warning_at (gimple_location (stmt), 0,
2330 "%<#pragma omp cancel for%> inside "
2331 "%<nowait%> for construct");
2332 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2333 OMP_CLAUSE_ORDERED))
2334 warning_at (gimple_location (stmt), 0,
2335 "%<#pragma omp cancel for%> inside "
2336 "%<ordered%> for construct");
2338 kind = "for";
2339 break;
2340 case 4:
2341 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2342 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2343 bad = "#pragma omp sections";
2344 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2345 == BUILT_IN_GOMP_CANCEL
2346 && !integer_zerop (gimple_call_arg (stmt, 1)))
2348 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2350 ctx->cancellable = true;
2351 if (find_omp_clause (gimple_omp_sections_clauses
2352 (ctx->stmt),
2353 OMP_CLAUSE_NOWAIT))
2354 warning_at (gimple_location (stmt), 0,
2355 "%<#pragma omp cancel sections%> inside "
2356 "%<nowait%> sections construct");
2358 else
2360 gcc_assert (ctx->outer
2361 && gimple_code (ctx->outer->stmt)
2362 == GIMPLE_OMP_SECTIONS);
2363 ctx->outer->cancellable = true;
2364 if (find_omp_clause (gimple_omp_sections_clauses
2365 (ctx->outer->stmt),
2366 OMP_CLAUSE_NOWAIT))
2367 warning_at (gimple_location (stmt), 0,
2368 "%<#pragma omp cancel sections%> inside "
2369 "%<nowait%> sections construct");
2372 kind = "sections";
2373 break;
2374 case 8:
2375 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2376 bad = "#pragma omp task";
2377 else
2378 ctx->cancellable = true;
2379 kind = "taskgroup";
2380 break;
2381 default:
2382 error_at (gimple_location (stmt), "invalid arguments");
2383 return false;
2385 if (bad)
2387 error_at (gimple_location (stmt),
2388 "%<%s %s%> construct not closely nested inside of %qs",
2389 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2390 == BUILT_IN_GOMP_CANCEL
2391 ? "#pragma omp cancel"
2392 : "#pragma omp cancellation point", kind, bad);
2393 return false;
2396 /* FALLTHRU */
2397 case GIMPLE_OMP_SECTIONS:
2398 case GIMPLE_OMP_SINGLE:
2399 for (; ctx != NULL; ctx = ctx->outer)
2400 switch (gimple_code (ctx->stmt))
2402 case GIMPLE_OMP_FOR:
2403 case GIMPLE_OMP_SECTIONS:
2404 case GIMPLE_OMP_SINGLE:
2405 case GIMPLE_OMP_ORDERED:
2406 case GIMPLE_OMP_MASTER:
2407 case GIMPLE_OMP_TASK:
2408 case GIMPLE_OMP_CRITICAL:
2409 if (is_gimple_call (stmt))
2411 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2412 != BUILT_IN_GOMP_BARRIER)
2413 return true;
2414 error_at (gimple_location (stmt),
2415 "barrier region may not be closely nested inside "
2416 "of work-sharing, critical, ordered, master or "
2417 "explicit task region");
2418 return false;
2420 error_at (gimple_location (stmt),
2421 "work-sharing region may not be closely nested inside "
2422 "of work-sharing, critical, ordered, master or explicit "
2423 "task region");
2424 return false;
2425 case GIMPLE_OMP_PARALLEL:
2426 return true;
2427 default:
2428 break;
2430 break;
2431 case GIMPLE_OMP_MASTER:
2432 for (; ctx != NULL; ctx = ctx->outer)
2433 switch (gimple_code (ctx->stmt))
2435 case GIMPLE_OMP_FOR:
2436 case GIMPLE_OMP_SECTIONS:
2437 case GIMPLE_OMP_SINGLE:
2438 case GIMPLE_OMP_TASK:
2439 error_at (gimple_location (stmt),
2440 "master region may not be closely nested inside "
2441 "of work-sharing or explicit task region");
2442 return false;
2443 case GIMPLE_OMP_PARALLEL:
2444 return true;
2445 default:
2446 break;
2448 break;
2449 case GIMPLE_OMP_ORDERED:
2450 for (; ctx != NULL; ctx = ctx->outer)
2451 switch (gimple_code (ctx->stmt))
2453 case GIMPLE_OMP_CRITICAL:
2454 case GIMPLE_OMP_TASK:
2455 error_at (gimple_location (stmt),
2456 "ordered region may not be closely nested inside "
2457 "of critical or explicit task region");
2458 return false;
2459 case GIMPLE_OMP_FOR:
2460 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2461 OMP_CLAUSE_ORDERED) == NULL)
2463 error_at (gimple_location (stmt),
2464 "ordered region must be closely nested inside "
2465 "a loop region with an ordered clause");
2466 return false;
2468 return true;
2469 case GIMPLE_OMP_PARALLEL:
2470 error_at (gimple_location (stmt),
2471 "ordered region must be closely nested inside "
2472 "a loop region with an ordered clause");
2473 return false;
2474 default:
2475 break;
2477 break;
2478 case GIMPLE_OMP_CRITICAL:
2479 for (; ctx != NULL; ctx = ctx->outer)
2480 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2481 && (gimple_omp_critical_name (stmt)
2482 == gimple_omp_critical_name (ctx->stmt)))
2484 error_at (gimple_location (stmt),
2485 "critical region may not be nested inside a critical "
2486 "region with the same name");
2487 return false;
2489 break;
2490 case GIMPLE_OMP_TEAMS:
2491 if (ctx == NULL
2492 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2493 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2495 error_at (gimple_location (stmt),
2496 "teams construct not closely nested inside of target "
2497 "region");
2498 return false;
2500 break;
2501 default:
2502 break;
2504 return true;
2508 /* Helper function scan_omp.
2510 Callback for walk_tree or operators in walk_gimple_stmt used to
2511 scan for OpenMP directives in TP. */
2513 static tree
2514 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2516 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2517 omp_context *ctx = (omp_context *) wi->info;
2518 tree t = *tp;
2520 switch (TREE_CODE (t))
2522 case VAR_DECL:
2523 case PARM_DECL:
2524 case LABEL_DECL:
2525 case RESULT_DECL:
2526 if (ctx)
2527 *tp = remap_decl (t, &ctx->cb);
2528 break;
2530 default:
2531 if (ctx && TYPE_P (t))
2532 *tp = remap_type (t, &ctx->cb);
2533 else if (!DECL_P (t))
2535 *walk_subtrees = 1;
2536 if (ctx)
2538 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2539 if (tem != TREE_TYPE (t))
2541 if (TREE_CODE (t) == INTEGER_CST)
2542 *tp = build_int_cst_wide (tem,
2543 TREE_INT_CST_LOW (t),
2544 TREE_INT_CST_HIGH (t));
2545 else
2546 TREE_TYPE (t) = tem;
2550 break;
2553 return NULL_TREE;
2556 /* Return true if FNDECL is a setjmp or a longjmp. */
2558 static bool
2559 setjmp_or_longjmp_p (const_tree fndecl)
2561 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2562 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2563 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2564 return true;
2566 tree declname = DECL_NAME (fndecl);
2567 if (!declname)
2568 return false;
2569 const char *name = IDENTIFIER_POINTER (declname);
2570 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2574 /* Helper function for scan_omp.
2576 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2577 the current statement in GSI. */
2579 static tree
2580 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2581 struct walk_stmt_info *wi)
2583 gimple stmt = gsi_stmt (*gsi);
2584 omp_context *ctx = (omp_context *) wi->info;
2586 if (gimple_has_location (stmt))
2587 input_location = gimple_location (stmt);
2589 /* Check the OpenMP nesting restrictions. */
2590 bool remove = false;
2591 if (is_gimple_omp (stmt))
2592 remove = !check_omp_nesting_restrictions (stmt, ctx);
2593 else if (is_gimple_call (stmt))
2595 tree fndecl = gimple_call_fndecl (stmt);
2596 if (fndecl)
2598 if (setjmp_or_longjmp_p (fndecl)
2599 && ctx
2600 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2601 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2603 remove = true;
2604 error_at (gimple_location (stmt),
2605 "setjmp/longjmp inside simd construct");
2607 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2608 switch (DECL_FUNCTION_CODE (fndecl))
2610 case BUILT_IN_GOMP_BARRIER:
2611 case BUILT_IN_GOMP_CANCEL:
2612 case BUILT_IN_GOMP_CANCELLATION_POINT:
2613 case BUILT_IN_GOMP_TASKYIELD:
2614 case BUILT_IN_GOMP_TASKWAIT:
2615 case BUILT_IN_GOMP_TASKGROUP_START:
2616 case BUILT_IN_GOMP_TASKGROUP_END:
2617 remove = !check_omp_nesting_restrictions (stmt, ctx);
2618 break;
2619 default:
2620 break;
2624 if (remove)
2626 stmt = gimple_build_nop ();
2627 gsi_replace (gsi, stmt, false);
2630 *handled_ops_p = true;
2632 switch (gimple_code (stmt))
2634 case GIMPLE_OMP_PARALLEL:
2635 taskreg_nesting_level++;
2636 scan_omp_parallel (gsi, ctx);
2637 taskreg_nesting_level--;
2638 break;
2640 case GIMPLE_OMP_TASK:
2641 taskreg_nesting_level++;
2642 scan_omp_task (gsi, ctx);
2643 taskreg_nesting_level--;
2644 break;
2646 case GIMPLE_OMP_FOR:
2647 scan_omp_for (stmt, ctx);
2648 break;
2650 case GIMPLE_OMP_SECTIONS:
2651 scan_omp_sections (stmt, ctx);
2652 break;
2654 case GIMPLE_OMP_SINGLE:
2655 scan_omp_single (stmt, ctx);
2656 break;
2658 case GIMPLE_OMP_SECTION:
2659 case GIMPLE_OMP_MASTER:
2660 case GIMPLE_OMP_TASKGROUP:
2661 case GIMPLE_OMP_ORDERED:
2662 case GIMPLE_OMP_CRITICAL:
2663 ctx = new_omp_context (stmt, ctx);
2664 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2665 break;
2667 case GIMPLE_OMP_TARGET:
2668 scan_omp_target (stmt, ctx);
2669 break;
2671 case GIMPLE_OMP_TEAMS:
2672 scan_omp_teams (stmt, ctx);
2673 break;
2675 case GIMPLE_BIND:
2677 tree var;
2679 *handled_ops_p = false;
2680 if (ctx)
2681 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2682 insert_decl_map (&ctx->cb, var, var);
2684 break;
2685 default:
2686 *handled_ops_p = false;
2687 break;
2690 return NULL_TREE;
2694 /* Scan all the statements starting at the current statement. CTX
2695 contains context information about the OpenMP directives and
2696 clauses found during the scan. */
2698 static void
2699 scan_omp (gimple_seq *body_p, omp_context *ctx)
2701 location_t saved_location;
2702 struct walk_stmt_info wi;
2704 memset (&wi, 0, sizeof (wi));
2705 wi.info = ctx;
2706 wi.want_locations = true;
2708 saved_location = input_location;
2709 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2710 input_location = saved_location;
2713 /* Re-gimplification and code generation routines. */
2715 /* Build a call to GOMP_barrier. */
2717 static gimple
2718 build_omp_barrier (tree lhs)
2720 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2721 : BUILT_IN_GOMP_BARRIER);
2722 gimple g = gimple_build_call (fndecl, 0);
2723 if (lhs)
2724 gimple_call_set_lhs (g, lhs);
2725 return g;
2728 /* If a context was created for STMT when it was scanned, return it. */
2730 static omp_context *
2731 maybe_lookup_ctx (gimple stmt)
2733 splay_tree_node n;
2734 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2735 return n ? (omp_context *) n->value : NULL;
2739 /* Find the mapping for DECL in CTX or the immediately enclosing
2740 context that has a mapping for DECL.
2742 If CTX is a nested parallel directive, we may have to use the decl
2743 mappings created in CTX's parent context. Suppose that we have the
2744 following parallel nesting (variable UIDs showed for clarity):
2746 iD.1562 = 0;
2747 #omp parallel shared(iD.1562) -> outer parallel
2748 iD.1562 = iD.1562 + 1;
2750 #omp parallel shared (iD.1562) -> inner parallel
2751 iD.1562 = iD.1562 - 1;
2753 Each parallel structure will create a distinct .omp_data_s structure
2754 for copying iD.1562 in/out of the directive:
2756 outer parallel .omp_data_s.1.i -> iD.1562
2757 inner parallel .omp_data_s.2.i -> iD.1562
2759 A shared variable mapping will produce a copy-out operation before
2760 the parallel directive and a copy-in operation after it. So, in
2761 this case we would have:
2763 iD.1562 = 0;
2764 .omp_data_o.1.i = iD.1562;
2765 #omp parallel shared(iD.1562) -> outer parallel
2766 .omp_data_i.1 = &.omp_data_o.1
2767 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2769 .omp_data_o.2.i = iD.1562; -> **
2770 #omp parallel shared(iD.1562) -> inner parallel
2771 .omp_data_i.2 = &.omp_data_o.2
2772 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2775 ** This is a problem. The symbol iD.1562 cannot be referenced
2776 inside the body of the outer parallel region. But since we are
2777 emitting this copy operation while expanding the inner parallel
2778 directive, we need to access the CTX structure of the outer
2779 parallel directive to get the correct mapping:
2781 .omp_data_o.2.i = .omp_data_i.1->i
2783 Since there may be other workshare or parallel directives enclosing
2784 the parallel directive, it may be necessary to walk up the context
2785 parent chain. This is not a problem in general because nested
2786 parallelism happens only rarely. */
2788 static tree
2789 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2791 tree t;
2792 omp_context *up;
2794 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2795 t = maybe_lookup_decl (decl, up);
2797 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2799 return t ? t : decl;
2803 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2804 in outer contexts. */
2806 static tree
2807 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2809 tree t = NULL;
2810 omp_context *up;
2812 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2813 t = maybe_lookup_decl (decl, up);
2815 return t ? t : decl;
2819 /* Construct the initialization value for reduction CLAUSE. */
2821 tree
2822 omp_reduction_init (tree clause, tree type)
2824 location_t loc = OMP_CLAUSE_LOCATION (clause);
2825 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2827 case PLUS_EXPR:
2828 case MINUS_EXPR:
2829 case BIT_IOR_EXPR:
2830 case BIT_XOR_EXPR:
2831 case TRUTH_OR_EXPR:
2832 case TRUTH_ORIF_EXPR:
2833 case TRUTH_XOR_EXPR:
2834 case NE_EXPR:
2835 return build_zero_cst (type);
2837 case MULT_EXPR:
2838 case TRUTH_AND_EXPR:
2839 case TRUTH_ANDIF_EXPR:
2840 case EQ_EXPR:
2841 return fold_convert_loc (loc, type, integer_one_node);
2843 case BIT_AND_EXPR:
2844 return fold_convert_loc (loc, type, integer_minus_one_node);
2846 case MAX_EXPR:
2847 if (SCALAR_FLOAT_TYPE_P (type))
2849 REAL_VALUE_TYPE max, min;
2850 if (HONOR_INFINITIES (TYPE_MODE (type)))
2852 real_inf (&max);
2853 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2855 else
2856 real_maxval (&min, 1, TYPE_MODE (type));
2857 return build_real (type, min);
2859 else
2861 gcc_assert (INTEGRAL_TYPE_P (type));
2862 return TYPE_MIN_VALUE (type);
2865 case MIN_EXPR:
2866 if (SCALAR_FLOAT_TYPE_P (type))
2868 REAL_VALUE_TYPE max;
2869 if (HONOR_INFINITIES (TYPE_MODE (type)))
2870 real_inf (&max);
2871 else
2872 real_maxval (&max, 0, TYPE_MODE (type));
2873 return build_real (type, max);
2875 else
2877 gcc_assert (INTEGRAL_TYPE_P (type));
2878 return TYPE_MAX_VALUE (type);
2881 default:
2882 gcc_unreachable ();
2886 /* Return alignment to be assumed for var in CLAUSE, which should be
2887 OMP_CLAUSE_ALIGNED. */
2889 static tree
2890 omp_clause_aligned_alignment (tree clause)
2892 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
2893 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
2895 /* Otherwise return implementation defined alignment. */
2896 unsigned int al = 1;
2897 enum machine_mode mode, vmode;
2898 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2899 if (vs)
2900 vs = 1 << floor_log2 (vs);
2901 static enum mode_class classes[]
2902 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
2903 for (int i = 0; i < 4; i += 2)
2904 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
2905 mode != VOIDmode;
2906 mode = GET_MODE_WIDER_MODE (mode))
2908 vmode = targetm.vectorize.preferred_simd_mode (mode);
2909 if (GET_MODE_CLASS (vmode) != classes[i + 1])
2910 continue;
2911 while (vs
2912 && GET_MODE_SIZE (vmode) < vs
2913 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
2914 vmode = GET_MODE_2XWIDER_MODE (vmode);
2916 tree type = lang_hooks.types.type_for_mode (mode, 1);
2917 if (type == NULL_TREE || TYPE_MODE (type) != mode)
2918 continue;
2919 type = build_vector_type (type, GET_MODE_SIZE (vmode)
2920 / GET_MODE_SIZE (mode));
2921 if (TYPE_MODE (type) != vmode)
2922 continue;
2923 if (TYPE_ALIGN_UNIT (type) > al)
2924 al = TYPE_ALIGN_UNIT (type);
2926 return build_int_cst (integer_type_node, al);
2929 /* Return maximum possible vectorization factor for the target. */
2931 static int
2932 omp_max_vf (void)
2934 if (!optimize
2935 || optimize_debug
2936 || (!flag_tree_loop_vectorize
2937 && (global_options_set.x_flag_tree_loop_vectorize
2938 || global_options_set.x_flag_tree_vectorize)))
2939 return 1;
2941 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2942 if (vs)
2944 vs = 1 << floor_log2 (vs);
2945 return vs;
2947 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
2948 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
2949 return GET_MODE_NUNITS (vqimode);
2950 return 1;
2953 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2954 privatization. */
2956 static bool
2957 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
2958 tree &idx, tree &lane, tree &ivar, tree &lvar)
2960 if (max_vf == 0)
2962 max_vf = omp_max_vf ();
2963 if (max_vf > 1)
2965 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2966 OMP_CLAUSE_SAFELEN);
2967 if (c
2968 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
2969 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
2971 if (max_vf > 1)
2973 idx = create_tmp_var (unsigned_type_node, NULL);
2974 lane = create_tmp_var (unsigned_type_node, NULL);
2977 if (max_vf == 1)
2978 return false;
2980 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
2981 tree avar = create_tmp_var_raw (atype, NULL);
2982 if (TREE_ADDRESSABLE (new_var))
2983 TREE_ADDRESSABLE (avar) = 1;
2984 DECL_ATTRIBUTES (avar)
2985 = tree_cons (get_identifier ("omp simd array"), NULL,
2986 DECL_ATTRIBUTES (avar));
2987 gimple_add_tmp_var (avar);
2988 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
2989 NULL_TREE, NULL_TREE);
2990 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
2991 NULL_TREE, NULL_TREE);
2992 if (DECL_P (new_var))
2994 SET_DECL_VALUE_EXPR (new_var, lvar);
2995 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2997 return true;
3000 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3001 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3002 private variables. Initialization statements go in ILIST, while calls
3003 to destructors go in DLIST. */
3005 static void
3006 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3007 omp_context *ctx, struct omp_for_data *fd)
3009 tree c, dtor, copyin_seq, x, ptr;
3010 bool copyin_by_ref = false;
3011 bool lastprivate_firstprivate = false;
3012 bool reduction_omp_orig_ref = false;
3013 int pass;
3014 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3015 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD);
3016 int max_vf = 0;
3017 tree lane = NULL_TREE, idx = NULL_TREE;
3018 tree ivar = NULL_TREE, lvar = NULL_TREE;
3019 gimple_seq llist[2] = { NULL, NULL };
3021 copyin_seq = NULL;
3023 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3024 with data sharing clauses referencing variable sized vars. That
3025 is unnecessarily hard to support and very unlikely to result in
3026 vectorized code anyway. */
3027 if (is_simd)
3028 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3029 switch (OMP_CLAUSE_CODE (c))
3031 case OMP_CLAUSE_REDUCTION:
3032 case OMP_CLAUSE_PRIVATE:
3033 case OMP_CLAUSE_FIRSTPRIVATE:
3034 case OMP_CLAUSE_LASTPRIVATE:
3035 case OMP_CLAUSE_LINEAR:
3036 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3037 max_vf = 1;
3038 break;
3039 default:
3040 continue;
3043 /* Do all the fixed sized types in the first pass, and the variable sized
3044 types in the second pass. This makes sure that the scalar arguments to
3045 the variable sized types are processed before we use them in the
3046 variable sized operations. */
3047 for (pass = 0; pass < 2; ++pass)
3049 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3051 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3052 tree var, new_var;
3053 bool by_ref;
3054 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3056 switch (c_kind)
3058 case OMP_CLAUSE_PRIVATE:
3059 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3060 continue;
3061 break;
3062 case OMP_CLAUSE_SHARED:
3063 /* Ignore shared directives in teams construct. */
3064 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3065 continue;
3066 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3068 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3069 continue;
3071 case OMP_CLAUSE_FIRSTPRIVATE:
3072 case OMP_CLAUSE_COPYIN:
3073 case OMP_CLAUSE_LINEAR:
3074 break;
3075 case OMP_CLAUSE_REDUCTION:
3076 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3077 reduction_omp_orig_ref = true;
3078 break;
3079 case OMP_CLAUSE__LOOPTEMP_:
3080 /* Handle _looptemp_ clauses only on parallel. */
3081 if (fd)
3082 continue;
3083 break;
3084 case OMP_CLAUSE_LASTPRIVATE:
3085 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3087 lastprivate_firstprivate = true;
3088 if (pass != 0)
3089 continue;
3091 break;
3092 case OMP_CLAUSE_ALIGNED:
3093 if (pass == 0)
3094 continue;
3095 var = OMP_CLAUSE_DECL (c);
3096 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3097 && !is_global_var (var))
3099 new_var = maybe_lookup_decl (var, ctx);
3100 if (new_var == NULL_TREE)
3101 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3102 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3103 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3104 omp_clause_aligned_alignment (c));
3105 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3106 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3107 gimplify_and_add (x, ilist);
3109 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3110 && is_global_var (var))
3112 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3113 new_var = lookup_decl (var, ctx);
3114 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3115 t = build_fold_addr_expr_loc (clause_loc, t);
3116 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3117 t = build_call_expr_loc (clause_loc, t2, 2, t,
3118 omp_clause_aligned_alignment (c));
3119 t = fold_convert_loc (clause_loc, ptype, t);
3120 x = create_tmp_var (ptype, NULL);
3121 t = build2 (MODIFY_EXPR, ptype, x, t);
3122 gimplify_and_add (t, ilist);
3123 t = build_simple_mem_ref_loc (clause_loc, x);
3124 SET_DECL_VALUE_EXPR (new_var, t);
3125 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3127 continue;
3128 default:
3129 continue;
3132 new_var = var = OMP_CLAUSE_DECL (c);
3133 if (c_kind != OMP_CLAUSE_COPYIN)
3134 new_var = lookup_decl (var, ctx);
3136 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3138 if (pass != 0)
3139 continue;
3141 else if (is_variable_sized (var))
3143 /* For variable sized types, we need to allocate the
3144 actual storage here. Call alloca and store the
3145 result in the pointer decl that we created elsewhere. */
3146 if (pass == 0)
3147 continue;
3149 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3151 gimple stmt;
3152 tree tmp, atmp;
3154 ptr = DECL_VALUE_EXPR (new_var);
3155 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3156 ptr = TREE_OPERAND (ptr, 0);
3157 gcc_assert (DECL_P (ptr));
3158 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3160 /* void *tmp = __builtin_alloca */
3161 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3162 stmt = gimple_build_call (atmp, 1, x);
3163 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3164 gimple_add_tmp_var (tmp);
3165 gimple_call_set_lhs (stmt, tmp);
3167 gimple_seq_add_stmt (ilist, stmt);
3169 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3170 gimplify_assign (ptr, x, ilist);
3173 else if (is_reference (var))
3175 /* For references that are being privatized for Fortran,
3176 allocate new backing storage for the new pointer
3177 variable. This allows us to avoid changing all the
3178 code that expects a pointer to something that expects
3179 a direct variable. */
3180 if (pass == 0)
3181 continue;
3183 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3184 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3186 x = build_receiver_ref (var, false, ctx);
3187 x = build_fold_addr_expr_loc (clause_loc, x);
3189 else if (TREE_CONSTANT (x))
3191 /* For reduction with placeholder in SIMD loop,
3192 defer adding the initialization of the reference,
3193 because if we decide to use SIMD array for it,
3194 the initilization could cause expansion ICE. */
3195 if (c_kind == OMP_CLAUSE_REDUCTION
3196 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
3197 && is_simd)
3198 x = NULL_TREE;
3199 else
3201 const char *name = NULL;
3202 if (DECL_NAME (var))
3203 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3205 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3206 name);
3207 gimple_add_tmp_var (x);
3208 TREE_ADDRESSABLE (x) = 1;
3209 x = build_fold_addr_expr_loc (clause_loc, x);
3212 else
3214 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3215 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3218 if (x)
3220 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3221 gimplify_assign (new_var, x, ilist);
3224 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3226 else if (c_kind == OMP_CLAUSE_REDUCTION
3227 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3229 if (pass == 0)
3230 continue;
3232 else if (pass != 0)
3233 continue;
3235 switch (OMP_CLAUSE_CODE (c))
3237 case OMP_CLAUSE_SHARED:
3238 /* Ignore shared directives in teams construct. */
3239 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3240 continue;
3241 /* Shared global vars are just accessed directly. */
3242 if (is_global_var (new_var))
3243 break;
3244 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3245 needs to be delayed until after fixup_child_record_type so
3246 that we get the correct type during the dereference. */
3247 by_ref = use_pointer_for_field (var, ctx);
3248 x = build_receiver_ref (var, by_ref, ctx);
3249 SET_DECL_VALUE_EXPR (new_var, x);
3250 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3252 /* ??? If VAR is not passed by reference, and the variable
3253 hasn't been initialized yet, then we'll get a warning for
3254 the store into the omp_data_s structure. Ideally, we'd be
3255 able to notice this and not store anything at all, but
3256 we're generating code too early. Suppress the warning. */
3257 if (!by_ref)
3258 TREE_NO_WARNING (var) = 1;
3259 break;
3261 case OMP_CLAUSE_LASTPRIVATE:
3262 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3263 break;
3264 /* FALLTHRU */
3266 case OMP_CLAUSE_PRIVATE:
3267 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3268 x = build_outer_var_ref (var, ctx);
3269 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3271 if (is_task_ctx (ctx))
3272 x = build_receiver_ref (var, false, ctx);
3273 else
3274 x = build_outer_var_ref (var, ctx);
3276 else
3277 x = NULL;
3278 do_private:
3279 tree nx;
3280 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3281 if (is_simd)
3283 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3284 if ((TREE_ADDRESSABLE (new_var) || nx || y
3285 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3286 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3287 idx, lane, ivar, lvar))
3289 if (nx)
3290 x = lang_hooks.decls.omp_clause_default_ctor
3291 (c, unshare_expr (ivar), x);
3292 if (nx && x)
3293 gimplify_and_add (x, &llist[0]);
3294 if (y)
3296 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3297 if (y)
3299 gimple_seq tseq = NULL;
3301 dtor = y;
3302 gimplify_stmt (&dtor, &tseq);
3303 gimple_seq_add_seq (&llist[1], tseq);
3306 break;
3309 if (nx)
3310 gimplify_and_add (nx, ilist);
3311 /* FALLTHRU */
3313 do_dtor:
3314 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3315 if (x)
3317 gimple_seq tseq = NULL;
3319 dtor = x;
3320 gimplify_stmt (&dtor, &tseq);
3321 gimple_seq_add_seq (dlist, tseq);
3323 break;
3325 case OMP_CLAUSE_LINEAR:
3326 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3327 goto do_firstprivate;
3328 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3329 x = NULL;
3330 else
3331 x = build_outer_var_ref (var, ctx);
3332 goto do_private;
3334 case OMP_CLAUSE_FIRSTPRIVATE:
3335 if (is_task_ctx (ctx))
3337 if (is_reference (var) || is_variable_sized (var))
3338 goto do_dtor;
3339 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3340 ctx))
3341 || use_pointer_for_field (var, NULL))
3343 x = build_receiver_ref (var, false, ctx);
3344 SET_DECL_VALUE_EXPR (new_var, x);
3345 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3346 goto do_dtor;
3349 do_firstprivate:
3350 x = build_outer_var_ref (var, ctx);
3351 if (is_simd)
3353 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3354 && gimple_omp_for_combined_into_p (ctx->stmt))
3356 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3357 ? sizetype : TREE_TYPE (x);
3358 tree t = fold_convert (stept,
3359 OMP_CLAUSE_LINEAR_STEP (c));
3360 tree c = find_omp_clause (clauses,
3361 OMP_CLAUSE__LOOPTEMP_);
3362 gcc_assert (c);
3363 tree l = OMP_CLAUSE_DECL (c);
3364 if (fd->collapse == 1)
3366 tree n1 = fd->loop.n1;
3367 tree step = fd->loop.step;
3368 tree itype = TREE_TYPE (l);
3369 if (POINTER_TYPE_P (itype))
3370 itype = signed_type_for (itype);
3371 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3372 if (TYPE_UNSIGNED (itype)
3373 && fd->loop.cond_code == GT_EXPR)
3374 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3375 fold_build1 (NEGATE_EXPR,
3376 itype, l),
3377 fold_build1 (NEGATE_EXPR,
3378 itype, step));
3379 else
3380 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3382 t = fold_build2 (MULT_EXPR, stept,
3383 fold_convert (stept, l), t);
3384 if (POINTER_TYPE_P (TREE_TYPE (x)))
3385 x = fold_build2 (POINTER_PLUS_EXPR,
3386 TREE_TYPE (x), x, t);
3387 else
3388 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3391 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3392 || TREE_ADDRESSABLE (new_var))
3393 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3394 idx, lane, ivar, lvar))
3396 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3398 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3399 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3400 gimplify_and_add (x, ilist);
3401 gimple_stmt_iterator gsi
3402 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3403 gimple g
3404 = gimple_build_assign (unshare_expr (lvar), iv);
3405 gsi_insert_before_without_update (&gsi, g,
3406 GSI_SAME_STMT);
3407 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3408 ? sizetype : TREE_TYPE (x);
3409 tree t = fold_convert (stept,
3410 OMP_CLAUSE_LINEAR_STEP (c));
3411 enum tree_code code = PLUS_EXPR;
3412 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3413 code = POINTER_PLUS_EXPR;
3414 g = gimple_build_assign_with_ops (code, iv, iv, t);
3415 gsi_insert_before_without_update (&gsi, g,
3416 GSI_SAME_STMT);
3417 break;
3419 x = lang_hooks.decls.omp_clause_copy_ctor
3420 (c, unshare_expr (ivar), x);
3421 gimplify_and_add (x, &llist[0]);
3422 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3423 if (x)
3425 gimple_seq tseq = NULL;
3427 dtor = x;
3428 gimplify_stmt (&dtor, &tseq);
3429 gimple_seq_add_seq (&llist[1], tseq);
3431 break;
3434 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3435 gimplify_and_add (x, ilist);
3436 goto do_dtor;
3438 case OMP_CLAUSE__LOOPTEMP_:
3439 gcc_assert (is_parallel_ctx (ctx));
3440 x = build_outer_var_ref (var, ctx);
3441 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3442 gimplify_and_add (x, ilist);
3443 break;
3445 case OMP_CLAUSE_COPYIN:
3446 by_ref = use_pointer_for_field (var, NULL);
3447 x = build_receiver_ref (var, by_ref, ctx);
3448 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3449 append_to_statement_list (x, &copyin_seq);
3450 copyin_by_ref |= by_ref;
3451 break;
3453 case OMP_CLAUSE_REDUCTION:
3454 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3456 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3457 gimple tseq;
3458 x = build_outer_var_ref (var, ctx);
3460 if (is_reference (var)
3461 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3462 TREE_TYPE (x)))
3463 x = build_fold_addr_expr_loc (clause_loc, x);
3464 SET_DECL_VALUE_EXPR (placeholder, x);
3465 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3466 tree new_vard = new_var;
3467 if (is_reference (var))
3469 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3470 new_vard = TREE_OPERAND (new_var, 0);
3471 gcc_assert (DECL_P (new_vard));
3473 if (is_simd
3474 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3475 idx, lane, ivar, lvar))
3477 if (new_vard == new_var)
3479 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3480 SET_DECL_VALUE_EXPR (new_var, ivar);
3482 else
3484 SET_DECL_VALUE_EXPR (new_vard,
3485 build_fold_addr_expr (ivar));
3486 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3488 x = lang_hooks.decls.omp_clause_default_ctor
3489 (c, unshare_expr (ivar),
3490 build_outer_var_ref (var, ctx));
3491 if (x)
3492 gimplify_and_add (x, &llist[0]);
3493 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3495 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3496 lower_omp (&tseq, ctx);
3497 gimple_seq_add_seq (&llist[0], tseq);
3499 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3500 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3501 lower_omp (&tseq, ctx);
3502 gimple_seq_add_seq (&llist[1], tseq);
3503 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3504 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3505 if (new_vard == new_var)
3506 SET_DECL_VALUE_EXPR (new_var, lvar);
3507 else
3508 SET_DECL_VALUE_EXPR (new_vard,
3509 build_fold_addr_expr (lvar));
3510 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3511 if (x)
3513 tseq = NULL;
3514 dtor = x;
3515 gimplify_stmt (&dtor, &tseq);
3516 gimple_seq_add_seq (&llist[1], tseq);
3518 break;
3520 /* If this is a reference to constant size reduction var
3521 with placeholder, we haven't emitted the initializer
3522 for it because it is undesirable if SIMD arrays are used.
3523 But if they aren't used, we need to emit the deferred
3524 initialization now. */
3525 else if (is_reference (var) && is_simd)
3527 tree z
3528 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3529 if (TREE_CONSTANT (z))
3531 const char *name = NULL;
3532 if (DECL_NAME (var))
3533 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3535 z = create_tmp_var_raw
3536 (TREE_TYPE (TREE_TYPE (new_vard)), name);
3537 gimple_add_tmp_var (z);
3538 TREE_ADDRESSABLE (z) = 1;
3539 z = build_fold_addr_expr_loc (clause_loc, z);
3540 gimplify_assign (new_vard, z, ilist);
3543 x = lang_hooks.decls.omp_clause_default_ctor
3544 (c, new_var, unshare_expr (x));
3545 if (x)
3546 gimplify_and_add (x, ilist);
3547 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3549 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3550 lower_omp (&tseq, ctx);
3551 gimple_seq_add_seq (ilist, tseq);
3553 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3554 if (is_simd)
3556 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3557 lower_omp (&tseq, ctx);
3558 gimple_seq_add_seq (dlist, tseq);
3559 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3561 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3562 goto do_dtor;
3564 else
3566 x = omp_reduction_init (c, TREE_TYPE (new_var));
3567 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3568 if (is_simd
3569 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3570 idx, lane, ivar, lvar))
3572 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3573 tree ref = build_outer_var_ref (var, ctx);
3575 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3577 /* reduction(-:var) sums up the partial results, so it
3578 acts identically to reduction(+:var). */
3579 if (code == MINUS_EXPR)
3580 code = PLUS_EXPR;
3582 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3583 ref = build_outer_var_ref (var, ctx);
3584 gimplify_assign (ref, x, &llist[1]);
3586 else
3588 gimplify_assign (new_var, x, ilist);
3589 if (is_simd)
3590 gimplify_assign (build_outer_var_ref (var, ctx),
3591 new_var, dlist);
3594 break;
3596 default:
3597 gcc_unreachable ();
3602 if (lane)
3604 tree uid = create_tmp_var (ptr_type_node, "simduid");
3605 /* Don't want uninit warnings on simduid, it is always uninitialized,
3606 but we use it not for the value, but for the DECL_UID only. */
3607 TREE_NO_WARNING (uid) = 1;
3608 gimple g
3609 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3610 gimple_call_set_lhs (g, lane);
3611 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3612 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3613 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3614 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3615 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3616 gimple_omp_for_set_clauses (ctx->stmt, c);
3617 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3618 build_int_cst (unsigned_type_node, 0),
3619 NULL_TREE);
3620 gimple_seq_add_stmt (ilist, g);
3621 for (int i = 0; i < 2; i++)
3622 if (llist[i])
3624 tree vf = create_tmp_var (unsigned_type_node, NULL);
3625 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3626 gimple_call_set_lhs (g, vf);
3627 gimple_seq *seq = i == 0 ? ilist : dlist;
3628 gimple_seq_add_stmt (seq, g);
3629 tree t = build_int_cst (unsigned_type_node, 0);
3630 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3631 gimple_seq_add_stmt (seq, g);
3632 tree body = create_artificial_label (UNKNOWN_LOCATION);
3633 tree header = create_artificial_label (UNKNOWN_LOCATION);
3634 tree end = create_artificial_label (UNKNOWN_LOCATION);
3635 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3636 gimple_seq_add_stmt (seq, gimple_build_label (body));
3637 gimple_seq_add_seq (seq, llist[i]);
3638 t = build_int_cst (unsigned_type_node, 1);
3639 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3640 gimple_seq_add_stmt (seq, g);
3641 gimple_seq_add_stmt (seq, gimple_build_label (header));
3642 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3643 gimple_seq_add_stmt (seq, g);
3644 gimple_seq_add_stmt (seq, gimple_build_label (end));
3648 /* The copyin sequence is not to be executed by the main thread, since
3649 that would result in self-copies. Perhaps not visible to scalars,
3650 but it certainly is to C++ operator=. */
3651 if (copyin_seq)
3653 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3655 x = build2 (NE_EXPR, boolean_type_node, x,
3656 build_int_cst (TREE_TYPE (x), 0));
3657 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3658 gimplify_and_add (x, ilist);
3661 /* If any copyin variable is passed by reference, we must ensure the
3662 master thread doesn't modify it before it is copied over in all
3663 threads. Similarly for variables in both firstprivate and
3664 lastprivate clauses we need to ensure the lastprivate copying
3665 happens after firstprivate copying in all threads. And similarly
3666 for UDRs if initializer expression refers to omp_orig. */
3667 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3669 /* Don't add any barrier for #pragma omp simd or
3670 #pragma omp distribute. */
3671 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3672 || gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_FOR)
3673 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3676 /* If max_vf is non-zero, then we can use only a vectorization factor
3677 up to the max_vf we chose. So stick it into the safelen clause. */
3678 if (max_vf)
3680 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3681 OMP_CLAUSE_SAFELEN);
3682 if (c == NULL_TREE
3683 || compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3684 max_vf) == 1)
3686 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3687 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3688 max_vf);
3689 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3690 gimple_omp_for_set_clauses (ctx->stmt, c);
3696 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3697 both parallel and workshare constructs. PREDICATE may be NULL if it's
3698 always true. */
3700 static void
3701 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3702 omp_context *ctx)
3704 tree x, c, label = NULL, orig_clauses = clauses;
3705 bool par_clauses = false;
3706 tree simduid = NULL, lastlane = NULL;
3708 /* Early exit if there are no lastprivate or linear clauses. */
3709 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3710 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3711 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3712 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3713 break;
3714 if (clauses == NULL)
3716 /* If this was a workshare clause, see if it had been combined
3717 with its parallel. In that case, look for the clauses on the
3718 parallel statement itself. */
3719 if (is_parallel_ctx (ctx))
3720 return;
3722 ctx = ctx->outer;
3723 if (ctx == NULL || !is_parallel_ctx (ctx))
3724 return;
3726 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3727 OMP_CLAUSE_LASTPRIVATE);
3728 if (clauses == NULL)
3729 return;
3730 par_clauses = true;
3733 if (predicate)
3735 gimple stmt;
3736 tree label_true, arm1, arm2;
3738 label = create_artificial_label (UNKNOWN_LOCATION);
3739 label_true = create_artificial_label (UNKNOWN_LOCATION);
3740 arm1 = TREE_OPERAND (predicate, 0);
3741 arm2 = TREE_OPERAND (predicate, 1);
3742 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3743 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3744 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3745 label_true, label);
3746 gimple_seq_add_stmt (stmt_list, stmt);
3747 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3750 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3751 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
3753 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3754 if (simduid)
3755 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3758 for (c = clauses; c ;)
3760 tree var, new_var;
3761 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3763 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3764 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3765 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3767 var = OMP_CLAUSE_DECL (c);
3768 new_var = lookup_decl (var, ctx);
3770 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3772 tree val = DECL_VALUE_EXPR (new_var);
3773 if (TREE_CODE (val) == ARRAY_REF
3774 && VAR_P (TREE_OPERAND (val, 0))
3775 && lookup_attribute ("omp simd array",
3776 DECL_ATTRIBUTES (TREE_OPERAND (val,
3777 0))))
3779 if (lastlane == NULL)
3781 lastlane = create_tmp_var (unsigned_type_node, NULL);
3782 gimple g
3783 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
3784 2, simduid,
3785 TREE_OPERAND (val, 1));
3786 gimple_call_set_lhs (g, lastlane);
3787 gimple_seq_add_stmt (stmt_list, g);
3789 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
3790 TREE_OPERAND (val, 0), lastlane,
3791 NULL_TREE, NULL_TREE);
3795 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3796 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
3798 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
3799 gimple_seq_add_seq (stmt_list,
3800 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3801 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
3804 x = build_outer_var_ref (var, ctx);
3805 if (is_reference (var))
3806 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3807 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
3808 gimplify_and_add (x, stmt_list);
3810 c = OMP_CLAUSE_CHAIN (c);
3811 if (c == NULL && !par_clauses)
3813 /* If this was a workshare clause, see if it had been combined
3814 with its parallel. In that case, continue looking for the
3815 clauses also on the parallel statement itself. */
3816 if (is_parallel_ctx (ctx))
3817 break;
3819 ctx = ctx->outer;
3820 if (ctx == NULL || !is_parallel_ctx (ctx))
3821 break;
3823 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3824 OMP_CLAUSE_LASTPRIVATE);
3825 par_clauses = true;
3829 if (label)
3830 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
3834 /* Generate code to implement the REDUCTION clauses. */
3836 static void
3837 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
3839 gimple_seq sub_seq = NULL;
3840 gimple stmt;
3841 tree x, c;
3842 int count = 0;
3844 /* SIMD reductions are handled in lower_rec_input_clauses. */
3845 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3846 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
3847 return;
3849 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3850 update in that case, otherwise use a lock. */
3851 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
3852 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
3854 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3856 /* Never use OMP_ATOMIC for array reductions or UDRs. */
3857 count = -1;
3858 break;
3860 count++;
3863 if (count == 0)
3864 return;
3866 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3868 tree var, ref, new_var;
3869 enum tree_code code;
3870 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3872 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
3873 continue;
3875 var = OMP_CLAUSE_DECL (c);
3876 new_var = lookup_decl (var, ctx);
3877 if (is_reference (var))
3878 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3879 ref = build_outer_var_ref (var, ctx);
3880 code = OMP_CLAUSE_REDUCTION_CODE (c);
3882 /* reduction(-:var) sums up the partial results, so it acts
3883 identically to reduction(+:var). */
3884 if (code == MINUS_EXPR)
3885 code = PLUS_EXPR;
3887 if (count == 1)
3889 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
3891 addr = save_expr (addr);
3892 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
3893 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
3894 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
3895 gimplify_and_add (x, stmt_seqp);
3896 return;
3899 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3901 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3903 if (is_reference (var)
3904 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3905 TREE_TYPE (ref)))
3906 ref = build_fold_addr_expr_loc (clause_loc, ref);
3907 SET_DECL_VALUE_EXPR (placeholder, ref);
3908 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3909 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
3910 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
3911 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3912 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
3914 else
3916 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3917 ref = build_outer_var_ref (var, ctx);
3918 gimplify_assign (ref, x, &sub_seq);
3922 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
3924 gimple_seq_add_stmt (stmt_seqp, stmt);
3926 gimple_seq_add_seq (stmt_seqp, sub_seq);
3928 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
3930 gimple_seq_add_stmt (stmt_seqp, stmt);
3934 /* Generate code to implement the COPYPRIVATE clauses. */
3936 static void
3937 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
3938 omp_context *ctx)
3940 tree c;
3942 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3944 tree var, new_var, ref, x;
3945 bool by_ref;
3946 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3948 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
3949 continue;
3951 var = OMP_CLAUSE_DECL (c);
3952 by_ref = use_pointer_for_field (var, NULL);
3954 ref = build_sender_ref (var, ctx);
3955 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
3956 if (by_ref)
3958 x = build_fold_addr_expr_loc (clause_loc, new_var);
3959 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
3961 gimplify_assign (ref, x, slist);
3963 ref = build_receiver_ref (var, false, ctx);
3964 if (by_ref)
3966 ref = fold_convert_loc (clause_loc,
3967 build_pointer_type (TREE_TYPE (new_var)),
3968 ref);
3969 ref = build_fold_indirect_ref_loc (clause_loc, ref);
3971 if (is_reference (var))
3973 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
3974 ref = build_simple_mem_ref_loc (clause_loc, ref);
3975 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3977 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
3978 gimplify_and_add (x, rlist);
3983 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
3984 and REDUCTION from the sender (aka parent) side. */
3986 static void
3987 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
3988 omp_context *ctx)
3990 tree c;
3992 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3994 tree val, ref, x, var;
3995 bool by_ref, do_in = false, do_out = false;
3996 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3998 switch (OMP_CLAUSE_CODE (c))
4000 case OMP_CLAUSE_PRIVATE:
4001 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4002 break;
4003 continue;
4004 case OMP_CLAUSE_FIRSTPRIVATE:
4005 case OMP_CLAUSE_COPYIN:
4006 case OMP_CLAUSE_LASTPRIVATE:
4007 case OMP_CLAUSE_REDUCTION:
4008 case OMP_CLAUSE__LOOPTEMP_:
4009 break;
4010 default:
4011 continue;
4014 val = OMP_CLAUSE_DECL (c);
4015 var = lookup_decl_in_outer_ctx (val, ctx);
4017 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4018 && is_global_var (var))
4019 continue;
4020 if (is_variable_sized (val))
4021 continue;
4022 by_ref = use_pointer_for_field (val, NULL);
4024 switch (OMP_CLAUSE_CODE (c))
4026 case OMP_CLAUSE_PRIVATE:
4027 case OMP_CLAUSE_FIRSTPRIVATE:
4028 case OMP_CLAUSE_COPYIN:
4029 case OMP_CLAUSE__LOOPTEMP_:
4030 do_in = true;
4031 break;
4033 case OMP_CLAUSE_LASTPRIVATE:
4034 if (by_ref || is_reference (val))
4036 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4037 continue;
4038 do_in = true;
4040 else
4042 do_out = true;
4043 if (lang_hooks.decls.omp_private_outer_ref (val))
4044 do_in = true;
4046 break;
4048 case OMP_CLAUSE_REDUCTION:
4049 do_in = true;
4050 do_out = !(by_ref || is_reference (val));
4051 break;
4053 default:
4054 gcc_unreachable ();
4057 if (do_in)
4059 ref = build_sender_ref (val, ctx);
4060 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4061 gimplify_assign (ref, x, ilist);
4062 if (is_task_ctx (ctx))
4063 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4066 if (do_out)
4068 ref = build_sender_ref (val, ctx);
4069 gimplify_assign (var, ref, olist);
4074 /* Generate code to implement SHARED from the sender (aka parent)
4075 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4076 list things that got automatically shared. */
4078 static void
4079 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4081 tree var, ovar, nvar, f, x, record_type;
4083 if (ctx->record_type == NULL)
4084 return;
4086 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4087 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4089 ovar = DECL_ABSTRACT_ORIGIN (f);
4090 nvar = maybe_lookup_decl (ovar, ctx);
4091 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4092 continue;
4094 /* If CTX is a nested parallel directive. Find the immediately
4095 enclosing parallel or workshare construct that contains a
4096 mapping for OVAR. */
4097 var = lookup_decl_in_outer_ctx (ovar, ctx);
4099 if (use_pointer_for_field (ovar, ctx))
4101 x = build_sender_ref (ovar, ctx);
4102 var = build_fold_addr_expr (var);
4103 gimplify_assign (x, var, ilist);
4105 else
4107 x = build_sender_ref (ovar, ctx);
4108 gimplify_assign (x, var, ilist);
4110 if (!TREE_READONLY (var)
4111 /* We don't need to receive a new reference to a result
4112 or parm decl. In fact we may not store to it as we will
4113 invalidate any pending RSO and generate wrong gimple
4114 during inlining. */
4115 && !((TREE_CODE (var) == RESULT_DECL
4116 || TREE_CODE (var) == PARM_DECL)
4117 && DECL_BY_REFERENCE (var)))
4119 x = build_sender_ref (ovar, ctx);
4120 gimplify_assign (var, x, olist);
4127 /* A convenience function to build an empty GIMPLE_COND with just the
4128 condition. */
4130 static gimple
4131 gimple_build_cond_empty (tree cond)
4133 enum tree_code pred_code;
4134 tree lhs, rhs;
4136 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4137 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4141 /* Build the function calls to GOMP_parallel_start etc to actually
4142 generate the parallel operation. REGION is the parallel region
4143 being expanded. BB is the block where to insert the code. WS_ARGS
4144 will be set if this is a call to a combined parallel+workshare
4145 construct, it contains the list of additional arguments needed by
4146 the workshare construct. */
4148 static void
4149 expand_parallel_call (struct omp_region *region, basic_block bb,
4150 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4152 tree t, t1, t2, val, cond, c, clauses, flags;
4153 gimple_stmt_iterator gsi;
4154 gimple stmt;
4155 enum built_in_function start_ix;
4156 int start_ix2;
4157 location_t clause_loc;
4158 vec<tree, va_gc> *args;
4160 clauses = gimple_omp_parallel_clauses (entry_stmt);
4162 /* Determine what flavor of GOMP_parallel we will be
4163 emitting. */
4164 start_ix = BUILT_IN_GOMP_PARALLEL;
4165 if (is_combined_parallel (region))
4167 switch (region->inner->type)
4169 case GIMPLE_OMP_FOR:
4170 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4171 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4172 + (region->inner->sched_kind
4173 == OMP_CLAUSE_SCHEDULE_RUNTIME
4174 ? 3 : region->inner->sched_kind));
4175 start_ix = (enum built_in_function)start_ix2;
4176 break;
4177 case GIMPLE_OMP_SECTIONS:
4178 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4179 break;
4180 default:
4181 gcc_unreachable ();
4185 /* By default, the value of NUM_THREADS is zero (selected at run time)
4186 and there is no conditional. */
4187 cond = NULL_TREE;
4188 val = build_int_cst (unsigned_type_node, 0);
4189 flags = build_int_cst (unsigned_type_node, 0);
4191 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4192 if (c)
4193 cond = OMP_CLAUSE_IF_EXPR (c);
4195 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4196 if (c)
4198 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4199 clause_loc = OMP_CLAUSE_LOCATION (c);
4201 else
4202 clause_loc = gimple_location (entry_stmt);
4204 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4205 if (c)
4206 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4208 /* Ensure 'val' is of the correct type. */
4209 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4211 /* If we found the clause 'if (cond)', build either
4212 (cond != 0) or (cond ? val : 1u). */
4213 if (cond)
4215 gimple_stmt_iterator gsi;
4217 cond = gimple_boolify (cond);
4219 if (integer_zerop (val))
4220 val = fold_build2_loc (clause_loc,
4221 EQ_EXPR, unsigned_type_node, cond,
4222 build_int_cst (TREE_TYPE (cond), 0));
4223 else
4225 basic_block cond_bb, then_bb, else_bb;
4226 edge e, e_then, e_else;
4227 tree tmp_then, tmp_else, tmp_join, tmp_var;
4229 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4230 if (gimple_in_ssa_p (cfun))
4232 tmp_then = make_ssa_name (tmp_var, NULL);
4233 tmp_else = make_ssa_name (tmp_var, NULL);
4234 tmp_join = make_ssa_name (tmp_var, NULL);
4236 else
4238 tmp_then = tmp_var;
4239 tmp_else = tmp_var;
4240 tmp_join = tmp_var;
4243 e = split_block (bb, NULL);
4244 cond_bb = e->src;
4245 bb = e->dest;
4246 remove_edge (e);
4248 then_bb = create_empty_bb (cond_bb);
4249 else_bb = create_empty_bb (then_bb);
4250 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4251 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4253 stmt = gimple_build_cond_empty (cond);
4254 gsi = gsi_start_bb (cond_bb);
4255 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4257 gsi = gsi_start_bb (then_bb);
4258 stmt = gimple_build_assign (tmp_then, val);
4259 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4261 gsi = gsi_start_bb (else_bb);
4262 stmt = gimple_build_assign
4263 (tmp_else, build_int_cst (unsigned_type_node, 1));
4264 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4266 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4267 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4268 if (current_loops)
4270 add_bb_to_loop (then_bb, cond_bb->loop_father);
4271 add_bb_to_loop (else_bb, cond_bb->loop_father);
4273 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4274 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4276 if (gimple_in_ssa_p (cfun))
4278 gimple phi = create_phi_node (tmp_join, bb);
4279 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4280 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4283 val = tmp_join;
4286 gsi = gsi_start_bb (bb);
4287 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4288 false, GSI_CONTINUE_LINKING);
4291 gsi = gsi_last_bb (bb);
4292 t = gimple_omp_parallel_data_arg (entry_stmt);
4293 if (t == NULL)
4294 t1 = null_pointer_node;
4295 else
4296 t1 = build_fold_addr_expr (t);
4297 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4299 vec_alloc (args, 4 + vec_safe_length (ws_args));
4300 args->quick_push (t2);
4301 args->quick_push (t1);
4302 args->quick_push (val);
4303 if (ws_args)
4304 args->splice (*ws_args);
4305 args->quick_push (flags);
4307 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4308 builtin_decl_explicit (start_ix), args);
4310 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4311 false, GSI_CONTINUE_LINKING);
4315 /* Build the function call to GOMP_task to actually
4316 generate the task operation. BB is the block where to insert the code. */
4318 static void
4319 expand_task_call (basic_block bb, gimple entry_stmt)
4321 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4322 gimple_stmt_iterator gsi;
4323 location_t loc = gimple_location (entry_stmt);
4325 clauses = gimple_omp_task_clauses (entry_stmt);
4327 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4328 if (c)
4329 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4330 else
4331 cond = boolean_true_node;
4333 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4334 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4335 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4336 flags = build_int_cst (unsigned_type_node,
4337 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4339 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4340 if (c)
4342 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4343 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4344 build_int_cst (unsigned_type_node, 2),
4345 build_int_cst (unsigned_type_node, 0));
4346 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4348 if (depend)
4349 depend = OMP_CLAUSE_DECL (depend);
4350 else
4351 depend = build_int_cst (ptr_type_node, 0);
4353 gsi = gsi_last_bb (bb);
4354 t = gimple_omp_task_data_arg (entry_stmt);
4355 if (t == NULL)
4356 t2 = null_pointer_node;
4357 else
4358 t2 = build_fold_addr_expr_loc (loc, t);
4359 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4360 t = gimple_omp_task_copy_fn (entry_stmt);
4361 if (t == NULL)
4362 t3 = null_pointer_node;
4363 else
4364 t3 = build_fold_addr_expr_loc (loc, t);
4366 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4367 8, t1, t2, t3,
4368 gimple_omp_task_arg_size (entry_stmt),
4369 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4370 depend);
4372 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4373 false, GSI_CONTINUE_LINKING);
4377 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4378 catch handler and return it. This prevents programs from violating the
4379 structured block semantics with throws. */
4381 static gimple_seq
4382 maybe_catch_exception (gimple_seq body)
4384 gimple g;
4385 tree decl;
4387 if (!flag_exceptions)
4388 return body;
4390 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4391 decl = lang_hooks.eh_protect_cleanup_actions ();
4392 else
4393 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4395 g = gimple_build_eh_must_not_throw (decl);
4396 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4397 GIMPLE_TRY_CATCH);
4399 return gimple_seq_alloc_with_stmt (g);
4402 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4404 static tree
4405 vec2chain (vec<tree, va_gc> *v)
4407 tree chain = NULL_TREE, t;
4408 unsigned ix;
4410 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4412 DECL_CHAIN (t) = chain;
4413 chain = t;
4416 return chain;
4420 /* Remove barriers in REGION->EXIT's block. Note that this is only
4421 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4422 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4423 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4424 removed. */
4426 static void
4427 remove_exit_barrier (struct omp_region *region)
4429 gimple_stmt_iterator gsi;
4430 basic_block exit_bb;
4431 edge_iterator ei;
4432 edge e;
4433 gimple stmt;
4434 int any_addressable_vars = -1;
4436 exit_bb = region->exit;
4438 /* If the parallel region doesn't return, we don't have REGION->EXIT
4439 block at all. */
4440 if (! exit_bb)
4441 return;
4443 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4444 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4445 statements that can appear in between are extremely limited -- no
4446 memory operations at all. Here, we allow nothing at all, so the
4447 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4448 gsi = gsi_last_bb (exit_bb);
4449 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4450 gsi_prev (&gsi);
4451 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4452 return;
4454 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4456 gsi = gsi_last_bb (e->src);
4457 if (gsi_end_p (gsi))
4458 continue;
4459 stmt = gsi_stmt (gsi);
4460 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4461 && !gimple_omp_return_nowait_p (stmt))
4463 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4464 in many cases. If there could be tasks queued, the barrier
4465 might be needed to let the tasks run before some local
4466 variable of the parallel that the task uses as shared
4467 runs out of scope. The task can be spawned either
4468 from within current function (this would be easy to check)
4469 or from some function it calls and gets passed an address
4470 of such a variable. */
4471 if (any_addressable_vars < 0)
4473 gimple parallel_stmt = last_stmt (region->entry);
4474 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4475 tree local_decls, block, decl;
4476 unsigned ix;
4478 any_addressable_vars = 0;
4479 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4480 if (TREE_ADDRESSABLE (decl))
4482 any_addressable_vars = 1;
4483 break;
4485 for (block = gimple_block (stmt);
4486 !any_addressable_vars
4487 && block
4488 && TREE_CODE (block) == BLOCK;
4489 block = BLOCK_SUPERCONTEXT (block))
4491 for (local_decls = BLOCK_VARS (block);
4492 local_decls;
4493 local_decls = DECL_CHAIN (local_decls))
4494 if (TREE_ADDRESSABLE (local_decls))
4496 any_addressable_vars = 1;
4497 break;
4499 if (block == gimple_block (parallel_stmt))
4500 break;
4503 if (!any_addressable_vars)
4504 gimple_omp_return_set_nowait (stmt);
4509 static void
4510 remove_exit_barriers (struct omp_region *region)
4512 if (region->type == GIMPLE_OMP_PARALLEL)
4513 remove_exit_barrier (region);
4515 if (region->inner)
4517 region = region->inner;
4518 remove_exit_barriers (region);
4519 while (region->next)
4521 region = region->next;
4522 remove_exit_barriers (region);
4527 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4528 calls. These can't be declared as const functions, but
4529 within one parallel body they are constant, so they can be
4530 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4531 which are declared const. Similarly for task body, except
4532 that in untied task omp_get_thread_num () can change at any task
4533 scheduling point. */
4535 static void
4536 optimize_omp_library_calls (gimple entry_stmt)
4538 basic_block bb;
4539 gimple_stmt_iterator gsi;
4540 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4541 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4542 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4543 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4544 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4545 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4546 OMP_CLAUSE_UNTIED) != NULL);
4548 FOR_EACH_BB (bb)
4549 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4551 gimple call = gsi_stmt (gsi);
4552 tree decl;
4554 if (is_gimple_call (call)
4555 && (decl = gimple_call_fndecl (call))
4556 && DECL_EXTERNAL (decl)
4557 && TREE_PUBLIC (decl)
4558 && DECL_INITIAL (decl) == NULL)
4560 tree built_in;
4562 if (DECL_NAME (decl) == thr_num_id)
4564 /* In #pragma omp task untied omp_get_thread_num () can change
4565 during the execution of the task region. */
4566 if (untied_task)
4567 continue;
4568 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4570 else if (DECL_NAME (decl) == num_thr_id)
4571 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4572 else
4573 continue;
4575 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4576 || gimple_call_num_args (call) != 0)
4577 continue;
4579 if (flag_exceptions && !TREE_NOTHROW (decl))
4580 continue;
4582 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4583 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4584 TREE_TYPE (TREE_TYPE (built_in))))
4585 continue;
4587 gimple_call_set_fndecl (call, built_in);
4592 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4593 regimplified. */
4595 static tree
4596 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4598 tree t = *tp;
4600 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4601 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4602 return t;
4604 if (TREE_CODE (t) == ADDR_EXPR)
4605 recompute_tree_invariant_for_addr_expr (t);
4607 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4608 return NULL_TREE;
4611 /* Prepend TO = FROM assignment before *GSI_P. */
4613 static void
4614 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4616 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4617 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4618 true, GSI_SAME_STMT);
4619 gimple stmt = gimple_build_assign (to, from);
4620 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4621 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4622 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4624 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4625 gimple_regimplify_operands (stmt, &gsi);
4629 /* Expand the OpenMP parallel or task directive starting at REGION. */
4631 static void
4632 expand_omp_taskreg (struct omp_region *region)
4634 basic_block entry_bb, exit_bb, new_bb;
4635 struct function *child_cfun;
4636 tree child_fn, block, t;
4637 gimple_stmt_iterator gsi;
4638 gimple entry_stmt, stmt;
4639 edge e;
4640 vec<tree, va_gc> *ws_args;
4642 entry_stmt = last_stmt (region->entry);
4643 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4644 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4646 entry_bb = region->entry;
4647 exit_bb = region->exit;
4649 if (is_combined_parallel (region))
4650 ws_args = region->ws_args;
4651 else
4652 ws_args = NULL;
4654 if (child_cfun->cfg)
4656 /* Due to inlining, it may happen that we have already outlined
4657 the region, in which case all we need to do is make the
4658 sub-graph unreachable and emit the parallel call. */
4659 edge entry_succ_e, exit_succ_e;
4660 gimple_stmt_iterator gsi;
4662 entry_succ_e = single_succ_edge (entry_bb);
4664 gsi = gsi_last_bb (entry_bb);
4665 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4666 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4667 gsi_remove (&gsi, true);
4669 new_bb = entry_bb;
4670 if (exit_bb)
4672 exit_succ_e = single_succ_edge (exit_bb);
4673 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4675 remove_edge_and_dominated_blocks (entry_succ_e);
4677 else
4679 unsigned srcidx, dstidx, num;
4681 /* If the parallel region needs data sent from the parent
4682 function, then the very first statement (except possible
4683 tree profile counter updates) of the parallel body
4684 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4685 &.OMP_DATA_O is passed as an argument to the child function,
4686 we need to replace it with the argument as seen by the child
4687 function.
4689 In most cases, this will end up being the identity assignment
4690 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4691 a function call that has been inlined, the original PARM_DECL
4692 .OMP_DATA_I may have been converted into a different local
4693 variable. In which case, we need to keep the assignment. */
4694 if (gimple_omp_taskreg_data_arg (entry_stmt))
4696 basic_block entry_succ_bb = single_succ (entry_bb);
4697 gimple_stmt_iterator gsi;
4698 tree arg, narg;
4699 gimple parcopy_stmt = NULL;
4701 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4703 gimple stmt;
4705 gcc_assert (!gsi_end_p (gsi));
4706 stmt = gsi_stmt (gsi);
4707 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4708 continue;
4710 if (gimple_num_ops (stmt) == 2)
4712 tree arg = gimple_assign_rhs1 (stmt);
4714 /* We're ignore the subcode because we're
4715 effectively doing a STRIP_NOPS. */
4717 if (TREE_CODE (arg) == ADDR_EXPR
4718 && TREE_OPERAND (arg, 0)
4719 == gimple_omp_taskreg_data_arg (entry_stmt))
4721 parcopy_stmt = stmt;
4722 break;
4727 gcc_assert (parcopy_stmt != NULL);
4728 arg = DECL_ARGUMENTS (child_fn);
4730 if (!gimple_in_ssa_p (cfun))
4732 if (gimple_assign_lhs (parcopy_stmt) == arg)
4733 gsi_remove (&gsi, true);
4734 else
4736 /* ?? Is setting the subcode really necessary ?? */
4737 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
4738 gimple_assign_set_rhs1 (parcopy_stmt, arg);
4741 else
4743 /* If we are in ssa form, we must load the value from the default
4744 definition of the argument. That should not be defined now,
4745 since the argument is not used uninitialized. */
4746 gcc_assert (ssa_default_def (cfun, arg) == NULL);
4747 narg = make_ssa_name (arg, gimple_build_nop ());
4748 set_ssa_default_def (cfun, arg, narg);
4749 /* ?? Is setting the subcode really necessary ?? */
4750 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
4751 gimple_assign_set_rhs1 (parcopy_stmt, narg);
4752 update_stmt (parcopy_stmt);
4756 /* Declare local variables needed in CHILD_CFUN. */
4757 block = DECL_INITIAL (child_fn);
4758 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4759 /* The gimplifier could record temporaries in parallel/task block
4760 rather than in containing function's local_decls chain,
4761 which would mean cgraph missed finalizing them. Do it now. */
4762 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4763 if (TREE_CODE (t) == VAR_DECL
4764 && TREE_STATIC (t)
4765 && !DECL_EXTERNAL (t))
4766 varpool_finalize_decl (t);
4767 DECL_SAVED_TREE (child_fn) = NULL;
4768 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4769 gimple_set_body (child_fn, NULL);
4770 TREE_USED (block) = 1;
4772 /* Reset DECL_CONTEXT on function arguments. */
4773 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
4774 DECL_CONTEXT (t) = child_fn;
4776 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
4777 so that it can be moved to the child function. */
4778 gsi = gsi_last_bb (entry_bb);
4779 stmt = gsi_stmt (gsi);
4780 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
4781 || gimple_code (stmt) == GIMPLE_OMP_TASK));
4782 gsi_remove (&gsi, true);
4783 e = split_block (entry_bb, stmt);
4784 entry_bb = e->dest;
4785 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4787 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4788 if (exit_bb)
4790 gsi = gsi_last_bb (exit_bb);
4791 gcc_assert (!gsi_end_p (gsi)
4792 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4793 stmt = gimple_build_return (NULL);
4794 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4795 gsi_remove (&gsi, true);
4798 /* Move the parallel region into CHILD_CFUN. */
4800 if (gimple_in_ssa_p (cfun))
4802 init_tree_ssa (child_cfun);
4803 init_ssa_operands (child_cfun);
4804 child_cfun->gimple_df->in_ssa_p = true;
4805 block = NULL_TREE;
4807 else
4808 block = gimple_block (entry_stmt);
4810 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
4811 if (exit_bb)
4812 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
4813 /* When the OMP expansion process cannot guarantee an up-to-date
4814 loop tree arrange for the child function to fixup loops. */
4815 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
4816 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
4818 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
4819 num = vec_safe_length (child_cfun->local_decls);
4820 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
4822 t = (*child_cfun->local_decls)[srcidx];
4823 if (DECL_CONTEXT (t) == cfun->decl)
4824 continue;
4825 if (srcidx != dstidx)
4826 (*child_cfun->local_decls)[dstidx] = t;
4827 dstidx++;
4829 if (dstidx != num)
4830 vec_safe_truncate (child_cfun->local_decls, dstidx);
4832 /* Inform the callgraph about the new function. */
4833 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
4834 cgraph_add_new_function (child_fn, true);
4836 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4837 fixed in a following pass. */
4838 push_cfun (child_cfun);
4839 if (optimize)
4840 optimize_omp_library_calls (entry_stmt);
4841 rebuild_cgraph_edges ();
4843 /* Some EH regions might become dead, see PR34608. If
4844 pass_cleanup_cfg isn't the first pass to happen with the
4845 new child, these dead EH edges might cause problems.
4846 Clean them up now. */
4847 if (flag_exceptions)
4849 basic_block bb;
4850 bool changed = false;
4852 FOR_EACH_BB (bb)
4853 changed |= gimple_purge_dead_eh_edges (bb);
4854 if (changed)
4855 cleanup_tree_cfg ();
4857 if (gimple_in_ssa_p (cfun))
4858 update_ssa (TODO_update_ssa);
4859 pop_cfun ();
4862 /* Emit a library call to launch the children threads. */
4863 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
4864 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
4865 else
4866 expand_task_call (new_bb, entry_stmt);
4867 if (gimple_in_ssa_p (cfun))
4868 update_ssa (TODO_update_ssa_only_virtuals);
4872 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4873 of the combined collapse > 1 loop constructs, generate code like:
4874 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4875 if (cond3 is <)
4876 adj = STEP3 - 1;
4877 else
4878 adj = STEP3 + 1;
4879 count3 = (adj + N32 - N31) / STEP3;
4880 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4881 if (cond2 is <)
4882 adj = STEP2 - 1;
4883 else
4884 adj = STEP2 + 1;
4885 count2 = (adj + N22 - N21) / STEP2;
4886 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4887 if (cond1 is <)
4888 adj = STEP1 - 1;
4889 else
4890 adj = STEP1 + 1;
4891 count1 = (adj + N12 - N11) / STEP1;
4892 count = count1 * count2 * count3;
4893 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4894 count = 0;
4895 and set ZERO_ITER_BB to that bb. If this isn't the outermost
4896 of the combined loop constructs, just initialize COUNTS array
4897 from the _looptemp_ clauses. */
4899 /* NOTE: It *could* be better to moosh all of the BBs together,
4900 creating one larger BB with all the computation and the unexpected
4901 jump at the end. I.e.
4903 bool zero3, zero2, zero1, zero;
4905 zero3 = N32 c3 N31;
4906 count3 = (N32 - N31) /[cl] STEP3;
4907 zero2 = N22 c2 N21;
4908 count2 = (N22 - N21) /[cl] STEP2;
4909 zero1 = N12 c1 N11;
4910 count1 = (N12 - N11) /[cl] STEP1;
4911 zero = zero3 || zero2 || zero1;
4912 count = count1 * count2 * count3;
4913 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4915 After all, we expect the zero=false, and thus we expect to have to
4916 evaluate all of the comparison expressions, so short-circuiting
4917 oughtn't be a win. Since the condition isn't protecting a
4918 denominator, we're not concerned about divide-by-zero, so we can
4919 fully evaluate count even if a numerator turned out to be wrong.
4921 It seems like putting this all together would create much better
4922 scheduling opportunities, and less pressure on the chip's branch
4923 predictor. */
4925 static void
4926 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4927 basic_block &entry_bb, tree *counts,
4928 basic_block &zero_iter_bb, int &first_zero_iter,
4929 basic_block &l2_dom_bb)
4931 tree t, type = TREE_TYPE (fd->loop.v);
4932 gimple stmt;
4933 edge e, ne;
4934 int i;
4936 /* Collapsed loops need work for expansion into SSA form. */
4937 gcc_assert (!gimple_in_ssa_p (cfun));
4939 if (gimple_omp_for_combined_into_p (fd->for_stmt)
4940 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
4942 /* First two _looptemp_ clauses are for istart/iend, counts[0]
4943 isn't supposed to be handled, as the inner loop doesn't
4944 use it. */
4945 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
4946 OMP_CLAUSE__LOOPTEMP_);
4947 gcc_assert (innerc);
4948 for (i = 0; i < fd->collapse; i++)
4950 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
4951 OMP_CLAUSE__LOOPTEMP_);
4952 gcc_assert (innerc);
4953 if (i)
4954 counts[i] = OMP_CLAUSE_DECL (innerc);
4955 else
4956 counts[0] = NULL_TREE;
4958 return;
4961 for (i = 0; i < fd->collapse; i++)
4963 tree itype = TREE_TYPE (fd->loops[i].v);
4965 if (SSA_VAR_P (fd->loop.n2)
4966 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
4967 fold_convert (itype, fd->loops[i].n1),
4968 fold_convert (itype, fd->loops[i].n2)))
4969 == NULL_TREE || !integer_onep (t)))
4971 tree n1, n2;
4972 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
4973 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
4974 true, GSI_SAME_STMT);
4975 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
4976 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
4977 true, GSI_SAME_STMT);
4978 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
4979 NULL_TREE, NULL_TREE);
4980 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4981 if (walk_tree (gimple_cond_lhs_ptr (stmt),
4982 expand_omp_regimplify_p, NULL, NULL)
4983 || walk_tree (gimple_cond_rhs_ptr (stmt),
4984 expand_omp_regimplify_p, NULL, NULL))
4986 *gsi = gsi_for_stmt (stmt);
4987 gimple_regimplify_operands (stmt, gsi);
4989 e = split_block (entry_bb, stmt);
4990 if (zero_iter_bb == NULL)
4992 first_zero_iter = i;
4993 zero_iter_bb = create_empty_bb (entry_bb);
4994 if (current_loops)
4995 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
4996 *gsi = gsi_after_labels (zero_iter_bb);
4997 stmt = gimple_build_assign (fd->loop.n2,
4998 build_zero_cst (type));
4999 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5000 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5001 entry_bb);
5003 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5004 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5005 e->flags = EDGE_TRUE_VALUE;
5006 e->probability = REG_BR_PROB_BASE - ne->probability;
5007 if (l2_dom_bb == NULL)
5008 l2_dom_bb = entry_bb;
5009 entry_bb = e->dest;
5010 *gsi = gsi_last_bb (entry_bb);
5013 if (POINTER_TYPE_P (itype))
5014 itype = signed_type_for (itype);
5015 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5016 ? -1 : 1));
5017 t = fold_build2 (PLUS_EXPR, itype,
5018 fold_convert (itype, fd->loops[i].step), t);
5019 t = fold_build2 (PLUS_EXPR, itype, t,
5020 fold_convert (itype, fd->loops[i].n2));
5021 t = fold_build2 (MINUS_EXPR, itype, t,
5022 fold_convert (itype, fd->loops[i].n1));
5023 /* ?? We could probably use CEIL_DIV_EXPR instead of
5024 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5025 generate the same code in the end because generically we
5026 don't know that the values involved must be negative for
5027 GT?? */
5028 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5029 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5030 fold_build1 (NEGATE_EXPR, itype, t),
5031 fold_build1 (NEGATE_EXPR, itype,
5032 fold_convert (itype,
5033 fd->loops[i].step)));
5034 else
5035 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5036 fold_convert (itype, fd->loops[i].step));
5037 t = fold_convert (type, t);
5038 if (TREE_CODE (t) == INTEGER_CST)
5039 counts[i] = t;
5040 else
5042 counts[i] = create_tmp_reg (type, ".count");
5043 expand_omp_build_assign (gsi, counts[i], t);
5045 if (SSA_VAR_P (fd->loop.n2))
5047 if (i == 0)
5048 t = counts[0];
5049 else
5050 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5051 expand_omp_build_assign (gsi, fd->loop.n2, t);
5057 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5058 T = V;
5059 V3 = N31 + (T % count3) * STEP3;
5060 T = T / count3;
5061 V2 = N21 + (T % count2) * STEP2;
5062 T = T / count2;
5063 V1 = N11 + T * STEP1;
5064 if this loop doesn't have an inner loop construct combined with it.
5065 If it does have an inner loop construct combined with it and the
5066 iteration count isn't known constant, store values from counts array
5067 into its _looptemp_ temporaries instead. */
5069 static void
5070 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5071 tree *counts, gimple inner_stmt, tree startvar)
5073 int i;
5074 if (gimple_omp_for_combined_p (fd->for_stmt))
5076 /* If fd->loop.n2 is constant, then no propagation of the counts
5077 is needed, they are constant. */
5078 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5079 return;
5081 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5082 ? gimple_omp_parallel_clauses (inner_stmt)
5083 : gimple_omp_for_clauses (inner_stmt);
5084 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5085 isn't supposed to be handled, as the inner loop doesn't
5086 use it. */
5087 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5088 gcc_assert (innerc);
5089 for (i = 0; i < fd->collapse; i++)
5091 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5092 OMP_CLAUSE__LOOPTEMP_);
5093 gcc_assert (innerc);
5094 if (i)
5096 tree tem = OMP_CLAUSE_DECL (innerc);
5097 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5098 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5099 false, GSI_CONTINUE_LINKING);
5100 gimple stmt = gimple_build_assign (tem, t);
5101 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5104 return;
5107 tree type = TREE_TYPE (fd->loop.v);
5108 tree tem = create_tmp_reg (type, ".tem");
5109 gimple stmt = gimple_build_assign (tem, startvar);
5110 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5112 for (i = fd->collapse - 1; i >= 0; i--)
5114 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5115 itype = vtype;
5116 if (POINTER_TYPE_P (vtype))
5117 itype = signed_type_for (vtype);
5118 if (i != 0)
5119 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5120 else
5121 t = tem;
5122 t = fold_convert (itype, t);
5123 t = fold_build2 (MULT_EXPR, itype, t,
5124 fold_convert (itype, fd->loops[i].step));
5125 if (POINTER_TYPE_P (vtype))
5126 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5127 else
5128 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5129 t = force_gimple_operand_gsi (gsi, t,
5130 DECL_P (fd->loops[i].v)
5131 && TREE_ADDRESSABLE (fd->loops[i].v),
5132 NULL_TREE, false,
5133 GSI_CONTINUE_LINKING);
5134 stmt = gimple_build_assign (fd->loops[i].v, t);
5135 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5136 if (i != 0)
5138 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5139 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5140 false, GSI_CONTINUE_LINKING);
5141 stmt = gimple_build_assign (tem, t);
5142 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5148 /* Helper function for expand_omp_for_*. Generate code like:
5149 L10:
5150 V3 += STEP3;
5151 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5152 L11:
5153 V3 = N31;
5154 V2 += STEP2;
5155 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5156 L12:
5157 V2 = N21;
5158 V1 += STEP1;
5159 goto BODY_BB; */
5161 static basic_block
5162 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5163 basic_block body_bb)
5165 basic_block last_bb, bb, collapse_bb = NULL;
5166 int i;
5167 gimple_stmt_iterator gsi;
5168 edge e;
5169 tree t;
5170 gimple stmt;
5172 last_bb = cont_bb;
5173 for (i = fd->collapse - 1; i >= 0; i--)
5175 tree vtype = TREE_TYPE (fd->loops[i].v);
5177 bb = create_empty_bb (last_bb);
5178 if (current_loops)
5179 add_bb_to_loop (bb, last_bb->loop_father);
5180 gsi = gsi_start_bb (bb);
5182 if (i < fd->collapse - 1)
5184 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5185 e->probability = REG_BR_PROB_BASE / 8;
5187 t = fd->loops[i + 1].n1;
5188 t = force_gimple_operand_gsi (&gsi, t,
5189 DECL_P (fd->loops[i + 1].v)
5190 && TREE_ADDRESSABLE (fd->loops[i
5191 + 1].v),
5192 NULL_TREE, false,
5193 GSI_CONTINUE_LINKING);
5194 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5195 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5197 else
5198 collapse_bb = bb;
5200 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5202 if (POINTER_TYPE_P (vtype))
5203 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5204 else
5205 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5206 t = force_gimple_operand_gsi (&gsi, t,
5207 DECL_P (fd->loops[i].v)
5208 && TREE_ADDRESSABLE (fd->loops[i].v),
5209 NULL_TREE, false, GSI_CONTINUE_LINKING);
5210 stmt = gimple_build_assign (fd->loops[i].v, t);
5211 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5213 if (i > 0)
5215 t = fd->loops[i].n2;
5216 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5217 false, GSI_CONTINUE_LINKING);
5218 tree v = fd->loops[i].v;
5219 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5220 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5221 false, GSI_CONTINUE_LINKING);
5222 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5223 stmt = gimple_build_cond_empty (t);
5224 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5225 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5226 e->probability = REG_BR_PROB_BASE * 7 / 8;
5228 else
5229 make_edge (bb, body_bb, EDGE_FALLTHRU);
5230 last_bb = bb;
5233 return collapse_bb;
5237 /* A subroutine of expand_omp_for. Generate code for a parallel
5238 loop with any schedule. Given parameters:
5240 for (V = N1; V cond N2; V += STEP) BODY;
5242 where COND is "<" or ">", we generate pseudocode
5244 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5245 if (more) goto L0; else goto L3;
5247 V = istart0;
5248 iend = iend0;
5250 BODY;
5251 V += STEP;
5252 if (V cond iend) goto L1; else goto L2;
5254 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5257 If this is a combined omp parallel loop, instead of the call to
5258 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5259 If this is gimple_omp_for_combined_p loop, then instead of assigning
5260 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5261 inner GIMPLE_OMP_FOR and V += STEP; and
5262 if (V cond iend) goto L1; else goto L2; are removed.
5264 For collapsed loops, given parameters:
5265 collapse(3)
5266 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5267 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5268 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5269 BODY;
5271 we generate pseudocode
5273 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5274 if (cond3 is <)
5275 adj = STEP3 - 1;
5276 else
5277 adj = STEP3 + 1;
5278 count3 = (adj + N32 - N31) / STEP3;
5279 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5280 if (cond2 is <)
5281 adj = STEP2 - 1;
5282 else
5283 adj = STEP2 + 1;
5284 count2 = (adj + N22 - N21) / STEP2;
5285 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5286 if (cond1 is <)
5287 adj = STEP1 - 1;
5288 else
5289 adj = STEP1 + 1;
5290 count1 = (adj + N12 - N11) / STEP1;
5291 count = count1 * count2 * count3;
5292 goto Z1;
5294 count = 0;
5296 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5297 if (more) goto L0; else goto L3;
5299 V = istart0;
5300 T = V;
5301 V3 = N31 + (T % count3) * STEP3;
5302 T = T / count3;
5303 V2 = N21 + (T % count2) * STEP2;
5304 T = T / count2;
5305 V1 = N11 + T * STEP1;
5306 iend = iend0;
5308 BODY;
5309 V += 1;
5310 if (V < iend) goto L10; else goto L2;
5311 L10:
5312 V3 += STEP3;
5313 if (V3 cond3 N32) goto L1; else goto L11;
5314 L11:
5315 V3 = N31;
5316 V2 += STEP2;
5317 if (V2 cond2 N22) goto L1; else goto L12;
5318 L12:
5319 V2 = N21;
5320 V1 += STEP1;
5321 goto L1;
5323 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5328 static void
5329 expand_omp_for_generic (struct omp_region *region,
5330 struct omp_for_data *fd,
5331 enum built_in_function start_fn,
5332 enum built_in_function next_fn,
5333 gimple inner_stmt)
5335 tree type, istart0, iend0, iend;
5336 tree t, vmain, vback, bias = NULL_TREE;
5337 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5338 basic_block l2_bb = NULL, l3_bb = NULL;
5339 gimple_stmt_iterator gsi;
5340 gimple stmt;
5341 bool in_combined_parallel = is_combined_parallel (region);
5342 bool broken_loop = region->cont == NULL;
5343 edge e, ne;
5344 tree *counts = NULL;
5345 int i;
5347 gcc_assert (!broken_loop || !in_combined_parallel);
5348 gcc_assert (fd->iter_type == long_integer_type_node
5349 || !in_combined_parallel);
5351 type = TREE_TYPE (fd->loop.v);
5352 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5353 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5354 TREE_ADDRESSABLE (istart0) = 1;
5355 TREE_ADDRESSABLE (iend0) = 1;
5357 /* See if we need to bias by LLONG_MIN. */
5358 if (fd->iter_type == long_long_unsigned_type_node
5359 && TREE_CODE (type) == INTEGER_TYPE
5360 && !TYPE_UNSIGNED (type))
5362 tree n1, n2;
5364 if (fd->loop.cond_code == LT_EXPR)
5366 n1 = fd->loop.n1;
5367 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5369 else
5371 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5372 n2 = fd->loop.n1;
5374 if (TREE_CODE (n1) != INTEGER_CST
5375 || TREE_CODE (n2) != INTEGER_CST
5376 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5377 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5380 entry_bb = region->entry;
5381 cont_bb = region->cont;
5382 collapse_bb = NULL;
5383 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5384 gcc_assert (broken_loop
5385 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5386 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5387 l1_bb = single_succ (l0_bb);
5388 if (!broken_loop)
5390 l2_bb = create_empty_bb (cont_bb);
5391 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5392 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5394 else
5395 l2_bb = NULL;
5396 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5397 exit_bb = region->exit;
5399 gsi = gsi_last_bb (entry_bb);
5401 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5402 if (fd->collapse > 1)
5404 int first_zero_iter = -1;
5405 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5407 counts = XALLOCAVEC (tree, fd->collapse);
5408 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5409 zero_iter_bb, first_zero_iter,
5410 l2_dom_bb);
5412 if (zero_iter_bb)
5414 /* Some counts[i] vars might be uninitialized if
5415 some loop has zero iterations. But the body shouldn't
5416 be executed in that case, so just avoid uninit warnings. */
5417 for (i = first_zero_iter; i < fd->collapse; i++)
5418 if (SSA_VAR_P (counts[i]))
5419 TREE_NO_WARNING (counts[i]) = 1;
5420 gsi_prev (&gsi);
5421 e = split_block (entry_bb, gsi_stmt (gsi));
5422 entry_bb = e->dest;
5423 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5424 gsi = gsi_last_bb (entry_bb);
5425 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5426 get_immediate_dominator (CDI_DOMINATORS,
5427 zero_iter_bb));
5430 if (in_combined_parallel)
5432 /* In a combined parallel loop, emit a call to
5433 GOMP_loop_foo_next. */
5434 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5435 build_fold_addr_expr (istart0),
5436 build_fold_addr_expr (iend0));
5438 else
5440 tree t0, t1, t2, t3, t4;
5441 /* If this is not a combined parallel loop, emit a call to
5442 GOMP_loop_foo_start in ENTRY_BB. */
5443 t4 = build_fold_addr_expr (iend0);
5444 t3 = build_fold_addr_expr (istart0);
5445 t2 = fold_convert (fd->iter_type, fd->loop.step);
5446 t1 = fd->loop.n2;
5447 t0 = fd->loop.n1;
5448 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5450 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5451 OMP_CLAUSE__LOOPTEMP_);
5452 gcc_assert (innerc);
5453 t0 = OMP_CLAUSE_DECL (innerc);
5454 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5455 OMP_CLAUSE__LOOPTEMP_);
5456 gcc_assert (innerc);
5457 t1 = OMP_CLAUSE_DECL (innerc);
5459 if (POINTER_TYPE_P (TREE_TYPE (t0))
5460 && TYPE_PRECISION (TREE_TYPE (t0))
5461 != TYPE_PRECISION (fd->iter_type))
5463 /* Avoid casting pointers to integer of a different size. */
5464 tree itype = signed_type_for (type);
5465 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5466 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5468 else
5470 t1 = fold_convert (fd->iter_type, t1);
5471 t0 = fold_convert (fd->iter_type, t0);
5473 if (bias)
5475 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5476 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5478 if (fd->iter_type == long_integer_type_node)
5480 if (fd->chunk_size)
5482 t = fold_convert (fd->iter_type, fd->chunk_size);
5483 t = build_call_expr (builtin_decl_explicit (start_fn),
5484 6, t0, t1, t2, t, t3, t4);
5486 else
5487 t = build_call_expr (builtin_decl_explicit (start_fn),
5488 5, t0, t1, t2, t3, t4);
5490 else
5492 tree t5;
5493 tree c_bool_type;
5494 tree bfn_decl;
5496 /* The GOMP_loop_ull_*start functions have additional boolean
5497 argument, true for < loops and false for > loops.
5498 In Fortran, the C bool type can be different from
5499 boolean_type_node. */
5500 bfn_decl = builtin_decl_explicit (start_fn);
5501 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5502 t5 = build_int_cst (c_bool_type,
5503 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5504 if (fd->chunk_size)
5506 tree bfn_decl = builtin_decl_explicit (start_fn);
5507 t = fold_convert (fd->iter_type, fd->chunk_size);
5508 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5510 else
5511 t = build_call_expr (builtin_decl_explicit (start_fn),
5512 6, t5, t0, t1, t2, t3, t4);
5515 if (TREE_TYPE (t) != boolean_type_node)
5516 t = fold_build2 (NE_EXPR, boolean_type_node,
5517 t, build_int_cst (TREE_TYPE (t), 0));
5518 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5519 true, GSI_SAME_STMT);
5520 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5522 /* Remove the GIMPLE_OMP_FOR statement. */
5523 gsi_remove (&gsi, true);
5525 /* Iteration setup for sequential loop goes in L0_BB. */
5526 tree startvar = fd->loop.v;
5527 tree endvar = NULL_TREE;
5529 if (gimple_omp_for_combined_p (fd->for_stmt))
5531 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5532 && gimple_omp_for_kind (inner_stmt)
5533 == GF_OMP_FOR_KIND_SIMD);
5534 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5535 OMP_CLAUSE__LOOPTEMP_);
5536 gcc_assert (innerc);
5537 startvar = OMP_CLAUSE_DECL (innerc);
5538 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5539 OMP_CLAUSE__LOOPTEMP_);
5540 gcc_assert (innerc);
5541 endvar = OMP_CLAUSE_DECL (innerc);
5544 gsi = gsi_start_bb (l0_bb);
5545 t = istart0;
5546 if (bias)
5547 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5548 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5549 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5550 t = fold_convert (TREE_TYPE (startvar), t);
5551 t = force_gimple_operand_gsi (&gsi, t,
5552 DECL_P (startvar)
5553 && TREE_ADDRESSABLE (startvar),
5554 NULL_TREE, false, GSI_CONTINUE_LINKING);
5555 stmt = gimple_build_assign (startvar, t);
5556 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5558 t = iend0;
5559 if (bias)
5560 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5561 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5562 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5563 t = fold_convert (TREE_TYPE (startvar), t);
5564 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5565 false, GSI_CONTINUE_LINKING);
5566 if (endvar)
5568 stmt = gimple_build_assign (endvar, iend);
5569 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5571 if (fd->collapse > 1)
5572 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5574 if (!broken_loop)
5576 /* Code to control the increment and predicate for the sequential
5577 loop goes in the CONT_BB. */
5578 gsi = gsi_last_bb (cont_bb);
5579 stmt = gsi_stmt (gsi);
5580 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5581 vmain = gimple_omp_continue_control_use (stmt);
5582 vback = gimple_omp_continue_control_def (stmt);
5584 if (!gimple_omp_for_combined_p (fd->for_stmt))
5586 if (POINTER_TYPE_P (type))
5587 t = fold_build_pointer_plus (vmain, fd->loop.step);
5588 else
5589 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5590 t = force_gimple_operand_gsi (&gsi, t,
5591 DECL_P (vback)
5592 && TREE_ADDRESSABLE (vback),
5593 NULL_TREE, true, GSI_SAME_STMT);
5594 stmt = gimple_build_assign (vback, t);
5595 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5597 t = build2 (fd->loop.cond_code, boolean_type_node,
5598 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5599 iend);
5600 stmt = gimple_build_cond_empty (t);
5601 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5604 /* Remove GIMPLE_OMP_CONTINUE. */
5605 gsi_remove (&gsi, true);
5607 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5608 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5610 /* Emit code to get the next parallel iteration in L2_BB. */
5611 gsi = gsi_start_bb (l2_bb);
5613 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5614 build_fold_addr_expr (istart0),
5615 build_fold_addr_expr (iend0));
5616 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5617 false, GSI_CONTINUE_LINKING);
5618 if (TREE_TYPE (t) != boolean_type_node)
5619 t = fold_build2 (NE_EXPR, boolean_type_node,
5620 t, build_int_cst (TREE_TYPE (t), 0));
5621 stmt = gimple_build_cond_empty (t);
5622 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5625 /* Add the loop cleanup function. */
5626 gsi = gsi_last_bb (exit_bb);
5627 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5628 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5629 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5630 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5631 else
5632 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5633 stmt = gimple_build_call (t, 0);
5634 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5635 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5636 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5637 gsi_remove (&gsi, true);
5639 /* Connect the new blocks. */
5640 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5641 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5643 if (!broken_loop)
5645 gimple_seq phis;
5647 e = find_edge (cont_bb, l3_bb);
5648 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5650 phis = phi_nodes (l3_bb);
5651 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5653 gimple phi = gsi_stmt (gsi);
5654 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5655 PHI_ARG_DEF_FROM_EDGE (phi, e));
5657 remove_edge (e);
5659 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5660 if (current_loops)
5661 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5662 e = find_edge (cont_bb, l1_bb);
5663 if (gimple_omp_for_combined_p (fd->for_stmt))
5665 remove_edge (e);
5666 e = NULL;
5668 else if (fd->collapse > 1)
5670 remove_edge (e);
5671 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5673 else
5674 e->flags = EDGE_TRUE_VALUE;
5675 if (e)
5677 e->probability = REG_BR_PROB_BASE * 7 / 8;
5678 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5680 else
5682 e = find_edge (cont_bb, l2_bb);
5683 e->flags = EDGE_FALLTHRU;
5685 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5687 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5688 recompute_dominator (CDI_DOMINATORS, l2_bb));
5689 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5690 recompute_dominator (CDI_DOMINATORS, l3_bb));
5691 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5692 recompute_dominator (CDI_DOMINATORS, l0_bb));
5693 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5694 recompute_dominator (CDI_DOMINATORS, l1_bb));
5696 struct loop *outer_loop = alloc_loop ();
5697 outer_loop->header = l0_bb;
5698 outer_loop->latch = l2_bb;
5699 add_loop (outer_loop, l0_bb->loop_father);
5701 if (!gimple_omp_for_combined_p (fd->for_stmt))
5703 struct loop *loop = alloc_loop ();
5704 loop->header = l1_bb;
5705 /* The loop may have multiple latches. */
5706 add_loop (loop, outer_loop);
5712 /* A subroutine of expand_omp_for. Generate code for a parallel
5713 loop with static schedule and no specified chunk size. Given
5714 parameters:
5716 for (V = N1; V cond N2; V += STEP) BODY;
5718 where COND is "<" or ">", we generate pseudocode
5720 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5721 if (cond is <)
5722 adj = STEP - 1;
5723 else
5724 adj = STEP + 1;
5725 if ((__typeof (V)) -1 > 0 && cond is >)
5726 n = -(adj + N2 - N1) / -STEP;
5727 else
5728 n = (adj + N2 - N1) / STEP;
5729 q = n / nthreads;
5730 tt = n % nthreads;
5731 if (threadid < tt) goto L3; else goto L4;
5733 tt = 0;
5734 q = q + 1;
5736 s0 = q * threadid + tt;
5737 e0 = s0 + q;
5738 V = s0 * STEP + N1;
5739 if (s0 >= e0) goto L2; else goto L0;
5741 e = e0 * STEP + N1;
5743 BODY;
5744 V += STEP;
5745 if (V cond e) goto L1;
5749 static void
5750 expand_omp_for_static_nochunk (struct omp_region *region,
5751 struct omp_for_data *fd,
5752 gimple inner_stmt)
5754 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
5755 tree type, itype, vmain, vback;
5756 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
5757 basic_block body_bb, cont_bb, collapse_bb = NULL;
5758 basic_block fin_bb;
5759 gimple_stmt_iterator gsi;
5760 gimple stmt;
5761 edge ep;
5762 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
5763 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
5764 bool broken_loop = region->cont == NULL;
5765 tree *counts = NULL;
5766 tree n1, n2, step;
5768 itype = type = TREE_TYPE (fd->loop.v);
5769 if (POINTER_TYPE_P (type))
5770 itype = signed_type_for (type);
5772 entry_bb = region->entry;
5773 cont_bb = region->cont;
5774 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5775 fin_bb = BRANCH_EDGE (entry_bb)->dest;
5776 gcc_assert (broken_loop
5777 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
5778 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5779 body_bb = single_succ (seq_start_bb);
5780 if (!broken_loop)
5782 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
5783 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5785 exit_bb = region->exit;
5787 /* Iteration space partitioning goes in ENTRY_BB. */
5788 gsi = gsi_last_bb (entry_bb);
5789 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5791 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
5793 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
5794 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
5797 if (fd->collapse > 1)
5799 int first_zero_iter = -1;
5800 basic_block l2_dom_bb = NULL;
5802 counts = XALLOCAVEC (tree, fd->collapse);
5803 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5804 fin_bb, first_zero_iter,
5805 l2_dom_bb);
5806 t = NULL_TREE;
5808 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
5809 t = integer_one_node;
5810 else
5811 t = fold_binary (fd->loop.cond_code, boolean_type_node,
5812 fold_convert (type, fd->loop.n1),
5813 fold_convert (type, fd->loop.n2));
5814 if (fd->collapse == 1
5815 && TYPE_UNSIGNED (type)
5816 && (t == NULL_TREE || !integer_onep (t)))
5818 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5819 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5820 true, GSI_SAME_STMT);
5821 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5822 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5823 true, GSI_SAME_STMT);
5824 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
5825 NULL_TREE, NULL_TREE);
5826 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5827 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5828 expand_omp_regimplify_p, NULL, NULL)
5829 || walk_tree (gimple_cond_rhs_ptr (stmt),
5830 expand_omp_regimplify_p, NULL, NULL))
5832 gsi = gsi_for_stmt (stmt);
5833 gimple_regimplify_operands (stmt, &gsi);
5835 ep = split_block (entry_bb, stmt);
5836 ep->flags = EDGE_TRUE_VALUE;
5837 entry_bb = ep->dest;
5838 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
5839 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
5840 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
5841 if (gimple_in_ssa_p (cfun))
5843 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
5844 for (gsi = gsi_start_phis (fin_bb);
5845 !gsi_end_p (gsi); gsi_next (&gsi))
5847 gimple phi = gsi_stmt (gsi);
5848 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
5849 ep, UNKNOWN_LOCATION);
5852 gsi = gsi_last_bb (entry_bb);
5855 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
5856 t = fold_convert (itype, t);
5857 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5858 true, GSI_SAME_STMT);
5860 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
5861 t = fold_convert (itype, t);
5862 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5863 true, GSI_SAME_STMT);
5865 n1 = fd->loop.n1;
5866 n2 = fd->loop.n2;
5867 step = fd->loop.step;
5868 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5870 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5871 OMP_CLAUSE__LOOPTEMP_);
5872 gcc_assert (innerc);
5873 n1 = OMP_CLAUSE_DECL (innerc);
5874 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5875 OMP_CLAUSE__LOOPTEMP_);
5876 gcc_assert (innerc);
5877 n2 = OMP_CLAUSE_DECL (innerc);
5879 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
5880 true, NULL_TREE, true, GSI_SAME_STMT);
5881 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
5882 true, NULL_TREE, true, GSI_SAME_STMT);
5883 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
5884 true, NULL_TREE, true, GSI_SAME_STMT);
5886 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
5887 t = fold_build2 (PLUS_EXPR, itype, step, t);
5888 t = fold_build2 (PLUS_EXPR, itype, t, n2);
5889 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
5890 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
5891 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5892 fold_build1 (NEGATE_EXPR, itype, t),
5893 fold_build1 (NEGATE_EXPR, itype, step));
5894 else
5895 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
5896 t = fold_convert (itype, t);
5897 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5899 q = create_tmp_reg (itype, "q");
5900 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
5901 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5902 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
5904 tt = create_tmp_reg (itype, "tt");
5905 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
5906 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5907 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
5909 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
5910 stmt = gimple_build_cond_empty (t);
5911 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5913 second_bb = split_block (entry_bb, stmt)->dest;
5914 gsi = gsi_last_bb (second_bb);
5915 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5917 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
5918 GSI_SAME_STMT);
5919 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
5920 build_int_cst (itype, 1));
5921 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5923 third_bb = split_block (second_bb, stmt)->dest;
5924 gsi = gsi_last_bb (third_bb);
5925 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5927 t = build2 (MULT_EXPR, itype, q, threadid);
5928 t = build2 (PLUS_EXPR, itype, t, tt);
5929 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5931 t = fold_build2 (PLUS_EXPR, itype, s0, q);
5932 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5934 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
5935 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5937 /* Remove the GIMPLE_OMP_FOR statement. */
5938 gsi_remove (&gsi, true);
5940 /* Setup code for sequential iteration goes in SEQ_START_BB. */
5941 gsi = gsi_start_bb (seq_start_bb);
5943 tree startvar = fd->loop.v;
5944 tree endvar = NULL_TREE;
5946 if (gimple_omp_for_combined_p (fd->for_stmt))
5948 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5949 ? gimple_omp_parallel_clauses (inner_stmt)
5950 : gimple_omp_for_clauses (inner_stmt);
5951 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5952 gcc_assert (innerc);
5953 startvar = OMP_CLAUSE_DECL (innerc);
5954 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5955 OMP_CLAUSE__LOOPTEMP_);
5956 gcc_assert (innerc);
5957 endvar = OMP_CLAUSE_DECL (innerc);
5959 t = fold_convert (itype, s0);
5960 t = fold_build2 (MULT_EXPR, itype, t, step);
5961 if (POINTER_TYPE_P (type))
5962 t = fold_build_pointer_plus (n1, t);
5963 else
5964 t = fold_build2 (PLUS_EXPR, type, t, n1);
5965 t = fold_convert (TREE_TYPE (startvar), t);
5966 t = force_gimple_operand_gsi (&gsi, t,
5967 DECL_P (startvar)
5968 && TREE_ADDRESSABLE (startvar),
5969 NULL_TREE, false, GSI_CONTINUE_LINKING);
5970 stmt = gimple_build_assign (startvar, t);
5971 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5973 t = fold_convert (itype, e0);
5974 t = fold_build2 (MULT_EXPR, itype, t, step);
5975 if (POINTER_TYPE_P (type))
5976 t = fold_build_pointer_plus (n1, t);
5977 else
5978 t = fold_build2 (PLUS_EXPR, type, t, n1);
5979 t = fold_convert (TREE_TYPE (startvar), t);
5980 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5981 false, GSI_CONTINUE_LINKING);
5982 if (endvar)
5984 stmt = gimple_build_assign (endvar, e);
5985 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5987 if (fd->collapse > 1)
5988 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5990 if (!broken_loop)
5992 /* The code controlling the sequential loop replaces the
5993 GIMPLE_OMP_CONTINUE. */
5994 gsi = gsi_last_bb (cont_bb);
5995 stmt = gsi_stmt (gsi);
5996 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5997 vmain = gimple_omp_continue_control_use (stmt);
5998 vback = gimple_omp_continue_control_def (stmt);
6000 if (!gimple_omp_for_combined_p (fd->for_stmt))
6002 if (POINTER_TYPE_P (type))
6003 t = fold_build_pointer_plus (vmain, step);
6004 else
6005 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6006 t = force_gimple_operand_gsi (&gsi, t,
6007 DECL_P (vback)
6008 && TREE_ADDRESSABLE (vback),
6009 NULL_TREE, true, GSI_SAME_STMT);
6010 stmt = gimple_build_assign (vback, t);
6011 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6013 t = build2 (fd->loop.cond_code, boolean_type_node,
6014 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6015 ? t : vback, e);
6016 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6019 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6020 gsi_remove (&gsi, true);
6022 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6023 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6026 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6027 gsi = gsi_last_bb (exit_bb);
6028 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6030 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6031 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6033 gsi_remove (&gsi, true);
6035 /* Connect all the blocks. */
6036 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6037 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6038 ep = find_edge (entry_bb, second_bb);
6039 ep->flags = EDGE_TRUE_VALUE;
6040 ep->probability = REG_BR_PROB_BASE / 4;
6041 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6042 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6044 if (!broken_loop)
6046 ep = find_edge (cont_bb, body_bb);
6047 if (gimple_omp_for_combined_p (fd->for_stmt))
6049 remove_edge (ep);
6050 ep = NULL;
6052 else if (fd->collapse > 1)
6054 remove_edge (ep);
6055 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6057 else
6058 ep->flags = EDGE_TRUE_VALUE;
6059 find_edge (cont_bb, fin_bb)->flags
6060 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6063 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6064 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6065 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6067 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6068 recompute_dominator (CDI_DOMINATORS, body_bb));
6069 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6070 recompute_dominator (CDI_DOMINATORS, fin_bb));
6072 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6074 struct loop *loop = alloc_loop ();
6075 loop->header = body_bb;
6076 if (collapse_bb == NULL)
6077 loop->latch = cont_bb;
6078 add_loop (loop, body_bb->loop_father);
6083 /* A subroutine of expand_omp_for. Generate code for a parallel
6084 loop with static schedule and a specified chunk size. Given
6085 parameters:
6087 for (V = N1; V cond N2; V += STEP) BODY;
6089 where COND is "<" or ">", we generate pseudocode
6091 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6092 if (cond is <)
6093 adj = STEP - 1;
6094 else
6095 adj = STEP + 1;
6096 if ((__typeof (V)) -1 > 0 && cond is >)
6097 n = -(adj + N2 - N1) / -STEP;
6098 else
6099 n = (adj + N2 - N1) / STEP;
6100 trip = 0;
6101 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6102 here so that V is defined
6103 if the loop is not entered
6105 s0 = (trip * nthreads + threadid) * CHUNK;
6106 e0 = min(s0 + CHUNK, n);
6107 if (s0 < n) goto L1; else goto L4;
6109 V = s0 * STEP + N1;
6110 e = e0 * STEP + N1;
6112 BODY;
6113 V += STEP;
6114 if (V cond e) goto L2; else goto L3;
6116 trip += 1;
6117 goto L0;
6121 static void
6122 expand_omp_for_static_chunk (struct omp_region *region,
6123 struct omp_for_data *fd, gimple inner_stmt)
6125 tree n, s0, e0, e, t;
6126 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6127 tree type, itype, v_main, v_back, v_extra;
6128 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6129 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6130 gimple_stmt_iterator si;
6131 gimple stmt;
6132 edge se;
6133 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6134 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6135 bool broken_loop = region->cont == NULL;
6136 tree *counts = NULL;
6137 tree n1, n2, step;
6139 itype = type = TREE_TYPE (fd->loop.v);
6140 if (POINTER_TYPE_P (type))
6141 itype = signed_type_for (type);
6143 entry_bb = region->entry;
6144 se = split_block (entry_bb, last_stmt (entry_bb));
6145 entry_bb = se->src;
6146 iter_part_bb = se->dest;
6147 cont_bb = region->cont;
6148 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6149 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6150 gcc_assert (broken_loop
6151 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6152 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6153 body_bb = single_succ (seq_start_bb);
6154 if (!broken_loop)
6156 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6157 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6158 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6160 exit_bb = region->exit;
6162 /* Trip and adjustment setup goes in ENTRY_BB. */
6163 si = gsi_last_bb (entry_bb);
6164 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
6166 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6168 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6169 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6172 if (fd->collapse > 1)
6174 int first_zero_iter = -1;
6175 basic_block l2_dom_bb = NULL;
6177 counts = XALLOCAVEC (tree, fd->collapse);
6178 expand_omp_for_init_counts (fd, &si, entry_bb, counts,
6179 fin_bb, first_zero_iter,
6180 l2_dom_bb);
6181 t = NULL_TREE;
6183 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6184 t = integer_one_node;
6185 else
6186 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6187 fold_convert (type, fd->loop.n1),
6188 fold_convert (type, fd->loop.n2));
6189 if (fd->collapse == 1
6190 && TYPE_UNSIGNED (type)
6191 && (t == NULL_TREE || !integer_onep (t)))
6193 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6194 n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
6195 true, GSI_SAME_STMT);
6196 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6197 n2 = force_gimple_operand_gsi (&si, n2, true, NULL_TREE,
6198 true, GSI_SAME_STMT);
6199 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6200 NULL_TREE, NULL_TREE);
6201 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6202 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6203 expand_omp_regimplify_p, NULL, NULL)
6204 || walk_tree (gimple_cond_rhs_ptr (stmt),
6205 expand_omp_regimplify_p, NULL, NULL))
6207 si = gsi_for_stmt (stmt);
6208 gimple_regimplify_operands (stmt, &si);
6210 se = split_block (entry_bb, stmt);
6211 se->flags = EDGE_TRUE_VALUE;
6212 entry_bb = se->dest;
6213 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6214 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6215 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6216 if (gimple_in_ssa_p (cfun))
6218 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6219 for (si = gsi_start_phis (fin_bb);
6220 !gsi_end_p (si); gsi_next (&si))
6222 gimple phi = gsi_stmt (si);
6223 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6224 se, UNKNOWN_LOCATION);
6227 si = gsi_last_bb (entry_bb);
6230 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6231 t = fold_convert (itype, t);
6232 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6233 true, GSI_SAME_STMT);
6235 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6236 t = fold_convert (itype, t);
6237 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6238 true, GSI_SAME_STMT);
6240 n1 = fd->loop.n1;
6241 n2 = fd->loop.n2;
6242 step = fd->loop.step;
6243 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6245 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6246 OMP_CLAUSE__LOOPTEMP_);
6247 gcc_assert (innerc);
6248 n1 = OMP_CLAUSE_DECL (innerc);
6249 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6250 OMP_CLAUSE__LOOPTEMP_);
6251 gcc_assert (innerc);
6252 n2 = OMP_CLAUSE_DECL (innerc);
6254 n1 = force_gimple_operand_gsi (&si, fold_convert (type, n1),
6255 true, NULL_TREE, true, GSI_SAME_STMT);
6256 n2 = force_gimple_operand_gsi (&si, fold_convert (itype, n2),
6257 true, NULL_TREE, true, GSI_SAME_STMT);
6258 step = force_gimple_operand_gsi (&si, fold_convert (itype, step),
6259 true, NULL_TREE, true, GSI_SAME_STMT);
6260 fd->chunk_size
6261 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
6262 true, NULL_TREE, true, GSI_SAME_STMT);
6264 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6265 t = fold_build2 (PLUS_EXPR, itype, step, t);
6266 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6267 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6268 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6269 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6270 fold_build1 (NEGATE_EXPR, itype, t),
6271 fold_build1 (NEGATE_EXPR, itype, step));
6272 else
6273 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6274 t = fold_convert (itype, t);
6275 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6276 true, GSI_SAME_STMT);
6278 trip_var = create_tmp_reg (itype, ".trip");
6279 if (gimple_in_ssa_p (cfun))
6281 trip_init = make_ssa_name (trip_var, NULL);
6282 trip_main = make_ssa_name (trip_var, NULL);
6283 trip_back = make_ssa_name (trip_var, NULL);
6285 else
6287 trip_init = trip_var;
6288 trip_main = trip_var;
6289 trip_back = trip_var;
6292 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6293 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6295 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6296 t = fold_build2 (MULT_EXPR, itype, t, step);
6297 if (POINTER_TYPE_P (type))
6298 t = fold_build_pointer_plus (n1, t);
6299 else
6300 t = fold_build2 (PLUS_EXPR, type, t, n1);
6301 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6302 true, GSI_SAME_STMT);
6304 /* Remove the GIMPLE_OMP_FOR. */
6305 gsi_remove (&si, true);
6307 /* Iteration space partitioning goes in ITER_PART_BB. */
6308 si = gsi_last_bb (iter_part_bb);
6310 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6311 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6312 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6313 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6314 false, GSI_CONTINUE_LINKING);
6316 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6317 t = fold_build2 (MIN_EXPR, itype, t, n);
6318 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6319 false, GSI_CONTINUE_LINKING);
6321 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6322 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6324 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6325 si = gsi_start_bb (seq_start_bb);
6327 tree startvar = fd->loop.v;
6328 tree endvar = NULL_TREE;
6330 if (gimple_omp_for_combined_p (fd->for_stmt))
6332 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6333 ? gimple_omp_parallel_clauses (inner_stmt)
6334 : gimple_omp_for_clauses (inner_stmt);
6335 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6336 gcc_assert (innerc);
6337 startvar = OMP_CLAUSE_DECL (innerc);
6338 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6339 OMP_CLAUSE__LOOPTEMP_);
6340 gcc_assert (innerc);
6341 endvar = OMP_CLAUSE_DECL (innerc);
6344 t = fold_convert (itype, s0);
6345 t = fold_build2 (MULT_EXPR, itype, t, step);
6346 if (POINTER_TYPE_P (type))
6347 t = fold_build_pointer_plus (n1, t);
6348 else
6349 t = fold_build2 (PLUS_EXPR, type, t, n1);
6350 t = fold_convert (TREE_TYPE (startvar), t);
6351 t = force_gimple_operand_gsi (&si, t,
6352 DECL_P (startvar)
6353 && TREE_ADDRESSABLE (startvar),
6354 NULL_TREE, false, GSI_CONTINUE_LINKING);
6355 stmt = gimple_build_assign (startvar, t);
6356 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6358 t = fold_convert (itype, e0);
6359 t = fold_build2 (MULT_EXPR, itype, t, step);
6360 if (POINTER_TYPE_P (type))
6361 t = fold_build_pointer_plus (n1, t);
6362 else
6363 t = fold_build2 (PLUS_EXPR, type, t, n1);
6364 t = fold_convert (TREE_TYPE (startvar), t);
6365 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6366 false, GSI_CONTINUE_LINKING);
6367 if (endvar)
6369 stmt = gimple_build_assign (endvar, e);
6370 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6372 if (fd->collapse > 1)
6373 expand_omp_for_init_vars (fd, &si, counts, inner_stmt, startvar);
6375 if (!broken_loop)
6377 /* The code controlling the sequential loop goes in CONT_BB,
6378 replacing the GIMPLE_OMP_CONTINUE. */
6379 si = gsi_last_bb (cont_bb);
6380 stmt = gsi_stmt (si);
6381 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6382 v_main = gimple_omp_continue_control_use (stmt);
6383 v_back = gimple_omp_continue_control_def (stmt);
6385 if (!gimple_omp_for_combined_p (fd->for_stmt))
6387 if (POINTER_TYPE_P (type))
6388 t = fold_build_pointer_plus (v_main, step);
6389 else
6390 t = fold_build2 (PLUS_EXPR, type, v_main, step);
6391 if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
6392 t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6393 true, GSI_SAME_STMT);
6394 stmt = gimple_build_assign (v_back, t);
6395 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6397 t = build2 (fd->loop.cond_code, boolean_type_node,
6398 DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
6399 ? t : v_back, e);
6400 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
6403 /* Remove GIMPLE_OMP_CONTINUE. */
6404 gsi_remove (&si, true);
6406 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6407 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6409 /* Trip update code goes into TRIP_UPDATE_BB. */
6410 si = gsi_start_bb (trip_update_bb);
6412 t = build_int_cst (itype, 1);
6413 t = build2 (PLUS_EXPR, itype, trip_main, t);
6414 stmt = gimple_build_assign (trip_back, t);
6415 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6418 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6419 si = gsi_last_bb (exit_bb);
6420 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
6422 t = gimple_omp_return_lhs (gsi_stmt (si));
6423 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
6425 gsi_remove (&si, true);
6427 /* Connect the new blocks. */
6428 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6429 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6431 if (!broken_loop)
6433 se = find_edge (cont_bb, body_bb);
6434 if (gimple_omp_for_combined_p (fd->for_stmt))
6436 remove_edge (se);
6437 se = NULL;
6439 else if (fd->collapse > 1)
6441 remove_edge (se);
6442 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6444 else
6445 se->flags = EDGE_TRUE_VALUE;
6446 find_edge (cont_bb, trip_update_bb)->flags
6447 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6449 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6452 if (gimple_in_ssa_p (cfun))
6454 gimple_stmt_iterator psi;
6455 gimple phi;
6456 edge re, ene;
6457 edge_var_map_vector *head;
6458 edge_var_map *vm;
6459 size_t i;
6461 gcc_assert (fd->collapse == 1 && !broken_loop);
6463 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6464 remove arguments of the phi nodes in fin_bb. We need to create
6465 appropriate phi nodes in iter_part_bb instead. */
6466 se = single_pred_edge (fin_bb);
6467 re = single_succ_edge (trip_update_bb);
6468 head = redirect_edge_var_map_vector (re);
6469 ene = single_succ_edge (entry_bb);
6471 psi = gsi_start_phis (fin_bb);
6472 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6473 gsi_next (&psi), ++i)
6475 gimple nphi;
6476 source_location locus;
6478 phi = gsi_stmt (psi);
6479 t = gimple_phi_result (phi);
6480 gcc_assert (t == redirect_edge_var_map_result (vm));
6481 nphi = create_phi_node (t, iter_part_bb);
6483 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6484 locus = gimple_phi_arg_location_from_edge (phi, se);
6486 /* A special case -- fd->loop.v is not yet computed in
6487 iter_part_bb, we need to use v_extra instead. */
6488 if (t == fd->loop.v)
6489 t = v_extra;
6490 add_phi_arg (nphi, t, ene, locus);
6491 locus = redirect_edge_var_map_location (vm);
6492 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6494 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6495 redirect_edge_var_map_clear (re);
6496 while (1)
6498 psi = gsi_start_phis (fin_bb);
6499 if (gsi_end_p (psi))
6500 break;
6501 remove_phi_node (&psi, false);
6504 /* Make phi node for trip. */
6505 phi = create_phi_node (trip_main, iter_part_bb);
6506 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6507 UNKNOWN_LOCATION);
6508 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6509 UNKNOWN_LOCATION);
6512 if (!broken_loop)
6513 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6514 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6515 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6516 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6517 recompute_dominator (CDI_DOMINATORS, fin_bb));
6518 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6519 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6520 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6521 recompute_dominator (CDI_DOMINATORS, body_bb));
6523 if (!broken_loop)
6525 struct loop *trip_loop = alloc_loop ();
6526 trip_loop->header = iter_part_bb;
6527 trip_loop->latch = trip_update_bb;
6528 add_loop (trip_loop, iter_part_bb->loop_father);
6530 if (!gimple_omp_for_combined_p (fd->for_stmt))
6532 struct loop *loop = alloc_loop ();
6533 loop->header = body_bb;
6534 if (collapse_bb == NULL)
6535 loop->latch = cont_bb;
6536 add_loop (loop, trip_loop);
6542 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6543 loop. Given parameters:
6545 for (V = N1; V cond N2; V += STEP) BODY;
6547 where COND is "<" or ">", we generate pseudocode
6549 V = N1;
6550 goto L1;
6552 BODY;
6553 V += STEP;
6555 if (V cond N2) goto L0; else goto L2;
6558 For collapsed loops, given parameters:
6559 collapse(3)
6560 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6561 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6562 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6563 BODY;
6565 we generate pseudocode
6567 if (cond3 is <)
6568 adj = STEP3 - 1;
6569 else
6570 adj = STEP3 + 1;
6571 count3 = (adj + N32 - N31) / STEP3;
6572 if (cond2 is <)
6573 adj = STEP2 - 1;
6574 else
6575 adj = STEP2 + 1;
6576 count2 = (adj + N22 - N21) / STEP2;
6577 if (cond1 is <)
6578 adj = STEP1 - 1;
6579 else
6580 adj = STEP1 + 1;
6581 count1 = (adj + N12 - N11) / STEP1;
6582 count = count1 * count2 * count3;
6583 V = 0;
6584 V1 = N11;
6585 V2 = N21;
6586 V3 = N31;
6587 goto L1;
6589 BODY;
6590 V += 1;
6591 V3 += STEP3;
6592 V2 += (V3 cond3 N32) ? 0 : STEP2;
6593 V3 = (V3 cond3 N32) ? V3 : N31;
6594 V1 += (V2 cond2 N22) ? 0 : STEP1;
6595 V2 = (V2 cond2 N22) ? V2 : N21;
6597 if (V < count) goto L0; else goto L2;
6602 static void
6603 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
6605 tree type, t;
6606 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
6607 gimple_stmt_iterator gsi;
6608 gimple stmt;
6609 bool broken_loop = region->cont == NULL;
6610 edge e, ne;
6611 tree *counts = NULL;
6612 int i;
6613 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6614 OMP_CLAUSE_SAFELEN);
6615 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6616 OMP_CLAUSE__SIMDUID_);
6617 tree n1, n2;
6619 type = TREE_TYPE (fd->loop.v);
6620 entry_bb = region->entry;
6621 cont_bb = region->cont;
6622 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6623 gcc_assert (broken_loop
6624 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6625 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6626 if (!broken_loop)
6628 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6629 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6630 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6631 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6633 else
6635 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6636 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6637 l2_bb = single_succ (l1_bb);
6639 exit_bb = region->exit;
6640 l2_dom_bb = NULL;
6642 gsi = gsi_last_bb (entry_bb);
6644 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6645 /* Not needed in SSA form right now. */
6646 gcc_assert (!gimple_in_ssa_p (cfun));
6647 if (fd->collapse > 1)
6649 int first_zero_iter = -1;
6650 basic_block zero_iter_bb = l2_bb;
6652 counts = XALLOCAVEC (tree, fd->collapse);
6653 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6654 zero_iter_bb, first_zero_iter,
6655 l2_dom_bb);
6657 if (l2_dom_bb == NULL)
6658 l2_dom_bb = l1_bb;
6660 n1 = fd->loop.n1;
6661 n2 = fd->loop.n2;
6662 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6664 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6665 OMP_CLAUSE__LOOPTEMP_);
6666 gcc_assert (innerc);
6667 n1 = OMP_CLAUSE_DECL (innerc);
6668 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6669 OMP_CLAUSE__LOOPTEMP_);
6670 gcc_assert (innerc);
6671 n2 = OMP_CLAUSE_DECL (innerc);
6672 expand_omp_build_assign (&gsi, fd->loop.v,
6673 fold_convert (type, n1));
6674 if (fd->collapse > 1)
6676 gsi_prev (&gsi);
6677 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
6678 gsi_next (&gsi);
6681 else
6683 expand_omp_build_assign (&gsi, fd->loop.v,
6684 fold_convert (type, fd->loop.n1));
6685 if (fd->collapse > 1)
6686 for (i = 0; i < fd->collapse; i++)
6688 tree itype = TREE_TYPE (fd->loops[i].v);
6689 if (POINTER_TYPE_P (itype))
6690 itype = signed_type_for (itype);
6691 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
6692 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6696 /* Remove the GIMPLE_OMP_FOR statement. */
6697 gsi_remove (&gsi, true);
6699 if (!broken_loop)
6701 /* Code to control the increment goes in the CONT_BB. */
6702 gsi = gsi_last_bb (cont_bb);
6703 stmt = gsi_stmt (gsi);
6704 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6706 if (POINTER_TYPE_P (type))
6707 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
6708 else
6709 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
6710 expand_omp_build_assign (&gsi, fd->loop.v, t);
6712 if (fd->collapse > 1)
6714 i = fd->collapse - 1;
6715 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
6717 t = fold_convert (sizetype, fd->loops[i].step);
6718 t = fold_build_pointer_plus (fd->loops[i].v, t);
6720 else
6722 t = fold_convert (TREE_TYPE (fd->loops[i].v),
6723 fd->loops[i].step);
6724 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
6725 fd->loops[i].v, t);
6727 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6729 for (i = fd->collapse - 1; i > 0; i--)
6731 tree itype = TREE_TYPE (fd->loops[i].v);
6732 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
6733 if (POINTER_TYPE_P (itype2))
6734 itype2 = signed_type_for (itype2);
6735 t = build3 (COND_EXPR, itype2,
6736 build2 (fd->loops[i].cond_code, boolean_type_node,
6737 fd->loops[i].v,
6738 fold_convert (itype, fd->loops[i].n2)),
6739 build_int_cst (itype2, 0),
6740 fold_convert (itype2, fd->loops[i - 1].step));
6741 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
6742 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
6743 else
6744 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
6745 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
6747 t = build3 (COND_EXPR, itype,
6748 build2 (fd->loops[i].cond_code, boolean_type_node,
6749 fd->loops[i].v,
6750 fold_convert (itype, fd->loops[i].n2)),
6751 fd->loops[i].v,
6752 fold_convert (itype, fd->loops[i].n1));
6753 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6757 /* Remove GIMPLE_OMP_CONTINUE. */
6758 gsi_remove (&gsi, true);
6761 /* Emit the condition in L1_BB. */
6762 gsi = gsi_start_bb (l1_bb);
6764 t = fold_convert (type, n2);
6765 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6766 false, GSI_CONTINUE_LINKING);
6767 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
6768 stmt = gimple_build_cond_empty (t);
6769 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6770 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
6771 NULL, NULL)
6772 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
6773 NULL, NULL))
6775 gsi = gsi_for_stmt (stmt);
6776 gimple_regimplify_operands (stmt, &gsi);
6779 /* Remove GIMPLE_OMP_RETURN. */
6780 gsi = gsi_last_bb (exit_bb);
6781 gsi_remove (&gsi, true);
6783 /* Connect the new blocks. */
6784 remove_edge (FALLTHRU_EDGE (entry_bb));
6786 if (!broken_loop)
6788 remove_edge (BRANCH_EDGE (entry_bb));
6789 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6791 e = BRANCH_EDGE (l1_bb);
6792 ne = FALLTHRU_EDGE (l1_bb);
6793 e->flags = EDGE_TRUE_VALUE;
6795 else
6797 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6799 ne = single_succ_edge (l1_bb);
6800 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6803 ne->flags = EDGE_FALSE_VALUE;
6804 e->probability = REG_BR_PROB_BASE * 7 / 8;
6805 ne->probability = REG_BR_PROB_BASE / 8;
6807 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6808 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6809 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6811 if (!broken_loop)
6813 struct loop *loop = alloc_loop ();
6814 loop->header = l1_bb;
6815 loop->latch = cont_bb;
6816 add_loop (loop, l1_bb->loop_father);
6817 if (safelen == NULL_TREE)
6818 loop->safelen = INT_MAX;
6819 else
6821 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
6822 if (!tree_fits_uhwi_p (safelen)
6823 || tree_to_uhwi (safelen) > INT_MAX)
6824 loop->safelen = INT_MAX;
6825 else
6826 loop->safelen = tree_to_uhwi (safelen);
6827 if (loop->safelen == 1)
6828 loop->safelen = 0;
6830 if (simduid)
6832 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
6833 cfun->has_simduid_loops = true;
6835 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
6836 the loop. */
6837 if ((flag_tree_loop_vectorize
6838 || (!global_options_set.x_flag_tree_loop_vectorize
6839 && !global_options_set.x_flag_tree_vectorize))
6840 && loop->safelen > 1)
6842 loop->force_vect = true;
6843 cfun->has_force_vect_loops = true;
6849 /* Expand the OpenMP loop defined by REGION. */
6851 static void
6852 expand_omp_for (struct omp_region *region, gimple inner_stmt)
6854 struct omp_for_data fd;
6855 struct omp_for_data_loop *loops;
6857 loops
6858 = (struct omp_for_data_loop *)
6859 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
6860 * sizeof (struct omp_for_data_loop));
6861 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
6862 region->sched_kind = fd.sched_kind;
6864 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
6865 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6866 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6867 if (region->cont)
6869 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
6870 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6871 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6873 else
6874 /* If there isn't a continue then this is a degerate case where
6875 the introduction of abnormal edges during lowering will prevent
6876 original loops from being detected. Fix that up. */
6877 loops_state_set (LOOPS_NEED_FIXUP);
6879 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_KIND_SIMD)
6880 expand_omp_simd (region, &fd);
6881 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
6882 && !fd.have_ordered)
6884 if (fd.chunk_size == NULL)
6885 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
6886 else
6887 expand_omp_for_static_chunk (region, &fd, inner_stmt);
6889 else
6891 int fn_index, start_ix, next_ix;
6893 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
6894 == GF_OMP_FOR_KIND_FOR);
6895 if (fd.chunk_size == NULL
6896 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
6897 fd.chunk_size = integer_zero_node;
6898 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6899 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
6900 ? 3 : fd.sched_kind;
6901 fn_index += fd.have_ordered * 4;
6902 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
6903 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
6904 if (fd.iter_type == long_long_unsigned_type_node)
6906 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
6907 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
6908 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
6909 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
6911 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
6912 (enum built_in_function) next_ix, inner_stmt);
6915 if (gimple_in_ssa_p (cfun))
6916 update_ssa (TODO_update_ssa_only_virtuals);
6920 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
6922 v = GOMP_sections_start (n);
6924 switch (v)
6926 case 0:
6927 goto L2;
6928 case 1:
6929 section 1;
6930 goto L1;
6931 case 2:
6933 case n:
6935 default:
6936 abort ();
6939 v = GOMP_sections_next ();
6940 goto L0;
6942 reduction;
6944 If this is a combined parallel sections, replace the call to
6945 GOMP_sections_start with call to GOMP_sections_next. */
6947 static void
6948 expand_omp_sections (struct omp_region *region)
6950 tree t, u, vin = NULL, vmain, vnext, l2;
6951 unsigned len;
6952 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
6953 gimple_stmt_iterator si, switch_si;
6954 gimple sections_stmt, stmt, cont;
6955 edge_iterator ei;
6956 edge e;
6957 struct omp_region *inner;
6958 unsigned i, casei;
6959 bool exit_reachable = region->cont != NULL;
6961 gcc_assert (region->exit != NULL);
6962 entry_bb = region->entry;
6963 l0_bb = single_succ (entry_bb);
6964 l1_bb = region->cont;
6965 l2_bb = region->exit;
6966 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
6967 l2 = gimple_block_label (l2_bb);
6968 else
6970 /* This can happen if there are reductions. */
6971 len = EDGE_COUNT (l0_bb->succs);
6972 gcc_assert (len > 0);
6973 e = EDGE_SUCC (l0_bb, len - 1);
6974 si = gsi_last_bb (e->dest);
6975 l2 = NULL_TREE;
6976 if (gsi_end_p (si)
6977 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
6978 l2 = gimple_block_label (e->dest);
6979 else
6980 FOR_EACH_EDGE (e, ei, l0_bb->succs)
6982 si = gsi_last_bb (e->dest);
6983 if (gsi_end_p (si)
6984 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
6986 l2 = gimple_block_label (e->dest);
6987 break;
6991 if (exit_reachable)
6992 default_bb = create_empty_bb (l1_bb->prev_bb);
6993 else
6994 default_bb = create_empty_bb (l0_bb);
6996 /* We will build a switch() with enough cases for all the
6997 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
6998 and a default case to abort if something goes wrong. */
6999 len = EDGE_COUNT (l0_bb->succs);
7001 /* Use vec::quick_push on label_vec throughout, since we know the size
7002 in advance. */
7003 auto_vec<tree> label_vec (len);
7005 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7006 GIMPLE_OMP_SECTIONS statement. */
7007 si = gsi_last_bb (entry_bb);
7008 sections_stmt = gsi_stmt (si);
7009 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7010 vin = gimple_omp_sections_control (sections_stmt);
7011 if (!is_combined_parallel (region))
7013 /* If we are not inside a combined parallel+sections region,
7014 call GOMP_sections_start. */
7015 t = build_int_cst (unsigned_type_node, len - 1);
7016 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7017 stmt = gimple_build_call (u, 1, t);
7019 else
7021 /* Otherwise, call GOMP_sections_next. */
7022 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7023 stmt = gimple_build_call (u, 0);
7025 gimple_call_set_lhs (stmt, vin);
7026 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7027 gsi_remove (&si, true);
7029 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7030 L0_BB. */
7031 switch_si = gsi_last_bb (l0_bb);
7032 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7033 if (exit_reachable)
7035 cont = last_stmt (l1_bb);
7036 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7037 vmain = gimple_omp_continue_control_use (cont);
7038 vnext = gimple_omp_continue_control_def (cont);
7040 else
7042 vmain = vin;
7043 vnext = NULL_TREE;
7046 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7047 label_vec.quick_push (t);
7048 i = 1;
7050 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7051 for (inner = region->inner, casei = 1;
7052 inner;
7053 inner = inner->next, i++, casei++)
7055 basic_block s_entry_bb, s_exit_bb;
7057 /* Skip optional reduction region. */
7058 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7060 --i;
7061 --casei;
7062 continue;
7065 s_entry_bb = inner->entry;
7066 s_exit_bb = inner->exit;
7068 t = gimple_block_label (s_entry_bb);
7069 u = build_int_cst (unsigned_type_node, casei);
7070 u = build_case_label (u, NULL, t);
7071 label_vec.quick_push (u);
7073 si = gsi_last_bb (s_entry_bb);
7074 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7075 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7076 gsi_remove (&si, true);
7077 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7079 if (s_exit_bb == NULL)
7080 continue;
7082 si = gsi_last_bb (s_exit_bb);
7083 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7084 gsi_remove (&si, true);
7086 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7089 /* Error handling code goes in DEFAULT_BB. */
7090 t = gimple_block_label (default_bb);
7091 u = build_case_label (NULL, NULL, t);
7092 make_edge (l0_bb, default_bb, 0);
7093 if (current_loops)
7094 add_bb_to_loop (default_bb, current_loops->tree_root);
7096 stmt = gimple_build_switch (vmain, u, label_vec);
7097 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7098 gsi_remove (&switch_si, true);
7100 si = gsi_start_bb (default_bb);
7101 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7102 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7104 if (exit_reachable)
7106 tree bfn_decl;
7108 /* Code to get the next section goes in L1_BB. */
7109 si = gsi_last_bb (l1_bb);
7110 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7112 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7113 stmt = gimple_build_call (bfn_decl, 0);
7114 gimple_call_set_lhs (stmt, vnext);
7115 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7116 gsi_remove (&si, true);
7118 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7121 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7122 si = gsi_last_bb (l2_bb);
7123 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7124 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7125 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7126 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7127 else
7128 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7129 stmt = gimple_build_call (t, 0);
7130 if (gimple_omp_return_lhs (gsi_stmt (si)))
7131 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7132 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7133 gsi_remove (&si, true);
7135 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7139 /* Expand code for an OpenMP single directive. We've already expanded
7140 much of the code, here we simply place the GOMP_barrier call. */
7142 static void
7143 expand_omp_single (struct omp_region *region)
7145 basic_block entry_bb, exit_bb;
7146 gimple_stmt_iterator si;
7148 entry_bb = region->entry;
7149 exit_bb = region->exit;
7151 si = gsi_last_bb (entry_bb);
7152 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7153 gsi_remove (&si, true);
7154 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7156 si = gsi_last_bb (exit_bb);
7157 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7159 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7160 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7162 gsi_remove (&si, true);
7163 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7167 /* Generic expansion for OpenMP synchronization directives: master,
7168 ordered and critical. All we need to do here is remove the entry
7169 and exit markers for REGION. */
7171 static void
7172 expand_omp_synch (struct omp_region *region)
7174 basic_block entry_bb, exit_bb;
7175 gimple_stmt_iterator si;
7177 entry_bb = region->entry;
7178 exit_bb = region->exit;
7180 si = gsi_last_bb (entry_bb);
7181 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7182 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7183 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7184 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7185 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7186 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7187 gsi_remove (&si, true);
7188 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7190 if (exit_bb)
7192 si = gsi_last_bb (exit_bb);
7193 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7194 gsi_remove (&si, true);
7195 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7199 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7200 operation as a normal volatile load. */
7202 static bool
7203 expand_omp_atomic_load (basic_block load_bb, tree addr,
7204 tree loaded_val, int index)
7206 enum built_in_function tmpbase;
7207 gimple_stmt_iterator gsi;
7208 basic_block store_bb;
7209 location_t loc;
7210 gimple stmt;
7211 tree decl, call, type, itype;
7213 gsi = gsi_last_bb (load_bb);
7214 stmt = gsi_stmt (gsi);
7215 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7216 loc = gimple_location (stmt);
7218 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7219 is smaller than word size, then expand_atomic_load assumes that the load
7220 is atomic. We could avoid the builtin entirely in this case. */
7222 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7223 decl = builtin_decl_explicit (tmpbase);
7224 if (decl == NULL_TREE)
7225 return false;
7227 type = TREE_TYPE (loaded_val);
7228 itype = TREE_TYPE (TREE_TYPE (decl));
7230 call = build_call_expr_loc (loc, decl, 2, addr,
7231 build_int_cst (NULL,
7232 gimple_omp_atomic_seq_cst_p (stmt)
7233 ? MEMMODEL_SEQ_CST
7234 : MEMMODEL_RELAXED));
7235 if (!useless_type_conversion_p (type, itype))
7236 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7237 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7239 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7240 gsi_remove (&gsi, true);
7242 store_bb = single_succ (load_bb);
7243 gsi = gsi_last_bb (store_bb);
7244 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7245 gsi_remove (&gsi, true);
7247 if (gimple_in_ssa_p (cfun))
7248 update_ssa (TODO_update_ssa_no_phi);
7250 return true;
7253 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7254 operation as a normal volatile store. */
7256 static bool
7257 expand_omp_atomic_store (basic_block load_bb, tree addr,
7258 tree loaded_val, tree stored_val, int index)
7260 enum built_in_function tmpbase;
7261 gimple_stmt_iterator gsi;
7262 basic_block store_bb = single_succ (load_bb);
7263 location_t loc;
7264 gimple stmt;
7265 tree decl, call, type, itype;
7266 enum machine_mode imode;
7267 bool exchange;
7269 gsi = gsi_last_bb (load_bb);
7270 stmt = gsi_stmt (gsi);
7271 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7273 /* If the load value is needed, then this isn't a store but an exchange. */
7274 exchange = gimple_omp_atomic_need_value_p (stmt);
7276 gsi = gsi_last_bb (store_bb);
7277 stmt = gsi_stmt (gsi);
7278 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7279 loc = gimple_location (stmt);
7281 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7282 is smaller than word size, then expand_atomic_store assumes that the store
7283 is atomic. We could avoid the builtin entirely in this case. */
7285 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7286 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7287 decl = builtin_decl_explicit (tmpbase);
7288 if (decl == NULL_TREE)
7289 return false;
7291 type = TREE_TYPE (stored_val);
7293 /* Dig out the type of the function's second argument. */
7294 itype = TREE_TYPE (decl);
7295 itype = TYPE_ARG_TYPES (itype);
7296 itype = TREE_CHAIN (itype);
7297 itype = TREE_VALUE (itype);
7298 imode = TYPE_MODE (itype);
7300 if (exchange && !can_atomic_exchange_p (imode, true))
7301 return false;
7303 if (!useless_type_conversion_p (itype, type))
7304 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7305 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7306 build_int_cst (NULL,
7307 gimple_omp_atomic_seq_cst_p (stmt)
7308 ? MEMMODEL_SEQ_CST
7309 : MEMMODEL_RELAXED));
7310 if (exchange)
7312 if (!useless_type_conversion_p (type, itype))
7313 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7314 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7317 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7318 gsi_remove (&gsi, true);
7320 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7321 gsi = gsi_last_bb (load_bb);
7322 gsi_remove (&gsi, true);
7324 if (gimple_in_ssa_p (cfun))
7325 update_ssa (TODO_update_ssa_no_phi);
7327 return true;
7330 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7331 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7332 size of the data type, and thus usable to find the index of the builtin
7333 decl. Returns false if the expression is not of the proper form. */
7335 static bool
7336 expand_omp_atomic_fetch_op (basic_block load_bb,
7337 tree addr, tree loaded_val,
7338 tree stored_val, int index)
7340 enum built_in_function oldbase, newbase, tmpbase;
7341 tree decl, itype, call;
7342 tree lhs, rhs;
7343 basic_block store_bb = single_succ (load_bb);
7344 gimple_stmt_iterator gsi;
7345 gimple stmt;
7346 location_t loc;
7347 enum tree_code code;
7348 bool need_old, need_new;
7349 enum machine_mode imode;
7350 bool seq_cst;
7352 /* We expect to find the following sequences:
7354 load_bb:
7355 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7357 store_bb:
7358 val = tmp OP something; (or: something OP tmp)
7359 GIMPLE_OMP_STORE (val)
7361 ???FIXME: Allow a more flexible sequence.
7362 Perhaps use data flow to pick the statements.
7366 gsi = gsi_after_labels (store_bb);
7367 stmt = gsi_stmt (gsi);
7368 loc = gimple_location (stmt);
7369 if (!is_gimple_assign (stmt))
7370 return false;
7371 gsi_next (&gsi);
7372 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7373 return false;
7374 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7375 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7376 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7377 gcc_checking_assert (!need_old || !need_new);
7379 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7380 return false;
7382 /* Check for one of the supported fetch-op operations. */
7383 code = gimple_assign_rhs_code (stmt);
7384 switch (code)
7386 case PLUS_EXPR:
7387 case POINTER_PLUS_EXPR:
7388 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7389 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7390 break;
7391 case MINUS_EXPR:
7392 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7393 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7394 break;
7395 case BIT_AND_EXPR:
7396 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7397 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7398 break;
7399 case BIT_IOR_EXPR:
7400 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7401 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7402 break;
7403 case BIT_XOR_EXPR:
7404 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7405 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7406 break;
7407 default:
7408 return false;
7411 /* Make sure the expression is of the proper form. */
7412 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7413 rhs = gimple_assign_rhs2 (stmt);
7414 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7415 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7416 rhs = gimple_assign_rhs1 (stmt);
7417 else
7418 return false;
7420 tmpbase = ((enum built_in_function)
7421 ((need_new ? newbase : oldbase) + index + 1));
7422 decl = builtin_decl_explicit (tmpbase);
7423 if (decl == NULL_TREE)
7424 return false;
7425 itype = TREE_TYPE (TREE_TYPE (decl));
7426 imode = TYPE_MODE (itype);
7428 /* We could test all of the various optabs involved, but the fact of the
7429 matter is that (with the exception of i486 vs i586 and xadd) all targets
7430 that support any atomic operaton optab also implements compare-and-swap.
7431 Let optabs.c take care of expanding any compare-and-swap loop. */
7432 if (!can_compare_and_swap_p (imode, true))
7433 return false;
7435 gsi = gsi_last_bb (load_bb);
7436 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7438 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7439 It only requires that the operation happen atomically. Thus we can
7440 use the RELAXED memory model. */
7441 call = build_call_expr_loc (loc, decl, 3, addr,
7442 fold_convert_loc (loc, itype, rhs),
7443 build_int_cst (NULL,
7444 seq_cst ? MEMMODEL_SEQ_CST
7445 : MEMMODEL_RELAXED));
7447 if (need_old || need_new)
7449 lhs = need_old ? loaded_val : stored_val;
7450 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7451 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7453 else
7454 call = fold_convert_loc (loc, void_type_node, call);
7455 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7456 gsi_remove (&gsi, true);
7458 gsi = gsi_last_bb (store_bb);
7459 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7460 gsi_remove (&gsi, true);
7461 gsi = gsi_last_bb (store_bb);
7462 gsi_remove (&gsi, true);
7464 if (gimple_in_ssa_p (cfun))
7465 update_ssa (TODO_update_ssa_no_phi);
7467 return true;
7470 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7472 oldval = *addr;
7473 repeat:
7474 newval = rhs; // with oldval replacing *addr in rhs
7475 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7476 if (oldval != newval)
7477 goto repeat;
7479 INDEX is log2 of the size of the data type, and thus usable to find the
7480 index of the builtin decl. */
7482 static bool
7483 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7484 tree addr, tree loaded_val, tree stored_val,
7485 int index)
7487 tree loadedi, storedi, initial, new_storedi, old_vali;
7488 tree type, itype, cmpxchg, iaddr;
7489 gimple_stmt_iterator si;
7490 basic_block loop_header = single_succ (load_bb);
7491 gimple phi, stmt;
7492 edge e;
7493 enum built_in_function fncode;
7495 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7496 order to use the RELAXED memory model effectively. */
7497 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7498 + index + 1);
7499 cmpxchg = builtin_decl_explicit (fncode);
7500 if (cmpxchg == NULL_TREE)
7501 return false;
7502 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7503 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7505 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7506 return false;
7508 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7509 si = gsi_last_bb (load_bb);
7510 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7512 /* For floating-point values, we'll need to view-convert them to integers
7513 so that we can perform the atomic compare and swap. Simplify the
7514 following code by always setting up the "i"ntegral variables. */
7515 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7517 tree iaddr_val;
7519 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7520 true), NULL);
7521 iaddr_val
7522 = force_gimple_operand_gsi (&si,
7523 fold_convert (TREE_TYPE (iaddr), addr),
7524 false, NULL_TREE, true, GSI_SAME_STMT);
7525 stmt = gimple_build_assign (iaddr, iaddr_val);
7526 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7527 loadedi = create_tmp_var (itype, NULL);
7528 if (gimple_in_ssa_p (cfun))
7529 loadedi = make_ssa_name (loadedi, NULL);
7531 else
7533 iaddr = addr;
7534 loadedi = loaded_val;
7537 initial
7538 = force_gimple_operand_gsi (&si,
7539 build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
7540 iaddr,
7541 build_int_cst (TREE_TYPE (iaddr), 0)),
7542 true, NULL_TREE, true, GSI_SAME_STMT);
7544 /* Move the value to the LOADEDI temporary. */
7545 if (gimple_in_ssa_p (cfun))
7547 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
7548 phi = create_phi_node (loadedi, loop_header);
7549 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
7550 initial);
7552 else
7553 gsi_insert_before (&si,
7554 gimple_build_assign (loadedi, initial),
7555 GSI_SAME_STMT);
7556 if (loadedi != loaded_val)
7558 gimple_stmt_iterator gsi2;
7559 tree x;
7561 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
7562 gsi2 = gsi_start_bb (loop_header);
7563 if (gimple_in_ssa_p (cfun))
7565 gimple stmt;
7566 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7567 true, GSI_SAME_STMT);
7568 stmt = gimple_build_assign (loaded_val, x);
7569 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
7571 else
7573 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
7574 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7575 true, GSI_SAME_STMT);
7578 gsi_remove (&si, true);
7580 si = gsi_last_bb (store_bb);
7581 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7583 if (iaddr == addr)
7584 storedi = stored_val;
7585 else
7586 storedi =
7587 force_gimple_operand_gsi (&si,
7588 build1 (VIEW_CONVERT_EXPR, itype,
7589 stored_val), true, NULL_TREE, true,
7590 GSI_SAME_STMT);
7592 /* Build the compare&swap statement. */
7593 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
7594 new_storedi = force_gimple_operand_gsi (&si,
7595 fold_convert (TREE_TYPE (loadedi),
7596 new_storedi),
7597 true, NULL_TREE,
7598 true, GSI_SAME_STMT);
7600 if (gimple_in_ssa_p (cfun))
7601 old_vali = loadedi;
7602 else
7604 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
7605 stmt = gimple_build_assign (old_vali, loadedi);
7606 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7608 stmt = gimple_build_assign (loadedi, new_storedi);
7609 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7612 /* Note that we always perform the comparison as an integer, even for
7613 floating point. This allows the atomic operation to properly
7614 succeed even with NaNs and -0.0. */
7615 stmt = gimple_build_cond_empty
7616 (build2 (NE_EXPR, boolean_type_node,
7617 new_storedi, old_vali));
7618 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7620 /* Update cfg. */
7621 e = single_succ_edge (store_bb);
7622 e->flags &= ~EDGE_FALLTHRU;
7623 e->flags |= EDGE_FALSE_VALUE;
7625 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
7627 /* Copy the new value to loadedi (we already did that before the condition
7628 if we are not in SSA). */
7629 if (gimple_in_ssa_p (cfun))
7631 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
7632 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
7635 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
7636 gsi_remove (&si, true);
7638 struct loop *loop = alloc_loop ();
7639 loop->header = loop_header;
7640 loop->latch = store_bb;
7641 add_loop (loop, loop_header->loop_father);
7643 if (gimple_in_ssa_p (cfun))
7644 update_ssa (TODO_update_ssa_no_phi);
7646 return true;
7649 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7651 GOMP_atomic_start ();
7652 *addr = rhs;
7653 GOMP_atomic_end ();
7655 The result is not globally atomic, but works so long as all parallel
7656 references are within #pragma omp atomic directives. According to
7657 responses received from omp@openmp.org, appears to be within spec.
7658 Which makes sense, since that's how several other compilers handle
7659 this situation as well.
7660 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
7661 expanding. STORED_VAL is the operand of the matching
7662 GIMPLE_OMP_ATOMIC_STORE.
7664 We replace
7665 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
7666 loaded_val = *addr;
7668 and replace
7669 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
7670 *addr = stored_val;
7673 static bool
7674 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
7675 tree addr, tree loaded_val, tree stored_val)
7677 gimple_stmt_iterator si;
7678 gimple stmt;
7679 tree t;
7681 si = gsi_last_bb (load_bb);
7682 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7684 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
7685 t = build_call_expr (t, 0);
7686 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7688 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
7689 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7690 gsi_remove (&si, true);
7692 si = gsi_last_bb (store_bb);
7693 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7695 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
7696 stored_val);
7697 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7699 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
7700 t = build_call_expr (t, 0);
7701 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7702 gsi_remove (&si, true);
7704 if (gimple_in_ssa_p (cfun))
7705 update_ssa (TODO_update_ssa_no_phi);
7706 return true;
7709 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
7710 using expand_omp_atomic_fetch_op. If it failed, we try to
7711 call expand_omp_atomic_pipeline, and if it fails too, the
7712 ultimate fallback is wrapping the operation in a mutex
7713 (expand_omp_atomic_mutex). REGION is the atomic region built
7714 by build_omp_regions_1(). */
7716 static void
7717 expand_omp_atomic (struct omp_region *region)
7719 basic_block load_bb = region->entry, store_bb = region->exit;
7720 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
7721 tree loaded_val = gimple_omp_atomic_load_lhs (load);
7722 tree addr = gimple_omp_atomic_load_rhs (load);
7723 tree stored_val = gimple_omp_atomic_store_val (store);
7724 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7725 HOST_WIDE_INT index;
7727 /* Make sure the type is one of the supported sizes. */
7728 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
7729 index = exact_log2 (index);
7730 if (index >= 0 && index <= 4)
7732 unsigned int align = TYPE_ALIGN_UNIT (type);
7734 /* __sync builtins require strict data alignment. */
7735 if (exact_log2 (align) >= index)
7737 /* Atomic load. */
7738 if (loaded_val == stored_val
7739 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7740 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7741 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7742 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
7743 return;
7745 /* Atomic store. */
7746 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7747 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7748 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7749 && store_bb == single_succ (load_bb)
7750 && first_stmt (store_bb) == store
7751 && expand_omp_atomic_store (load_bb, addr, loaded_val,
7752 stored_val, index))
7753 return;
7755 /* When possible, use specialized atomic update functions. */
7756 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
7757 && store_bb == single_succ (load_bb)
7758 && expand_omp_atomic_fetch_op (load_bb, addr,
7759 loaded_val, stored_val, index))
7760 return;
7762 /* If we don't have specialized __sync builtins, try and implement
7763 as a compare and swap loop. */
7764 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
7765 loaded_val, stored_val, index))
7766 return;
7770 /* The ultimate fallback is wrapping the operation in a mutex. */
7771 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
7775 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
7777 static void
7778 expand_omp_target (struct omp_region *region)
7780 basic_block entry_bb, exit_bb, new_bb;
7781 struct function *child_cfun = NULL;
7782 tree child_fn = NULL_TREE, block, t;
7783 gimple_stmt_iterator gsi;
7784 gimple entry_stmt, stmt;
7785 edge e;
7787 entry_stmt = last_stmt (region->entry);
7788 new_bb = region->entry;
7789 int kind = gimple_omp_target_kind (entry_stmt);
7790 if (kind == GF_OMP_TARGET_KIND_REGION)
7792 child_fn = gimple_omp_target_child_fn (entry_stmt);
7793 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7796 entry_bb = region->entry;
7797 exit_bb = region->exit;
7799 if (kind == GF_OMP_TARGET_KIND_REGION)
7801 unsigned srcidx, dstidx, num;
7803 /* If the target region needs data sent from the parent
7804 function, then the very first statement (except possible
7805 tree profile counter updates) of the parallel body
7806 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7807 &.OMP_DATA_O is passed as an argument to the child function,
7808 we need to replace it with the argument as seen by the child
7809 function.
7811 In most cases, this will end up being the identity assignment
7812 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7813 a function call that has been inlined, the original PARM_DECL
7814 .OMP_DATA_I may have been converted into a different local
7815 variable. In which case, we need to keep the assignment. */
7816 if (gimple_omp_target_data_arg (entry_stmt))
7818 basic_block entry_succ_bb = single_succ (entry_bb);
7819 gimple_stmt_iterator gsi;
7820 tree arg;
7821 gimple tgtcopy_stmt = NULL;
7822 tree sender
7823 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
7825 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7827 gcc_assert (!gsi_end_p (gsi));
7828 stmt = gsi_stmt (gsi);
7829 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7830 continue;
7832 if (gimple_num_ops (stmt) == 2)
7834 tree arg = gimple_assign_rhs1 (stmt);
7836 /* We're ignoring the subcode because we're
7837 effectively doing a STRIP_NOPS. */
7839 if (TREE_CODE (arg) == ADDR_EXPR
7840 && TREE_OPERAND (arg, 0) == sender)
7842 tgtcopy_stmt = stmt;
7843 break;
7848 gcc_assert (tgtcopy_stmt != NULL);
7849 arg = DECL_ARGUMENTS (child_fn);
7851 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
7852 gsi_remove (&gsi, true);
7855 /* Declare local variables needed in CHILD_CFUN. */
7856 block = DECL_INITIAL (child_fn);
7857 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7858 /* The gimplifier could record temporaries in target block
7859 rather than in containing function's local_decls chain,
7860 which would mean cgraph missed finalizing them. Do it now. */
7861 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7862 if (TREE_CODE (t) == VAR_DECL
7863 && TREE_STATIC (t)
7864 && !DECL_EXTERNAL (t))
7865 varpool_finalize_decl (t);
7866 DECL_SAVED_TREE (child_fn) = NULL;
7867 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7868 gimple_set_body (child_fn, NULL);
7869 TREE_USED (block) = 1;
7871 /* Reset DECL_CONTEXT on function arguments. */
7872 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7873 DECL_CONTEXT (t) = child_fn;
7875 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
7876 so that it can be moved to the child function. */
7877 gsi = gsi_last_bb (entry_bb);
7878 stmt = gsi_stmt (gsi);
7879 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
7880 && gimple_omp_target_kind (stmt)
7881 == GF_OMP_TARGET_KIND_REGION);
7882 gsi_remove (&gsi, true);
7883 e = split_block (entry_bb, stmt);
7884 entry_bb = e->dest;
7885 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7887 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
7888 if (exit_bb)
7890 gsi = gsi_last_bb (exit_bb);
7891 gcc_assert (!gsi_end_p (gsi)
7892 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7893 stmt = gimple_build_return (NULL);
7894 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7895 gsi_remove (&gsi, true);
7898 /* Move the target region into CHILD_CFUN. */
7900 block = gimple_block (entry_stmt);
7902 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7903 if (exit_bb)
7904 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7905 /* When the OMP expansion process cannot guarantee an up-to-date
7906 loop tree arrange for the child function to fixup loops. */
7907 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7908 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7910 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7911 num = vec_safe_length (child_cfun->local_decls);
7912 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7914 t = (*child_cfun->local_decls)[srcidx];
7915 if (DECL_CONTEXT (t) == cfun->decl)
7916 continue;
7917 if (srcidx != dstidx)
7918 (*child_cfun->local_decls)[dstidx] = t;
7919 dstidx++;
7921 if (dstidx != num)
7922 vec_safe_truncate (child_cfun->local_decls, dstidx);
7924 /* Inform the callgraph about the new function. */
7925 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
7926 cgraph_add_new_function (child_fn, true);
7928 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7929 fixed in a following pass. */
7930 push_cfun (child_cfun);
7931 rebuild_cgraph_edges ();
7933 /* Some EH regions might become dead, see PR34608. If
7934 pass_cleanup_cfg isn't the first pass to happen with the
7935 new child, these dead EH edges might cause problems.
7936 Clean them up now. */
7937 if (flag_exceptions)
7939 basic_block bb;
7940 bool changed = false;
7942 FOR_EACH_BB (bb)
7943 changed |= gimple_purge_dead_eh_edges (bb);
7944 if (changed)
7945 cleanup_tree_cfg ();
7947 pop_cfun ();
7950 /* Emit a library call to launch the target region, or do data
7951 transfers. */
7952 tree t1, t2, t3, t4, device, cond, c, clauses;
7953 enum built_in_function start_ix;
7954 location_t clause_loc;
7956 clauses = gimple_omp_target_clauses (entry_stmt);
7958 if (kind == GF_OMP_TARGET_KIND_REGION)
7959 start_ix = BUILT_IN_GOMP_TARGET;
7960 else if (kind == GF_OMP_TARGET_KIND_DATA)
7961 start_ix = BUILT_IN_GOMP_TARGET_DATA;
7962 else
7963 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
7965 /* By default, the value of DEVICE is -1 (let runtime library choose)
7966 and there is no conditional. */
7967 cond = NULL_TREE;
7968 device = build_int_cst (integer_type_node, -1);
7970 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
7971 if (c)
7972 cond = OMP_CLAUSE_IF_EXPR (c);
7974 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
7975 if (c)
7977 device = OMP_CLAUSE_DEVICE_ID (c);
7978 clause_loc = OMP_CLAUSE_LOCATION (c);
7980 else
7981 clause_loc = gimple_location (entry_stmt);
7983 /* Ensure 'device' is of the correct type. */
7984 device = fold_convert_loc (clause_loc, integer_type_node, device);
7986 /* If we found the clause 'if (cond)', build
7987 (cond ? device : -2). */
7988 if (cond)
7990 cond = gimple_boolify (cond);
7992 basic_block cond_bb, then_bb, else_bb;
7993 edge e;
7994 tree tmp_var;
7996 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
7997 if (kind != GF_OMP_TARGET_KIND_REGION)
7999 gsi = gsi_last_bb (new_bb);
8000 gsi_prev (&gsi);
8001 e = split_block (new_bb, gsi_stmt (gsi));
8003 else
8004 e = split_block (new_bb, NULL);
8005 cond_bb = e->src;
8006 new_bb = e->dest;
8007 remove_edge (e);
8009 then_bb = create_empty_bb (cond_bb);
8010 else_bb = create_empty_bb (then_bb);
8011 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8012 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8014 stmt = gimple_build_cond_empty (cond);
8015 gsi = gsi_last_bb (cond_bb);
8016 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8018 gsi = gsi_start_bb (then_bb);
8019 stmt = gimple_build_assign (tmp_var, device);
8020 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8022 gsi = gsi_start_bb (else_bb);
8023 stmt = gimple_build_assign (tmp_var,
8024 build_int_cst (integer_type_node, -2));
8025 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8027 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8028 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8029 if (current_loops)
8031 add_bb_to_loop (then_bb, cond_bb->loop_father);
8032 add_bb_to_loop (else_bb, cond_bb->loop_father);
8034 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8035 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8037 device = tmp_var;
8040 gsi = gsi_last_bb (new_bb);
8041 t = gimple_omp_target_data_arg (entry_stmt);
8042 if (t == NULL)
8044 t1 = size_zero_node;
8045 t2 = build_zero_cst (ptr_type_node);
8046 t3 = t2;
8047 t4 = t2;
8049 else
8051 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8052 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8053 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8054 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8055 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8058 gimple g;
8059 /* FIXME: This will be address of
8060 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8061 symbol, as soon as the linker plugin is able to create it for us. */
8062 tree openmp_target = build_zero_cst (ptr_type_node);
8063 if (kind == GF_OMP_TARGET_KIND_REGION)
8065 tree fnaddr = build_fold_addr_expr (child_fn);
8066 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8067 device, fnaddr, openmp_target, t1, t2, t3, t4);
8069 else
8070 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8071 device, openmp_target, t1, t2, t3, t4);
8072 gimple_set_location (g, gimple_location (entry_stmt));
8073 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8074 if (kind != GF_OMP_TARGET_KIND_REGION)
8076 g = gsi_stmt (gsi);
8077 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8078 gsi_remove (&gsi, true);
8080 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8082 gsi = gsi_last_bb (region->exit);
8083 g = gsi_stmt (gsi);
8084 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8085 gsi_remove (&gsi, true);
8090 /* Expand the parallel region tree rooted at REGION. Expansion
8091 proceeds in depth-first order. Innermost regions are expanded
8092 first. This way, parallel regions that require a new function to
8093 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8094 internal dependencies in their body. */
8096 static void
8097 expand_omp (struct omp_region *region)
8099 while (region)
8101 location_t saved_location;
8102 gimple inner_stmt = NULL;
8104 /* First, determine whether this is a combined parallel+workshare
8105 region. */
8106 if (region->type == GIMPLE_OMP_PARALLEL)
8107 determine_parallel_type (region);
8109 if (region->type == GIMPLE_OMP_FOR
8110 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8111 inner_stmt = last_stmt (region->inner->entry);
8113 if (region->inner)
8114 expand_omp (region->inner);
8116 saved_location = input_location;
8117 if (gimple_has_location (last_stmt (region->entry)))
8118 input_location = gimple_location (last_stmt (region->entry));
8120 switch (region->type)
8122 case GIMPLE_OMP_PARALLEL:
8123 case GIMPLE_OMP_TASK:
8124 expand_omp_taskreg (region);
8125 break;
8127 case GIMPLE_OMP_FOR:
8128 expand_omp_for (region, inner_stmt);
8129 break;
8131 case GIMPLE_OMP_SECTIONS:
8132 expand_omp_sections (region);
8133 break;
8135 case GIMPLE_OMP_SECTION:
8136 /* Individual omp sections are handled together with their
8137 parent GIMPLE_OMP_SECTIONS region. */
8138 break;
8140 case GIMPLE_OMP_SINGLE:
8141 expand_omp_single (region);
8142 break;
8144 case GIMPLE_OMP_MASTER:
8145 case GIMPLE_OMP_TASKGROUP:
8146 case GIMPLE_OMP_ORDERED:
8147 case GIMPLE_OMP_CRITICAL:
8148 case GIMPLE_OMP_TEAMS:
8149 expand_omp_synch (region);
8150 break;
8152 case GIMPLE_OMP_ATOMIC_LOAD:
8153 expand_omp_atomic (region);
8154 break;
8156 case GIMPLE_OMP_TARGET:
8157 expand_omp_target (region);
8158 break;
8160 default:
8161 gcc_unreachable ();
8164 input_location = saved_location;
8165 region = region->next;
8170 /* Helper for build_omp_regions. Scan the dominator tree starting at
8171 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8172 true, the function ends once a single tree is built (otherwise, whole
8173 forest of OMP constructs may be built). */
8175 static void
8176 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8177 bool single_tree)
8179 gimple_stmt_iterator gsi;
8180 gimple stmt;
8181 basic_block son;
8183 gsi = gsi_last_bb (bb);
8184 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8186 struct omp_region *region;
8187 enum gimple_code code;
8189 stmt = gsi_stmt (gsi);
8190 code = gimple_code (stmt);
8191 if (code == GIMPLE_OMP_RETURN)
8193 /* STMT is the return point out of region PARENT. Mark it
8194 as the exit point and make PARENT the immediately
8195 enclosing region. */
8196 gcc_assert (parent);
8197 region = parent;
8198 region->exit = bb;
8199 parent = parent->outer;
8201 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8203 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8204 GIMPLE_OMP_RETURN, but matches with
8205 GIMPLE_OMP_ATOMIC_LOAD. */
8206 gcc_assert (parent);
8207 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8208 region = parent;
8209 region->exit = bb;
8210 parent = parent->outer;
8213 else if (code == GIMPLE_OMP_CONTINUE)
8215 gcc_assert (parent);
8216 parent->cont = bb;
8218 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8220 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8221 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8224 else if (code == GIMPLE_OMP_TARGET
8225 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8226 new_omp_region (bb, code, parent);
8227 else
8229 /* Otherwise, this directive becomes the parent for a new
8230 region. */
8231 region = new_omp_region (bb, code, parent);
8232 parent = region;
8236 if (single_tree && !parent)
8237 return;
8239 for (son = first_dom_son (CDI_DOMINATORS, bb);
8240 son;
8241 son = next_dom_son (CDI_DOMINATORS, son))
8242 build_omp_regions_1 (son, parent, single_tree);
8245 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8246 root_omp_region. */
8248 static void
8249 build_omp_regions_root (basic_block root)
8251 gcc_assert (root_omp_region == NULL);
8252 build_omp_regions_1 (root, NULL, true);
8253 gcc_assert (root_omp_region != NULL);
8256 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8258 void
8259 omp_expand_local (basic_block head)
8261 build_omp_regions_root (head);
8262 if (dump_file && (dump_flags & TDF_DETAILS))
8264 fprintf (dump_file, "\nOMP region tree\n\n");
8265 dump_omp_region (dump_file, root_omp_region, 0);
8266 fprintf (dump_file, "\n");
8269 remove_exit_barriers (root_omp_region);
8270 expand_omp (root_omp_region);
8272 free_omp_regions ();
8275 /* Scan the CFG and build a tree of OMP regions. Return the root of
8276 the OMP region tree. */
8278 static void
8279 build_omp_regions (void)
8281 gcc_assert (root_omp_region == NULL);
8282 calculate_dominance_info (CDI_DOMINATORS);
8283 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8286 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8288 static unsigned int
8289 execute_expand_omp (void)
8291 build_omp_regions ();
8293 if (!root_omp_region)
8294 return 0;
8296 if (dump_file)
8298 fprintf (dump_file, "\nOMP region tree\n\n");
8299 dump_omp_region (dump_file, root_omp_region, 0);
8300 fprintf (dump_file, "\n");
8303 remove_exit_barriers (root_omp_region);
8305 expand_omp (root_omp_region);
8307 cleanup_tree_cfg ();
8309 free_omp_regions ();
8311 return 0;
8314 /* OMP expansion -- the default pass, run before creation of SSA form. */
8316 static bool
8317 gate_expand_omp (void)
8319 return ((flag_openmp != 0 || flag_openmp_simd != 0
8320 || flag_enable_cilkplus != 0) && !seen_error ());
8323 namespace {
8325 const pass_data pass_data_expand_omp =
8327 GIMPLE_PASS, /* type */
8328 "ompexp", /* name */
8329 OPTGROUP_NONE, /* optinfo_flags */
8330 true, /* has_gate */
8331 true, /* has_execute */
8332 TV_NONE, /* tv_id */
8333 PROP_gimple_any, /* properties_required */
8334 0, /* properties_provided */
8335 0, /* properties_destroyed */
8336 0, /* todo_flags_start */
8337 0, /* todo_flags_finish */
8340 class pass_expand_omp : public gimple_opt_pass
8342 public:
8343 pass_expand_omp (gcc::context *ctxt)
8344 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8347 /* opt_pass methods: */
8348 bool gate () { return gate_expand_omp (); }
8349 unsigned int execute () { return execute_expand_omp (); }
8351 }; // class pass_expand_omp
8353 } // anon namespace
8355 gimple_opt_pass *
8356 make_pass_expand_omp (gcc::context *ctxt)
8358 return new pass_expand_omp (ctxt);
8361 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8363 /* If ctx is a worksharing context inside of a cancellable parallel
8364 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8365 and conditional branch to parallel's cancel_label to handle
8366 cancellation in the implicit barrier. */
8368 static void
8369 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8371 gimple omp_return = gimple_seq_last_stmt (*body);
8372 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8373 if (gimple_omp_return_nowait_p (omp_return))
8374 return;
8375 if (ctx->outer
8376 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8377 && ctx->outer->cancellable)
8379 tree lhs = create_tmp_var (boolean_type_node, NULL);
8380 gimple_omp_return_set_lhs (omp_return, lhs);
8381 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8382 gimple g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
8383 ctx->outer->cancel_label, fallthru_label);
8384 gimple_seq_add_stmt (body, g);
8385 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8389 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8390 CTX is the enclosing OMP context for the current statement. */
8392 static void
8393 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8395 tree block, control;
8396 gimple_stmt_iterator tgsi;
8397 gimple stmt, new_stmt, bind, t;
8398 gimple_seq ilist, dlist, olist, new_body;
8400 stmt = gsi_stmt (*gsi_p);
8402 push_gimplify_context ();
8404 dlist = NULL;
8405 ilist = NULL;
8406 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8407 &ilist, &dlist, ctx, NULL);
8409 new_body = gimple_omp_body (stmt);
8410 gimple_omp_set_body (stmt, NULL);
8411 tgsi = gsi_start (new_body);
8412 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8414 omp_context *sctx;
8415 gimple sec_start;
8417 sec_start = gsi_stmt (tgsi);
8418 sctx = maybe_lookup_ctx (sec_start);
8419 gcc_assert (sctx);
8421 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8422 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8423 GSI_CONTINUE_LINKING);
8424 gimple_omp_set_body (sec_start, NULL);
8426 if (gsi_one_before_end_p (tgsi))
8428 gimple_seq l = NULL;
8429 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8430 &l, ctx);
8431 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8432 gimple_omp_section_set_last (sec_start);
8435 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8436 GSI_CONTINUE_LINKING);
8439 block = make_node (BLOCK);
8440 bind = gimple_build_bind (NULL, new_body, block);
8442 olist = NULL;
8443 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8445 block = make_node (BLOCK);
8446 new_stmt = gimple_build_bind (NULL, NULL, block);
8447 gsi_replace (gsi_p, new_stmt, true);
8449 pop_gimplify_context (new_stmt);
8450 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8451 BLOCK_VARS (block) = gimple_bind_vars (bind);
8452 if (BLOCK_VARS (block))
8453 TREE_USED (block) = 1;
8455 new_body = NULL;
8456 gimple_seq_add_seq (&new_body, ilist);
8457 gimple_seq_add_stmt (&new_body, stmt);
8458 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8459 gimple_seq_add_stmt (&new_body, bind);
8461 control = create_tmp_var (unsigned_type_node, ".section");
8462 t = gimple_build_omp_continue (control, control);
8463 gimple_omp_sections_set_control (stmt, control);
8464 gimple_seq_add_stmt (&new_body, t);
8466 gimple_seq_add_seq (&new_body, olist);
8467 if (ctx->cancellable)
8468 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8469 gimple_seq_add_seq (&new_body, dlist);
8471 new_body = maybe_catch_exception (new_body);
8473 t = gimple_build_omp_return
8474 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8475 OMP_CLAUSE_NOWAIT));
8476 gimple_seq_add_stmt (&new_body, t);
8477 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8479 gimple_bind_set_body (new_stmt, new_body);
8483 /* A subroutine of lower_omp_single. Expand the simple form of
8484 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8486 if (GOMP_single_start ())
8487 BODY;
8488 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8490 FIXME. It may be better to delay expanding the logic of this until
8491 pass_expand_omp. The expanded logic may make the job more difficult
8492 to a synchronization analysis pass. */
8494 static void
8495 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8497 location_t loc = gimple_location (single_stmt);
8498 tree tlabel = create_artificial_label (loc);
8499 tree flabel = create_artificial_label (loc);
8500 gimple call, cond;
8501 tree lhs, decl;
8503 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8504 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8505 call = gimple_build_call (decl, 0);
8506 gimple_call_set_lhs (call, lhs);
8507 gimple_seq_add_stmt (pre_p, call);
8509 cond = gimple_build_cond (EQ_EXPR, lhs,
8510 fold_convert_loc (loc, TREE_TYPE (lhs),
8511 boolean_true_node),
8512 tlabel, flabel);
8513 gimple_seq_add_stmt (pre_p, cond);
8514 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8515 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8516 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8520 /* A subroutine of lower_omp_single. Expand the simple form of
8521 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8523 #pragma omp single copyprivate (a, b, c)
8525 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8528 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8530 BODY;
8531 copyout.a = a;
8532 copyout.b = b;
8533 copyout.c = c;
8534 GOMP_single_copy_end (&copyout);
8536 else
8538 a = copyout_p->a;
8539 b = copyout_p->b;
8540 c = copyout_p->c;
8542 GOMP_barrier ();
8545 FIXME. It may be better to delay expanding the logic of this until
8546 pass_expand_omp. The expanded logic may make the job more difficult
8547 to a synchronization analysis pass. */
8549 static void
8550 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
8552 tree ptr_type, t, l0, l1, l2, bfn_decl;
8553 gimple_seq copyin_seq;
8554 location_t loc = gimple_location (single_stmt);
8556 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8558 ptr_type = build_pointer_type (ctx->record_type);
8559 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8561 l0 = create_artificial_label (loc);
8562 l1 = create_artificial_label (loc);
8563 l2 = create_artificial_label (loc);
8565 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8566 t = build_call_expr_loc (loc, bfn_decl, 0);
8567 t = fold_convert_loc (loc, ptr_type, t);
8568 gimplify_assign (ctx->receiver_decl, t, pre_p);
8570 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8571 build_int_cst (ptr_type, 0));
8572 t = build3 (COND_EXPR, void_type_node, t,
8573 build_and_jump (&l0), build_and_jump (&l1));
8574 gimplify_and_add (t, pre_p);
8576 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8578 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8580 copyin_seq = NULL;
8581 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8582 &copyin_seq, ctx);
8584 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8585 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8586 t = build_call_expr_loc (loc, bfn_decl, 1, t);
8587 gimplify_and_add (t, pre_p);
8589 t = build_and_jump (&l2);
8590 gimplify_and_add (t, pre_p);
8592 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8594 gimple_seq_add_seq (pre_p, copyin_seq);
8596 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8600 /* Expand code for an OpenMP single directive. */
8602 static void
8603 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8605 tree block;
8606 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
8607 gimple_seq bind_body, bind_body_tail = NULL, dlist;
8609 push_gimplify_context ();
8611 block = make_node (BLOCK);
8612 bind = gimple_build_bind (NULL, NULL, block);
8613 gsi_replace (gsi_p, bind, true);
8614 bind_body = NULL;
8615 dlist = NULL;
8616 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8617 &bind_body, &dlist, ctx, NULL);
8618 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8620 gimple_seq_add_stmt (&bind_body, single_stmt);
8622 if (ctx->record_type)
8623 lower_omp_single_copy (single_stmt, &bind_body, ctx);
8624 else
8625 lower_omp_single_simple (single_stmt, &bind_body);
8627 gimple_omp_set_body (single_stmt, NULL);
8629 gimple_seq_add_seq (&bind_body, dlist);
8631 bind_body = maybe_catch_exception (bind_body);
8633 t = gimple_build_omp_return
8634 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
8635 OMP_CLAUSE_NOWAIT));
8636 gimple_seq_add_stmt (&bind_body_tail, t);
8637 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
8638 if (ctx->record_type)
8640 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8641 tree clobber = build_constructor (ctx->record_type, NULL);
8642 TREE_THIS_VOLATILE (clobber) = 1;
8643 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8644 clobber), GSI_SAME_STMT);
8646 gimple_seq_add_seq (&bind_body, bind_body_tail);
8647 gimple_bind_set_body (bind, bind_body);
8649 pop_gimplify_context (bind);
8651 gimple_bind_append_vars (bind, ctx->block_vars);
8652 BLOCK_VARS (block) = ctx->block_vars;
8653 if (BLOCK_VARS (block))
8654 TREE_USED (block) = 1;
8658 /* Expand code for an OpenMP master directive. */
8660 static void
8661 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8663 tree block, lab = NULL, x, bfn_decl;
8664 gimple stmt = gsi_stmt (*gsi_p), bind;
8665 location_t loc = gimple_location (stmt);
8666 gimple_seq tseq;
8668 push_gimplify_context ();
8670 block = make_node (BLOCK);
8671 bind = gimple_build_bind (NULL, NULL, block);
8672 gsi_replace (gsi_p, bind, true);
8673 gimple_bind_add_stmt (bind, stmt);
8675 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8676 x = build_call_expr_loc (loc, bfn_decl, 0);
8677 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
8678 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
8679 tseq = NULL;
8680 gimplify_and_add (x, &tseq);
8681 gimple_bind_add_seq (bind, tseq);
8683 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8684 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8685 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8686 gimple_omp_set_body (stmt, NULL);
8688 gimple_bind_add_stmt (bind, gimple_build_label (lab));
8690 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8692 pop_gimplify_context (bind);
8694 gimple_bind_append_vars (bind, ctx->block_vars);
8695 BLOCK_VARS (block) = ctx->block_vars;
8699 /* Expand code for an OpenMP taskgroup directive. */
8701 static void
8702 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8704 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8705 tree block = make_node (BLOCK);
8707 bind = gimple_build_bind (NULL, NULL, block);
8708 gsi_replace (gsi_p, bind, true);
8709 gimple_bind_add_stmt (bind, stmt);
8711 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
8713 gimple_bind_add_stmt (bind, x);
8715 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8716 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8717 gimple_omp_set_body (stmt, NULL);
8719 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8721 gimple_bind_append_vars (bind, ctx->block_vars);
8722 BLOCK_VARS (block) = ctx->block_vars;
8726 /* Expand code for an OpenMP ordered directive. */
8728 static void
8729 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8731 tree block;
8732 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8734 push_gimplify_context ();
8736 block = make_node (BLOCK);
8737 bind = gimple_build_bind (NULL, NULL, block);
8738 gsi_replace (gsi_p, bind, true);
8739 gimple_bind_add_stmt (bind, stmt);
8741 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
8743 gimple_bind_add_stmt (bind, x);
8745 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8746 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8747 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8748 gimple_omp_set_body (stmt, NULL);
8750 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
8751 gimple_bind_add_stmt (bind, x);
8753 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8755 pop_gimplify_context (bind);
8757 gimple_bind_append_vars (bind, ctx->block_vars);
8758 BLOCK_VARS (block) = gimple_bind_vars (bind);
8762 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
8763 substitution of a couple of function calls. But in the NAMED case,
8764 requires that languages coordinate a symbol name. It is therefore
8765 best put here in common code. */
8767 static GTY((param1_is (tree), param2_is (tree)))
8768 splay_tree critical_name_mutexes;
8770 static void
8771 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8773 tree block;
8774 tree name, lock, unlock;
8775 gimple stmt = gsi_stmt (*gsi_p), bind;
8776 location_t loc = gimple_location (stmt);
8777 gimple_seq tbody;
8779 name = gimple_omp_critical_name (stmt);
8780 if (name)
8782 tree decl;
8783 splay_tree_node n;
8785 if (!critical_name_mutexes)
8786 critical_name_mutexes
8787 = splay_tree_new_ggc (splay_tree_compare_pointers,
8788 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
8789 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
8791 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
8792 if (n == NULL)
8794 char *new_str;
8796 decl = create_tmp_var_raw (ptr_type_node, NULL);
8798 new_str = ACONCAT ((".gomp_critical_user_",
8799 IDENTIFIER_POINTER (name), NULL));
8800 DECL_NAME (decl) = get_identifier (new_str);
8801 TREE_PUBLIC (decl) = 1;
8802 TREE_STATIC (decl) = 1;
8803 DECL_COMMON (decl) = 1;
8804 DECL_ARTIFICIAL (decl) = 1;
8805 DECL_IGNORED_P (decl) = 1;
8806 varpool_finalize_decl (decl);
8808 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
8809 (splay_tree_value) decl);
8811 else
8812 decl = (tree) n->value;
8814 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
8815 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
8817 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
8818 unlock = build_call_expr_loc (loc, unlock, 1,
8819 build_fold_addr_expr_loc (loc, decl));
8821 else
8823 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
8824 lock = build_call_expr_loc (loc, lock, 0);
8826 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
8827 unlock = build_call_expr_loc (loc, unlock, 0);
8830 push_gimplify_context ();
8832 block = make_node (BLOCK);
8833 bind = gimple_build_bind (NULL, NULL, block);
8834 gsi_replace (gsi_p, bind, true);
8835 gimple_bind_add_stmt (bind, stmt);
8837 tbody = gimple_bind_body (bind);
8838 gimplify_and_add (lock, &tbody);
8839 gimple_bind_set_body (bind, tbody);
8841 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8842 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8843 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8844 gimple_omp_set_body (stmt, NULL);
8846 tbody = gimple_bind_body (bind);
8847 gimplify_and_add (unlock, &tbody);
8848 gimple_bind_set_body (bind, tbody);
8850 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8852 pop_gimplify_context (bind);
8853 gimple_bind_append_vars (bind, ctx->block_vars);
8854 BLOCK_VARS (block) = gimple_bind_vars (bind);
8858 /* A subroutine of lower_omp_for. Generate code to emit the predicate
8859 for a lastprivate clause. Given a loop control predicate of (V
8860 cond N2), we gate the clause on (!(V cond N2)). The lowered form
8861 is appended to *DLIST, iterator initialization is appended to
8862 *BODY_P. */
8864 static void
8865 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
8866 gimple_seq *dlist, struct omp_context *ctx)
8868 tree clauses, cond, vinit;
8869 enum tree_code cond_code;
8870 gimple_seq stmts;
8872 cond_code = fd->loop.cond_code;
8873 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
8875 /* When possible, use a strict equality expression. This can let VRP
8876 type optimizations deduce the value and remove a copy. */
8877 if (tree_fits_shwi_p (fd->loop.step))
8879 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
8880 if (step == 1 || step == -1)
8881 cond_code = EQ_EXPR;
8884 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
8886 clauses = gimple_omp_for_clauses (fd->for_stmt);
8887 stmts = NULL;
8888 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
8889 if (!gimple_seq_empty_p (stmts))
8891 gimple_seq_add_seq (&stmts, *dlist);
8892 *dlist = stmts;
8894 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
8895 vinit = fd->loop.n1;
8896 if (cond_code == EQ_EXPR
8897 && tree_fits_shwi_p (fd->loop.n2)
8898 && ! integer_zerop (fd->loop.n2))
8899 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
8900 else
8901 vinit = unshare_expr (vinit);
8903 /* Initialize the iterator variable, so that threads that don't execute
8904 any iterations don't execute the lastprivate clauses by accident. */
8905 gimplify_assign (fd->loop.v, vinit, body_p);
8910 /* Lower code for an OpenMP loop directive. */
8912 static void
8913 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8915 tree *rhs_p, block;
8916 struct omp_for_data fd, *fdp = NULL;
8917 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
8918 gimple_seq omp_for_body, body, dlist;
8919 size_t i;
8921 push_gimplify_context ();
8923 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
8925 block = make_node (BLOCK);
8926 new_stmt = gimple_build_bind (NULL, NULL, block);
8927 /* Replace at gsi right away, so that 'stmt' is no member
8928 of a sequence anymore as we're going to add to to a different
8929 one below. */
8930 gsi_replace (gsi_p, new_stmt, true);
8932 /* Move declaration of temporaries in the loop body before we make
8933 it go away. */
8934 omp_for_body = gimple_omp_body (stmt);
8935 if (!gimple_seq_empty_p (omp_for_body)
8936 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
8938 tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body));
8939 gimple_bind_append_vars (new_stmt, vars);
8942 if (gimple_omp_for_combined_into_p (stmt))
8944 extract_omp_for_data (stmt, &fd, NULL);
8945 fdp = &fd;
8947 /* We need two temporaries with fd.loop.v type (istart/iend)
8948 and then (fd.collapse - 1) temporaries with the same
8949 type for count2 ... countN-1 vars if not constant. */
8950 size_t count = 2;
8951 tree type = fd.iter_type;
8952 if (fd.collapse > 1
8953 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
8954 count += fd.collapse - 1;
8955 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
8956 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
8957 tree clauses = *pc;
8958 if (parallel_for)
8959 outerc
8960 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
8961 OMP_CLAUSE__LOOPTEMP_);
8962 for (i = 0; i < count; i++)
8964 tree temp;
8965 if (parallel_for)
8967 gcc_assert (outerc);
8968 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
8969 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
8970 OMP_CLAUSE__LOOPTEMP_);
8972 else
8973 temp = create_tmp_var (type, NULL);
8974 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
8975 OMP_CLAUSE_DECL (*pc) = temp;
8976 pc = &OMP_CLAUSE_CHAIN (*pc);
8978 *pc = clauses;
8981 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
8982 dlist = NULL;
8983 body = NULL;
8984 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
8985 fdp);
8986 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
8988 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8990 /* Lower the header expressions. At this point, we can assume that
8991 the header is of the form:
8993 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
8995 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
8996 using the .omp_data_s mapping, if needed. */
8997 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
8999 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9000 if (!is_gimple_min_invariant (*rhs_p))
9001 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9003 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9004 if (!is_gimple_min_invariant (*rhs_p))
9005 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9007 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9008 if (!is_gimple_min_invariant (*rhs_p))
9009 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9012 /* Once lowered, extract the bounds and clauses. */
9013 extract_omp_for_data (stmt, &fd, NULL);
9015 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9017 gimple_seq_add_stmt (&body, stmt);
9018 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9020 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9021 fd.loop.v));
9023 /* After the loop, add exit clauses. */
9024 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9026 if (ctx->cancellable)
9027 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9029 gimple_seq_add_seq (&body, dlist);
9031 body = maybe_catch_exception (body);
9033 /* Region exit marker goes at the end of the loop body. */
9034 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9035 maybe_add_implicit_barrier_cancel (ctx, &body);
9036 pop_gimplify_context (new_stmt);
9038 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9039 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9040 if (BLOCK_VARS (block))
9041 TREE_USED (block) = 1;
9043 gimple_bind_set_body (new_stmt, body);
9044 gimple_omp_set_body (stmt, NULL);
9045 gimple_omp_for_set_pre_body (stmt, NULL);
9048 /* Callback for walk_stmts. Check if the current statement only contains
9049 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
9051 static tree
9052 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9053 bool *handled_ops_p,
9054 struct walk_stmt_info *wi)
9056 int *info = (int *) wi->info;
9057 gimple stmt = gsi_stmt (*gsi_p);
9059 *handled_ops_p = true;
9060 switch (gimple_code (stmt))
9062 WALK_SUBSTMTS;
9064 case GIMPLE_OMP_FOR:
9065 case GIMPLE_OMP_SECTIONS:
9066 *info = *info == 0 ? 1 : -1;
9067 break;
9068 default:
9069 *info = -1;
9070 break;
9072 return NULL;
9075 struct omp_taskcopy_context
9077 /* This field must be at the beginning, as we do "inheritance": Some
9078 callback functions for tree-inline.c (e.g., omp_copy_decl)
9079 receive a copy_body_data pointer that is up-casted to an
9080 omp_context pointer. */
9081 copy_body_data cb;
9082 omp_context *ctx;
9085 static tree
9086 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9088 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9090 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9091 return create_tmp_var (TREE_TYPE (var), NULL);
9093 return var;
9096 static tree
9097 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9099 tree name, new_fields = NULL, type, f;
9101 type = lang_hooks.types.make_type (RECORD_TYPE);
9102 name = DECL_NAME (TYPE_NAME (orig_type));
9103 name = build_decl (gimple_location (tcctx->ctx->stmt),
9104 TYPE_DECL, name, type);
9105 TYPE_NAME (type) = name;
9107 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9109 tree new_f = copy_node (f);
9110 DECL_CONTEXT (new_f) = type;
9111 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9112 TREE_CHAIN (new_f) = new_fields;
9113 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9114 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9115 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9116 &tcctx->cb, NULL);
9117 new_fields = new_f;
9118 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
9120 TYPE_FIELDS (type) = nreverse (new_fields);
9121 layout_type (type);
9122 return type;
9125 /* Create task copyfn. */
9127 static void
9128 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9130 struct function *child_cfun;
9131 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9132 tree record_type, srecord_type, bind, list;
9133 bool record_needs_remap = false, srecord_needs_remap = false;
9134 splay_tree_node n;
9135 struct omp_taskcopy_context tcctx;
9136 location_t loc = gimple_location (task_stmt);
9138 child_fn = gimple_omp_task_copy_fn (task_stmt);
9139 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9140 gcc_assert (child_cfun->cfg == NULL);
9141 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9143 /* Reset DECL_CONTEXT on function arguments. */
9144 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9145 DECL_CONTEXT (t) = child_fn;
9147 /* Populate the function. */
9148 push_gimplify_context ();
9149 push_cfun (child_cfun);
9151 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9152 TREE_SIDE_EFFECTS (bind) = 1;
9153 list = NULL;
9154 DECL_SAVED_TREE (child_fn) = bind;
9155 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9157 /* Remap src and dst argument types if needed. */
9158 record_type = ctx->record_type;
9159 srecord_type = ctx->srecord_type;
9160 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9161 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9163 record_needs_remap = true;
9164 break;
9166 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9167 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9169 srecord_needs_remap = true;
9170 break;
9173 if (record_needs_remap || srecord_needs_remap)
9175 memset (&tcctx, '\0', sizeof (tcctx));
9176 tcctx.cb.src_fn = ctx->cb.src_fn;
9177 tcctx.cb.dst_fn = child_fn;
9178 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
9179 gcc_checking_assert (tcctx.cb.src_node);
9180 tcctx.cb.dst_node = tcctx.cb.src_node;
9181 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9182 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9183 tcctx.cb.eh_lp_nr = 0;
9184 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9185 tcctx.cb.decl_map = pointer_map_create ();
9186 tcctx.ctx = ctx;
9188 if (record_needs_remap)
9189 record_type = task_copyfn_remap_type (&tcctx, record_type);
9190 if (srecord_needs_remap)
9191 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9193 else
9194 tcctx.cb.decl_map = NULL;
9196 arg = DECL_ARGUMENTS (child_fn);
9197 TREE_TYPE (arg) = build_pointer_type (record_type);
9198 sarg = DECL_CHAIN (arg);
9199 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9201 /* First pass: initialize temporaries used in record_type and srecord_type
9202 sizes and field offsets. */
9203 if (tcctx.cb.decl_map)
9204 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9205 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9207 tree *p;
9209 decl = OMP_CLAUSE_DECL (c);
9210 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
9211 if (p == NULL)
9212 continue;
9213 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9214 sf = (tree) n->value;
9215 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9216 src = build_simple_mem_ref_loc (loc, sarg);
9217 src = omp_build_component_ref (src, sf);
9218 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9219 append_to_statement_list (t, &list);
9222 /* Second pass: copy shared var pointers and copy construct non-VLA
9223 firstprivate vars. */
9224 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9225 switch (OMP_CLAUSE_CODE (c))
9227 case OMP_CLAUSE_SHARED:
9228 decl = OMP_CLAUSE_DECL (c);
9229 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9230 if (n == NULL)
9231 break;
9232 f = (tree) n->value;
9233 if (tcctx.cb.decl_map)
9234 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9235 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9236 sf = (tree) n->value;
9237 if (tcctx.cb.decl_map)
9238 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9239 src = build_simple_mem_ref_loc (loc, sarg);
9240 src = omp_build_component_ref (src, sf);
9241 dst = build_simple_mem_ref_loc (loc, arg);
9242 dst = omp_build_component_ref (dst, f);
9243 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9244 append_to_statement_list (t, &list);
9245 break;
9246 case OMP_CLAUSE_FIRSTPRIVATE:
9247 decl = OMP_CLAUSE_DECL (c);
9248 if (is_variable_sized (decl))
9249 break;
9250 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9251 if (n == NULL)
9252 break;
9253 f = (tree) n->value;
9254 if (tcctx.cb.decl_map)
9255 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9256 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9257 if (n != NULL)
9259 sf = (tree) n->value;
9260 if (tcctx.cb.decl_map)
9261 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9262 src = build_simple_mem_ref_loc (loc, sarg);
9263 src = omp_build_component_ref (src, sf);
9264 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9265 src = build_simple_mem_ref_loc (loc, src);
9267 else
9268 src = decl;
9269 dst = build_simple_mem_ref_loc (loc, arg);
9270 dst = omp_build_component_ref (dst, f);
9271 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9272 append_to_statement_list (t, &list);
9273 break;
9274 case OMP_CLAUSE_PRIVATE:
9275 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9276 break;
9277 decl = OMP_CLAUSE_DECL (c);
9278 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9279 f = (tree) n->value;
9280 if (tcctx.cb.decl_map)
9281 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9282 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9283 if (n != NULL)
9285 sf = (tree) n->value;
9286 if (tcctx.cb.decl_map)
9287 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9288 src = build_simple_mem_ref_loc (loc, sarg);
9289 src = omp_build_component_ref (src, sf);
9290 if (use_pointer_for_field (decl, NULL))
9291 src = build_simple_mem_ref_loc (loc, src);
9293 else
9294 src = decl;
9295 dst = build_simple_mem_ref_loc (loc, arg);
9296 dst = omp_build_component_ref (dst, f);
9297 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9298 append_to_statement_list (t, &list);
9299 break;
9300 default:
9301 break;
9304 /* Last pass: handle VLA firstprivates. */
9305 if (tcctx.cb.decl_map)
9306 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9307 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9309 tree ind, ptr, df;
9311 decl = OMP_CLAUSE_DECL (c);
9312 if (!is_variable_sized (decl))
9313 continue;
9314 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9315 if (n == NULL)
9316 continue;
9317 f = (tree) n->value;
9318 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9319 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9320 ind = DECL_VALUE_EXPR (decl);
9321 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9322 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9323 n = splay_tree_lookup (ctx->sfield_map,
9324 (splay_tree_key) TREE_OPERAND (ind, 0));
9325 sf = (tree) n->value;
9326 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9327 src = build_simple_mem_ref_loc (loc, sarg);
9328 src = omp_build_component_ref (src, sf);
9329 src = build_simple_mem_ref_loc (loc, src);
9330 dst = build_simple_mem_ref_loc (loc, arg);
9331 dst = omp_build_component_ref (dst, f);
9332 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9333 append_to_statement_list (t, &list);
9334 n = splay_tree_lookup (ctx->field_map,
9335 (splay_tree_key) TREE_OPERAND (ind, 0));
9336 df = (tree) n->value;
9337 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
9338 ptr = build_simple_mem_ref_loc (loc, arg);
9339 ptr = omp_build_component_ref (ptr, df);
9340 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9341 build_fold_addr_expr_loc (loc, dst));
9342 append_to_statement_list (t, &list);
9345 t = build1 (RETURN_EXPR, void_type_node, NULL);
9346 append_to_statement_list (t, &list);
9348 if (tcctx.cb.decl_map)
9349 pointer_map_destroy (tcctx.cb.decl_map);
9350 pop_gimplify_context (NULL);
9351 BIND_EXPR_BODY (bind) = list;
9352 pop_cfun ();
9355 static void
9356 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9358 tree c, clauses;
9359 gimple g;
9360 size_t n_in = 0, n_out = 0, idx = 2, i;
9362 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9363 OMP_CLAUSE_DEPEND);
9364 gcc_assert (clauses);
9365 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9366 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9367 switch (OMP_CLAUSE_DEPEND_KIND (c))
9369 case OMP_CLAUSE_DEPEND_IN:
9370 n_in++;
9371 break;
9372 case OMP_CLAUSE_DEPEND_OUT:
9373 case OMP_CLAUSE_DEPEND_INOUT:
9374 n_out++;
9375 break;
9376 default:
9377 gcc_unreachable ();
9379 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9380 tree array = create_tmp_var (type, NULL);
9381 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9382 NULL_TREE);
9383 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9384 gimple_seq_add_stmt (iseq, g);
9385 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9386 NULL_TREE);
9387 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9388 gimple_seq_add_stmt (iseq, g);
9389 for (i = 0; i < 2; i++)
9391 if ((i ? n_in : n_out) == 0)
9392 continue;
9393 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9394 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9395 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9397 tree t = OMP_CLAUSE_DECL (c);
9398 t = fold_convert (ptr_type_node, t);
9399 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9400 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9401 NULL_TREE, NULL_TREE);
9402 g = gimple_build_assign (r, t);
9403 gimple_seq_add_stmt (iseq, g);
9406 tree *p = gimple_omp_task_clauses_ptr (stmt);
9407 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9408 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9409 OMP_CLAUSE_CHAIN (c) = *p;
9410 *p = c;
9411 tree clobber = build_constructor (type, NULL);
9412 TREE_THIS_VOLATILE (clobber) = 1;
9413 g = gimple_build_assign (array, clobber);
9414 gimple_seq_add_stmt (oseq, g);
9417 /* Lower the OpenMP parallel or task directive in the current statement
9418 in GSI_P. CTX holds context information for the directive. */
9420 static void
9421 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9423 tree clauses;
9424 tree child_fn, t;
9425 gimple stmt = gsi_stmt (*gsi_p);
9426 gimple par_bind, bind, dep_bind = NULL;
9427 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9428 location_t loc = gimple_location (stmt);
9430 clauses = gimple_omp_taskreg_clauses (stmt);
9431 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9432 par_body = gimple_bind_body (par_bind);
9433 child_fn = ctx->cb.dst_fn;
9434 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9435 && !gimple_omp_parallel_combined_p (stmt))
9437 struct walk_stmt_info wi;
9438 int ws_num = 0;
9440 memset (&wi, 0, sizeof (wi));
9441 wi.info = &ws_num;
9442 wi.val_only = true;
9443 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9444 if (ws_num == 1)
9445 gimple_omp_parallel_set_combined_p (stmt, true);
9447 gimple_seq dep_ilist = NULL;
9448 gimple_seq dep_olist = NULL;
9449 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9450 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9452 push_gimplify_context ();
9453 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9454 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9457 if (ctx->srecord_type)
9458 create_task_copyfn (stmt, ctx);
9460 push_gimplify_context ();
9462 par_olist = NULL;
9463 par_ilist = NULL;
9464 par_rlist = NULL;
9465 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9466 lower_omp (&par_body, ctx);
9467 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9468 lower_reduction_clauses (clauses, &par_rlist, ctx);
9470 /* Declare all the variables created by mapping and the variables
9471 declared in the scope of the parallel body. */
9472 record_vars_into (ctx->block_vars, child_fn);
9473 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9475 if (ctx->record_type)
9477 ctx->sender_decl
9478 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9479 : ctx->record_type, ".omp_data_o");
9480 DECL_NAMELESS (ctx->sender_decl) = 1;
9481 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9482 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9485 olist = NULL;
9486 ilist = NULL;
9487 lower_send_clauses (clauses, &ilist, &olist, ctx);
9488 lower_send_shared_vars (&ilist, &olist, ctx);
9490 if (ctx->record_type)
9492 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9493 TREE_THIS_VOLATILE (clobber) = 1;
9494 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9495 clobber));
9498 /* Once all the expansions are done, sequence all the different
9499 fragments inside gimple_omp_body. */
9501 new_body = NULL;
9503 if (ctx->record_type)
9505 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9506 /* fixup_child_record_type might have changed receiver_decl's type. */
9507 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9508 gimple_seq_add_stmt (&new_body,
9509 gimple_build_assign (ctx->receiver_decl, t));
9512 gimple_seq_add_seq (&new_body, par_ilist);
9513 gimple_seq_add_seq (&new_body, par_body);
9514 gimple_seq_add_seq (&new_body, par_rlist);
9515 if (ctx->cancellable)
9516 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9517 gimple_seq_add_seq (&new_body, par_olist);
9518 new_body = maybe_catch_exception (new_body);
9519 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9520 gimple_omp_set_body (stmt, new_body);
9522 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9523 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
9524 gimple_bind_add_seq (bind, ilist);
9525 gimple_bind_add_stmt (bind, stmt);
9526 gimple_bind_add_seq (bind, olist);
9528 pop_gimplify_context (NULL);
9530 if (dep_bind)
9532 gimple_bind_add_seq (dep_bind, dep_ilist);
9533 gimple_bind_add_stmt (dep_bind, bind);
9534 gimple_bind_add_seq (dep_bind, dep_olist);
9535 pop_gimplify_context (dep_bind);
9539 /* Lower the OpenMP target directive in the current statement
9540 in GSI_P. CTX holds context information for the directive. */
9542 static void
9543 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9545 tree clauses;
9546 tree child_fn, t, c;
9547 gimple stmt = gsi_stmt (*gsi_p);
9548 gimple tgt_bind = NULL, bind;
9549 gimple_seq tgt_body = NULL, olist, ilist, new_body;
9550 location_t loc = gimple_location (stmt);
9551 int kind = gimple_omp_target_kind (stmt);
9552 unsigned int map_cnt = 0;
9554 clauses = gimple_omp_target_clauses (stmt);
9555 if (kind == GF_OMP_TARGET_KIND_REGION)
9557 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9558 tgt_body = gimple_bind_body (tgt_bind);
9560 else if (kind == GF_OMP_TARGET_KIND_DATA)
9561 tgt_body = gimple_omp_body (stmt);
9562 child_fn = ctx->cb.dst_fn;
9564 push_gimplify_context ();
9566 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9567 switch (OMP_CLAUSE_CODE (c))
9569 tree var, x;
9571 default:
9572 break;
9573 case OMP_CLAUSE_MAP:
9574 case OMP_CLAUSE_TO:
9575 case OMP_CLAUSE_FROM:
9576 var = OMP_CLAUSE_DECL (c);
9577 if (!DECL_P (var))
9579 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
9580 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9581 map_cnt++;
9582 continue;
9585 if (DECL_SIZE (var)
9586 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
9588 tree var2 = DECL_VALUE_EXPR (var);
9589 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
9590 var2 = TREE_OPERAND (var2, 0);
9591 gcc_assert (DECL_P (var2));
9592 var = var2;
9595 if (!maybe_lookup_field (var, ctx))
9596 continue;
9598 if (kind == GF_OMP_TARGET_KIND_REGION)
9600 x = build_receiver_ref (var, true, ctx);
9601 tree new_var = lookup_decl (var, ctx);
9602 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9603 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9604 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9605 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
9606 x = build_simple_mem_ref (x);
9607 SET_DECL_VALUE_EXPR (new_var, x);
9608 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
9610 map_cnt++;
9613 if (kind == GF_OMP_TARGET_KIND_REGION)
9615 target_nesting_level++;
9616 lower_omp (&tgt_body, ctx);
9617 target_nesting_level--;
9619 else if (kind == GF_OMP_TARGET_KIND_DATA)
9620 lower_omp (&tgt_body, ctx);
9622 if (kind == GF_OMP_TARGET_KIND_REGION)
9624 /* Declare all the variables created by mapping and the variables
9625 declared in the scope of the target body. */
9626 record_vars_into (ctx->block_vars, child_fn);
9627 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
9630 olist = NULL;
9631 ilist = NULL;
9632 if (ctx->record_type)
9634 ctx->sender_decl
9635 = create_tmp_var (ctx->record_type, ".omp_data_arr");
9636 DECL_NAMELESS (ctx->sender_decl) = 1;
9637 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9638 t = make_tree_vec (3);
9639 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
9640 TREE_VEC_ELT (t, 1)
9641 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
9642 ".omp_data_sizes");
9643 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
9644 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
9645 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
9646 TREE_VEC_ELT (t, 2)
9647 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
9648 map_cnt),
9649 ".omp_data_kinds");
9650 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
9651 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
9652 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
9653 gimple_omp_target_set_data_arg (stmt, t);
9655 vec<constructor_elt, va_gc> *vsize;
9656 vec<constructor_elt, va_gc> *vkind;
9657 vec_alloc (vsize, map_cnt);
9658 vec_alloc (vkind, map_cnt);
9659 unsigned int map_idx = 0;
9661 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9662 switch (OMP_CLAUSE_CODE (c))
9664 tree ovar, nc;
9666 default:
9667 break;
9668 case OMP_CLAUSE_MAP:
9669 case OMP_CLAUSE_TO:
9670 case OMP_CLAUSE_FROM:
9671 nc = c;
9672 ovar = OMP_CLAUSE_DECL (c);
9673 if (!DECL_P (ovar))
9675 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9676 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9678 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
9679 == get_base_address (ovar));
9680 nc = OMP_CLAUSE_CHAIN (c);
9681 ovar = OMP_CLAUSE_DECL (nc);
9683 else
9685 tree x = build_sender_ref (ovar, ctx);
9686 tree v
9687 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
9688 gimplify_assign (x, v, &ilist);
9689 nc = NULL_TREE;
9692 else
9694 if (DECL_SIZE (ovar)
9695 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
9697 tree ovar2 = DECL_VALUE_EXPR (ovar);
9698 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
9699 ovar2 = TREE_OPERAND (ovar2, 0);
9700 gcc_assert (DECL_P (ovar2));
9701 ovar = ovar2;
9703 if (!maybe_lookup_field (ovar, ctx))
9704 continue;
9707 if (nc)
9709 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
9710 tree x = build_sender_ref (ovar, ctx);
9711 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9712 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9713 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9714 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
9716 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9717 tree avar
9718 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
9719 mark_addressable (avar);
9720 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
9721 avar = build_fold_addr_expr (avar);
9722 gimplify_assign (x, avar, &ilist);
9724 else if (is_gimple_reg (var))
9726 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9727 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
9728 mark_addressable (avar);
9729 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
9730 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
9731 gimplify_assign (avar, var, &ilist);
9732 avar = build_fold_addr_expr (avar);
9733 gimplify_assign (x, avar, &ilist);
9734 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
9735 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
9736 && !TYPE_READONLY (TREE_TYPE (var)))
9738 x = build_sender_ref (ovar, ctx);
9739 x = build_simple_mem_ref (x);
9740 gimplify_assign (var, x, &olist);
9743 else
9745 var = build_fold_addr_expr (var);
9746 gimplify_assign (x, var, &ilist);
9749 tree s = OMP_CLAUSE_SIZE (c);
9750 if (s == NULL_TREE)
9751 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
9752 s = fold_convert (size_type_node, s);
9753 tree purpose = size_int (map_idx++);
9754 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
9755 if (TREE_CODE (s) != INTEGER_CST)
9756 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
9758 unsigned char tkind = 0;
9759 switch (OMP_CLAUSE_CODE (c))
9761 case OMP_CLAUSE_MAP:
9762 tkind = OMP_CLAUSE_MAP_KIND (c);
9763 break;
9764 case OMP_CLAUSE_TO:
9765 tkind = OMP_CLAUSE_MAP_TO;
9766 break;
9767 case OMP_CLAUSE_FROM:
9768 tkind = OMP_CLAUSE_MAP_FROM;
9769 break;
9770 default:
9771 gcc_unreachable ();
9773 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
9774 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
9775 talign = DECL_ALIGN_UNIT (ovar);
9776 talign = ceil_log2 (talign);
9777 tkind |= talign << 3;
9778 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
9779 build_int_cst (unsigned_char_type_node,
9780 tkind));
9781 if (nc && nc != c)
9782 c = nc;
9785 gcc_assert (map_idx == map_cnt);
9787 DECL_INITIAL (TREE_VEC_ELT (t, 1))
9788 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
9789 DECL_INITIAL (TREE_VEC_ELT (t, 2))
9790 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
9791 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
9793 gimple_seq initlist = NULL;
9794 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
9795 TREE_VEC_ELT (t, 1)),
9796 &initlist, true, NULL_TREE);
9797 gimple_seq_add_seq (&ilist, initlist);
9800 tree clobber = build_constructor (ctx->record_type, NULL);
9801 TREE_THIS_VOLATILE (clobber) = 1;
9802 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9803 clobber));
9806 /* Once all the expansions are done, sequence all the different
9807 fragments inside gimple_omp_body. */
9809 new_body = NULL;
9811 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
9813 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9814 /* fixup_child_record_type might have changed receiver_decl's type. */
9815 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9816 gimple_seq_add_stmt (&new_body,
9817 gimple_build_assign (ctx->receiver_decl, t));
9820 if (kind == GF_OMP_TARGET_KIND_REGION)
9822 gimple_seq_add_seq (&new_body, tgt_body);
9823 new_body = maybe_catch_exception (new_body);
9825 else if (kind == GF_OMP_TARGET_KIND_DATA)
9826 new_body = tgt_body;
9827 if (kind != GF_OMP_TARGET_KIND_UPDATE)
9829 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9830 gimple_omp_set_body (stmt, new_body);
9833 bind = gimple_build_bind (NULL, NULL,
9834 tgt_bind ? gimple_bind_block (tgt_bind)
9835 : NULL_TREE);
9836 gsi_replace (gsi_p, bind, true);
9837 gimple_bind_add_seq (bind, ilist);
9838 gimple_bind_add_stmt (bind, stmt);
9839 gimple_bind_add_seq (bind, olist);
9841 pop_gimplify_context (NULL);
9844 /* Expand code for an OpenMP teams directive. */
9846 static void
9847 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9849 gimple teams_stmt = gsi_stmt (*gsi_p);
9850 push_gimplify_context ();
9852 tree block = make_node (BLOCK);
9853 gimple bind = gimple_build_bind (NULL, NULL, block);
9854 gsi_replace (gsi_p, bind, true);
9855 gimple_seq bind_body = NULL;
9856 gimple_seq dlist = NULL;
9857 gimple_seq olist = NULL;
9859 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9860 OMP_CLAUSE_NUM_TEAMS);
9861 if (num_teams == NULL_TREE)
9862 num_teams = build_int_cst (unsigned_type_node, 0);
9863 else
9865 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
9866 num_teams = fold_convert (unsigned_type_node, num_teams);
9867 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
9869 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9870 OMP_CLAUSE_THREAD_LIMIT);
9871 if (thread_limit == NULL_TREE)
9872 thread_limit = build_int_cst (unsigned_type_node, 0);
9873 else
9875 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
9876 thread_limit = fold_convert (unsigned_type_node, thread_limit);
9877 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
9878 fb_rvalue);
9881 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
9882 &bind_body, &dlist, ctx, NULL);
9883 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
9884 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
9885 gimple_seq_add_stmt (&bind_body, teams_stmt);
9887 location_t loc = gimple_location (teams_stmt);
9888 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
9889 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
9890 gimple_set_location (call, loc);
9891 gimple_seq_add_stmt (&bind_body, call);
9893 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
9894 gimple_omp_set_body (teams_stmt, NULL);
9895 gimple_seq_add_seq (&bind_body, olist);
9896 gimple_seq_add_seq (&bind_body, dlist);
9897 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
9898 gimple_bind_set_body (bind, bind_body);
9900 pop_gimplify_context (bind);
9902 gimple_bind_append_vars (bind, ctx->block_vars);
9903 BLOCK_VARS (block) = ctx->block_vars;
9904 if (BLOCK_VARS (block))
9905 TREE_USED (block) = 1;
9909 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
9910 regimplified. If DATA is non-NULL, lower_omp_1 is outside
9911 of OpenMP context, but with task_shared_vars set. */
9913 static tree
9914 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
9915 void *data)
9917 tree t = *tp;
9919 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
9920 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9921 return t;
9923 if (task_shared_vars
9924 && DECL_P (t)
9925 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
9926 return t;
9928 /* If a global variable has been privatized, TREE_CONSTANT on
9929 ADDR_EXPR might be wrong. */
9930 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
9931 recompute_tree_invariant_for_addr_expr (t);
9933 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
9934 return NULL_TREE;
9937 static void
9938 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9940 gimple stmt = gsi_stmt (*gsi_p);
9941 struct walk_stmt_info wi;
9943 if (gimple_has_location (stmt))
9944 input_location = gimple_location (stmt);
9946 if (task_shared_vars)
9947 memset (&wi, '\0', sizeof (wi));
9949 /* If we have issued syntax errors, avoid doing any heavy lifting.
9950 Just replace the OpenMP directives with a NOP to avoid
9951 confusing RTL expansion. */
9952 if (seen_error () && is_gimple_omp (stmt))
9954 gsi_replace (gsi_p, gimple_build_nop (), true);
9955 return;
9958 switch (gimple_code (stmt))
9960 case GIMPLE_COND:
9961 if ((ctx || task_shared_vars)
9962 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
9963 ctx ? NULL : &wi, NULL)
9964 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
9965 ctx ? NULL : &wi, NULL)))
9966 gimple_regimplify_operands (stmt, gsi_p);
9967 break;
9968 case GIMPLE_CATCH:
9969 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
9970 break;
9971 case GIMPLE_EH_FILTER:
9972 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
9973 break;
9974 case GIMPLE_TRY:
9975 lower_omp (gimple_try_eval_ptr (stmt), ctx);
9976 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
9977 break;
9978 case GIMPLE_TRANSACTION:
9979 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
9980 break;
9981 case GIMPLE_BIND:
9982 lower_omp (gimple_bind_body_ptr (stmt), ctx);
9983 break;
9984 case GIMPLE_OMP_PARALLEL:
9985 case GIMPLE_OMP_TASK:
9986 ctx = maybe_lookup_ctx (stmt);
9987 gcc_assert (ctx);
9988 if (ctx->cancellable)
9989 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9990 lower_omp_taskreg (gsi_p, ctx);
9991 break;
9992 case GIMPLE_OMP_FOR:
9993 ctx = maybe_lookup_ctx (stmt);
9994 gcc_assert (ctx);
9995 if (ctx->cancellable)
9996 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9997 lower_omp_for (gsi_p, ctx);
9998 break;
9999 case GIMPLE_OMP_SECTIONS:
10000 ctx = maybe_lookup_ctx (stmt);
10001 gcc_assert (ctx);
10002 if (ctx->cancellable)
10003 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10004 lower_omp_sections (gsi_p, ctx);
10005 break;
10006 case GIMPLE_OMP_SINGLE:
10007 ctx = maybe_lookup_ctx (stmt);
10008 gcc_assert (ctx);
10009 lower_omp_single (gsi_p, ctx);
10010 break;
10011 case GIMPLE_OMP_MASTER:
10012 ctx = maybe_lookup_ctx (stmt);
10013 gcc_assert (ctx);
10014 lower_omp_master (gsi_p, ctx);
10015 break;
10016 case GIMPLE_OMP_TASKGROUP:
10017 ctx = maybe_lookup_ctx (stmt);
10018 gcc_assert (ctx);
10019 lower_omp_taskgroup (gsi_p, ctx);
10020 break;
10021 case GIMPLE_OMP_ORDERED:
10022 ctx = maybe_lookup_ctx (stmt);
10023 gcc_assert (ctx);
10024 lower_omp_ordered (gsi_p, ctx);
10025 break;
10026 case GIMPLE_OMP_CRITICAL:
10027 ctx = maybe_lookup_ctx (stmt);
10028 gcc_assert (ctx);
10029 lower_omp_critical (gsi_p, ctx);
10030 break;
10031 case GIMPLE_OMP_ATOMIC_LOAD:
10032 if ((ctx || task_shared_vars)
10033 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
10034 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10035 gimple_regimplify_operands (stmt, gsi_p);
10036 break;
10037 case GIMPLE_OMP_TARGET:
10038 ctx = maybe_lookup_ctx (stmt);
10039 gcc_assert (ctx);
10040 lower_omp_target (gsi_p, ctx);
10041 break;
10042 case GIMPLE_OMP_TEAMS:
10043 ctx = maybe_lookup_ctx (stmt);
10044 gcc_assert (ctx);
10045 lower_omp_teams (gsi_p, ctx);
10046 break;
10047 case GIMPLE_CALL:
10048 tree fndecl;
10049 fndecl = gimple_call_fndecl (stmt);
10050 if (fndecl
10051 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10052 switch (DECL_FUNCTION_CODE (fndecl))
10054 case BUILT_IN_GOMP_BARRIER:
10055 if (ctx == NULL)
10056 break;
10057 /* FALLTHRU */
10058 case BUILT_IN_GOMP_CANCEL:
10059 case BUILT_IN_GOMP_CANCELLATION_POINT:
10060 omp_context *cctx;
10061 cctx = ctx;
10062 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10063 cctx = cctx->outer;
10064 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10065 if (!cctx->cancellable)
10067 if (DECL_FUNCTION_CODE (fndecl)
10068 == BUILT_IN_GOMP_CANCELLATION_POINT)
10070 stmt = gimple_build_nop ();
10071 gsi_replace (gsi_p, stmt, false);
10073 break;
10075 tree lhs;
10076 lhs = create_tmp_var (boolean_type_node, NULL);
10077 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10079 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10080 gimple_call_set_fndecl (stmt, fndecl);
10081 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10083 gimple_call_set_lhs (stmt, lhs);
10084 tree fallthru_label;
10085 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10086 gimple g;
10087 g = gimple_build_label (fallthru_label);
10088 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10089 g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
10090 cctx->cancel_label, fallthru_label);
10091 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10092 break;
10093 default:
10094 break;
10096 /* FALLTHRU */
10097 default:
10098 if ((ctx || task_shared_vars)
10099 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10100 ctx ? NULL : &wi))
10101 gimple_regimplify_operands (stmt, gsi_p);
10102 break;
10106 static void
10107 lower_omp (gimple_seq *body, omp_context *ctx)
10109 location_t saved_location = input_location;
10110 gimple_stmt_iterator gsi;
10111 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10112 lower_omp_1 (&gsi, ctx);
10113 /* Inside target region we haven't called fold_stmt during gimplification,
10114 because it can break code by adding decl references that weren't in the
10115 source. Call fold_stmt now. */
10116 if (target_nesting_level)
10117 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10118 fold_stmt (&gsi);
10119 input_location = saved_location;
10122 /* Main entry point. */
10124 static unsigned int
10125 execute_lower_omp (void)
10127 gimple_seq body;
10129 /* This pass always runs, to provide PROP_gimple_lomp.
10130 But there is nothing to do unless -fopenmp is given. */
10131 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_enable_cilkplus == 0)
10132 return 0;
10134 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10135 delete_omp_context);
10137 body = gimple_body (current_function_decl);
10138 scan_omp (&body, NULL);
10139 gcc_assert (taskreg_nesting_level == 0);
10141 if (all_contexts->root)
10143 if (task_shared_vars)
10144 push_gimplify_context ();
10145 lower_omp (&body, NULL);
10146 if (task_shared_vars)
10147 pop_gimplify_context (NULL);
10150 if (all_contexts)
10152 splay_tree_delete (all_contexts);
10153 all_contexts = NULL;
10155 BITMAP_FREE (task_shared_vars);
10156 return 0;
10159 namespace {
10161 const pass_data pass_data_lower_omp =
10163 GIMPLE_PASS, /* type */
10164 "omplower", /* name */
10165 OPTGROUP_NONE, /* optinfo_flags */
10166 false, /* has_gate */
10167 true, /* has_execute */
10168 TV_NONE, /* tv_id */
10169 PROP_gimple_any, /* properties_required */
10170 PROP_gimple_lomp, /* properties_provided */
10171 0, /* properties_destroyed */
10172 0, /* todo_flags_start */
10173 0, /* todo_flags_finish */
10176 class pass_lower_omp : public gimple_opt_pass
10178 public:
10179 pass_lower_omp (gcc::context *ctxt)
10180 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10183 /* opt_pass methods: */
10184 unsigned int execute () { return execute_lower_omp (); }
10186 }; // class pass_lower_omp
10188 } // anon namespace
10190 gimple_opt_pass *
10191 make_pass_lower_omp (gcc::context *ctxt)
10193 return new pass_lower_omp (ctxt);
10196 /* The following is a utility to diagnose OpenMP structured block violations.
10197 It is not part of the "omplower" pass, as that's invoked too late. It
10198 should be invoked by the respective front ends after gimplification. */
10200 static splay_tree all_labels;
10202 /* Check for mismatched contexts and generate an error if needed. Return
10203 true if an error is detected. */
10205 static bool
10206 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10207 gimple branch_ctx, gimple label_ctx)
10209 if (label_ctx == branch_ctx)
10210 return false;
10214 Previously we kept track of the label's entire context in diagnose_sb_[12]
10215 so we could traverse it and issue a correct "exit" or "enter" error
10216 message upon a structured block violation.
10218 We built the context by building a list with tree_cons'ing, but there is
10219 no easy counterpart in gimple tuples. It seems like far too much work
10220 for issuing exit/enter error messages. If someone really misses the
10221 distinct error message... patches welcome.
10224 #if 0
10225 /* Try to avoid confusing the user by producing and error message
10226 with correct "exit" or "enter" verbiage. We prefer "exit"
10227 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10228 if (branch_ctx == NULL)
10229 exit_p = false;
10230 else
10232 while (label_ctx)
10234 if (TREE_VALUE (label_ctx) == branch_ctx)
10236 exit_p = false;
10237 break;
10239 label_ctx = TREE_CHAIN (label_ctx);
10243 if (exit_p)
10244 error ("invalid exit from OpenMP structured block");
10245 else
10246 error ("invalid entry to OpenMP structured block");
10247 #endif
10249 bool cilkplus_block = false;
10250 if (flag_enable_cilkplus)
10252 if ((branch_ctx
10253 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10254 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10255 || (gimple_code (label_ctx) == GIMPLE_OMP_FOR
10256 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10257 cilkplus_block = true;
10260 /* If it's obvious we have an invalid entry, be specific about the error. */
10261 if (branch_ctx == NULL)
10263 if (cilkplus_block)
10264 error ("invalid entry to Cilk Plus structured block");
10265 else
10266 error ("invalid entry to OpenMP structured block");
10268 else
10270 /* Otherwise, be vague and lazy, but efficient. */
10271 if (cilkplus_block)
10272 error ("invalid branch to/from a Cilk Plus structured block");
10273 else
10274 error ("invalid branch to/from an OpenMP structured block");
10277 gsi_replace (gsi_p, gimple_build_nop (), false);
10278 return true;
10281 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10282 where each label is found. */
10284 static tree
10285 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10286 struct walk_stmt_info *wi)
10288 gimple context = (gimple) wi->info;
10289 gimple inner_context;
10290 gimple stmt = gsi_stmt (*gsi_p);
10292 *handled_ops_p = true;
10294 switch (gimple_code (stmt))
10296 WALK_SUBSTMTS;
10298 case GIMPLE_OMP_PARALLEL:
10299 case GIMPLE_OMP_TASK:
10300 case GIMPLE_OMP_SECTIONS:
10301 case GIMPLE_OMP_SINGLE:
10302 case GIMPLE_OMP_SECTION:
10303 case GIMPLE_OMP_MASTER:
10304 case GIMPLE_OMP_ORDERED:
10305 case GIMPLE_OMP_CRITICAL:
10306 case GIMPLE_OMP_TARGET:
10307 case GIMPLE_OMP_TEAMS:
10308 case GIMPLE_OMP_TASKGROUP:
10309 /* The minimal context here is just the current OMP construct. */
10310 inner_context = stmt;
10311 wi->info = inner_context;
10312 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10313 wi->info = context;
10314 break;
10316 case GIMPLE_OMP_FOR:
10317 inner_context = stmt;
10318 wi->info = inner_context;
10319 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10320 walk them. */
10321 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10322 diagnose_sb_1, NULL, wi);
10323 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10324 wi->info = context;
10325 break;
10327 case GIMPLE_LABEL:
10328 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10329 (splay_tree_value) context);
10330 break;
10332 default:
10333 break;
10336 return NULL_TREE;
10339 /* Pass 2: Check each branch and see if its context differs from that of
10340 the destination label's context. */
10342 static tree
10343 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10344 struct walk_stmt_info *wi)
10346 gimple context = (gimple) wi->info;
10347 splay_tree_node n;
10348 gimple stmt = gsi_stmt (*gsi_p);
10350 *handled_ops_p = true;
10352 switch (gimple_code (stmt))
10354 WALK_SUBSTMTS;
10356 case GIMPLE_OMP_PARALLEL:
10357 case GIMPLE_OMP_TASK:
10358 case GIMPLE_OMP_SECTIONS:
10359 case GIMPLE_OMP_SINGLE:
10360 case GIMPLE_OMP_SECTION:
10361 case GIMPLE_OMP_MASTER:
10362 case GIMPLE_OMP_ORDERED:
10363 case GIMPLE_OMP_CRITICAL:
10364 case GIMPLE_OMP_TARGET:
10365 case GIMPLE_OMP_TEAMS:
10366 case GIMPLE_OMP_TASKGROUP:
10367 wi->info = stmt;
10368 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10369 wi->info = context;
10370 break;
10372 case GIMPLE_OMP_FOR:
10373 wi->info = stmt;
10374 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10375 walk them. */
10376 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10377 diagnose_sb_2, NULL, wi);
10378 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10379 wi->info = context;
10380 break;
10382 case GIMPLE_COND:
10384 tree lab = gimple_cond_true_label (stmt);
10385 if (lab)
10387 n = splay_tree_lookup (all_labels,
10388 (splay_tree_key) lab);
10389 diagnose_sb_0 (gsi_p, context,
10390 n ? (gimple) n->value : NULL);
10392 lab = gimple_cond_false_label (stmt);
10393 if (lab)
10395 n = splay_tree_lookup (all_labels,
10396 (splay_tree_key) lab);
10397 diagnose_sb_0 (gsi_p, context,
10398 n ? (gimple) n->value : NULL);
10401 break;
10403 case GIMPLE_GOTO:
10405 tree lab = gimple_goto_dest (stmt);
10406 if (TREE_CODE (lab) != LABEL_DECL)
10407 break;
10409 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10410 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10412 break;
10414 case GIMPLE_SWITCH:
10416 unsigned int i;
10417 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10419 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10420 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10421 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10422 break;
10425 break;
10427 case GIMPLE_RETURN:
10428 diagnose_sb_0 (gsi_p, context, NULL);
10429 break;
10431 default:
10432 break;
10435 return NULL_TREE;
10438 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10439 codes. */
10440 bool
10441 make_gimple_omp_edges (basic_block bb, struct omp_region **region)
10443 gimple last = last_stmt (bb);
10444 enum gimple_code code = gimple_code (last);
10445 struct omp_region *cur_region = *region;
10446 bool fallthru = false;
10448 switch (code)
10450 case GIMPLE_OMP_PARALLEL:
10451 case GIMPLE_OMP_TASK:
10452 case GIMPLE_OMP_FOR:
10453 case GIMPLE_OMP_SINGLE:
10454 case GIMPLE_OMP_TEAMS:
10455 case GIMPLE_OMP_MASTER:
10456 case GIMPLE_OMP_TASKGROUP:
10457 case GIMPLE_OMP_ORDERED:
10458 case GIMPLE_OMP_CRITICAL:
10459 case GIMPLE_OMP_SECTION:
10460 cur_region = new_omp_region (bb, code, cur_region);
10461 fallthru = true;
10462 break;
10464 case GIMPLE_OMP_TARGET:
10465 cur_region = new_omp_region (bb, code, cur_region);
10466 fallthru = true;
10467 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10468 cur_region = cur_region->outer;
10469 break;
10471 case GIMPLE_OMP_SECTIONS:
10472 cur_region = new_omp_region (bb, code, cur_region);
10473 fallthru = true;
10474 break;
10476 case GIMPLE_OMP_SECTIONS_SWITCH:
10477 fallthru = false;
10478 break;
10480 case GIMPLE_OMP_ATOMIC_LOAD:
10481 case GIMPLE_OMP_ATOMIC_STORE:
10482 fallthru = true;
10483 break;
10485 case GIMPLE_OMP_RETURN:
10486 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10487 somewhere other than the next block. This will be
10488 created later. */
10489 cur_region->exit = bb;
10490 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
10491 cur_region = cur_region->outer;
10492 break;
10494 case GIMPLE_OMP_CONTINUE:
10495 cur_region->cont = bb;
10496 switch (cur_region->type)
10498 case GIMPLE_OMP_FOR:
10499 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
10500 succs edges as abnormal to prevent splitting
10501 them. */
10502 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
10503 /* Make the loopback edge. */
10504 make_edge (bb, single_succ (cur_region->entry),
10505 EDGE_ABNORMAL);
10507 /* Create an edge from GIMPLE_OMP_FOR to exit, which
10508 corresponds to the case that the body of the loop
10509 is not executed at all. */
10510 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
10511 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
10512 fallthru = false;
10513 break;
10515 case GIMPLE_OMP_SECTIONS:
10516 /* Wire up the edges into and out of the nested sections. */
10518 basic_block switch_bb = single_succ (cur_region->entry);
10520 struct omp_region *i;
10521 for (i = cur_region->inner; i ; i = i->next)
10523 gcc_assert (i->type == GIMPLE_OMP_SECTION);
10524 make_edge (switch_bb, i->entry, 0);
10525 make_edge (i->exit, bb, EDGE_FALLTHRU);
10528 /* Make the loopback edge to the block with
10529 GIMPLE_OMP_SECTIONS_SWITCH. */
10530 make_edge (bb, switch_bb, 0);
10532 /* Make the edge from the switch to exit. */
10533 make_edge (switch_bb, bb->next_bb, 0);
10534 fallthru = false;
10536 break;
10538 default:
10539 gcc_unreachable ();
10541 break;
10543 default:
10544 gcc_unreachable ();
10547 if (*region != cur_region)
10548 *region = cur_region;
10550 return fallthru;
10553 static unsigned int
10554 diagnose_omp_structured_block_errors (void)
10556 struct walk_stmt_info wi;
10557 gimple_seq body = gimple_body (current_function_decl);
10559 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
10561 memset (&wi, 0, sizeof (wi));
10562 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
10564 memset (&wi, 0, sizeof (wi));
10565 wi.want_locations = true;
10566 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
10568 gimple_set_body (current_function_decl, body);
10570 splay_tree_delete (all_labels);
10571 all_labels = NULL;
10573 return 0;
10576 static bool
10577 gate_diagnose_omp_blocks (void)
10579 return flag_openmp || flag_enable_cilkplus;
10582 namespace {
10584 const pass_data pass_data_diagnose_omp_blocks =
10586 GIMPLE_PASS, /* type */
10587 "*diagnose_omp_blocks", /* name */
10588 OPTGROUP_NONE, /* optinfo_flags */
10589 true, /* has_gate */
10590 true, /* has_execute */
10591 TV_NONE, /* tv_id */
10592 PROP_gimple_any, /* properties_required */
10593 0, /* properties_provided */
10594 0, /* properties_destroyed */
10595 0, /* todo_flags_start */
10596 0, /* todo_flags_finish */
10599 class pass_diagnose_omp_blocks : public gimple_opt_pass
10601 public:
10602 pass_diagnose_omp_blocks (gcc::context *ctxt)
10603 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
10606 /* opt_pass methods: */
10607 bool gate () { return gate_diagnose_omp_blocks (); }
10608 unsigned int execute () {
10609 return diagnose_omp_structured_block_errors ();
10612 }; // class pass_diagnose_omp_blocks
10614 } // anon namespace
10616 gimple_opt_pass *
10617 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
10619 return new pass_diagnose_omp_blocks (ctxt);
10622 /* SIMD clone supporting code. */
10624 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
10625 of arguments to reserve space for. */
10627 static struct cgraph_simd_clone *
10628 simd_clone_struct_alloc (int nargs)
10630 struct cgraph_simd_clone *clone_info;
10631 size_t len = (sizeof (struct cgraph_simd_clone)
10632 + nargs * sizeof (struct cgraph_simd_clone_arg));
10633 clone_info = (struct cgraph_simd_clone *)
10634 ggc_internal_cleared_alloc_stat (len PASS_MEM_STAT);
10635 return clone_info;
10638 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
10640 static inline void
10641 simd_clone_struct_copy (struct cgraph_simd_clone *to,
10642 struct cgraph_simd_clone *from)
10644 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
10645 + from->nargs * sizeof (struct cgraph_simd_clone_arg)));
10648 /* Return vector of parameter types of function FNDECL. This uses
10649 TYPE_ARG_TYPES if available, otherwise falls back to types of
10650 DECL_ARGUMENTS types. */
10652 vec<tree>
10653 simd_clone_vector_of_formal_parm_types (tree fndecl)
10655 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
10656 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
10657 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
10658 unsigned int i;
10659 tree arg;
10660 FOR_EACH_VEC_ELT (args, i, arg)
10661 args[i] = TREE_TYPE (args[i]);
10662 return args;
10665 /* Given a simd function in NODE, extract the simd specific
10666 information from the OMP clauses passed in CLAUSES, and return
10667 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
10668 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
10669 otherwise set to FALSE. */
10671 static struct cgraph_simd_clone *
10672 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
10673 bool *inbranch_specified)
10675 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
10676 tree t;
10677 int n;
10678 *inbranch_specified = false;
10680 n = args.length ();
10681 if (n > 0 && args.last () == void_type_node)
10682 n--;
10684 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
10685 be cloned have a distinctive artificial label in addition to "omp
10686 declare simd". */
10687 bool cilk_clone
10688 = (flag_enable_cilkplus
10689 && lookup_attribute ("cilk plus elemental",
10690 DECL_ATTRIBUTES (node->decl)));
10692 /* Allocate one more than needed just in case this is an in-branch
10693 clone which will require a mask argument. */
10694 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
10695 clone_info->nargs = n;
10696 clone_info->cilk_elemental = cilk_clone;
10698 if (!clauses)
10700 args.release ();
10701 return clone_info;
10703 clauses = TREE_VALUE (clauses);
10704 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
10705 return clone_info;
10707 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
10709 switch (OMP_CLAUSE_CODE (t))
10711 case OMP_CLAUSE_INBRANCH:
10712 clone_info->inbranch = 1;
10713 *inbranch_specified = true;
10714 break;
10715 case OMP_CLAUSE_NOTINBRANCH:
10716 clone_info->inbranch = 0;
10717 *inbranch_specified = true;
10718 break;
10719 case OMP_CLAUSE_SIMDLEN:
10720 clone_info->simdlen
10721 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
10722 break;
10723 case OMP_CLAUSE_LINEAR:
10725 tree decl = OMP_CLAUSE_DECL (t);
10726 tree step = OMP_CLAUSE_LINEAR_STEP (t);
10727 int argno = TREE_INT_CST_LOW (decl);
10728 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
10730 clone_info->args[argno].arg_type
10731 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
10732 clone_info->args[argno].linear_step = tree_to_shwi (step);
10733 gcc_assert (clone_info->args[argno].linear_step >= 0
10734 && clone_info->args[argno].linear_step < n);
10736 else
10738 if (POINTER_TYPE_P (args[argno]))
10739 step = fold_convert (ssizetype, step);
10740 if (!tree_fits_shwi_p (step))
10742 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10743 "ignoring large linear step");
10744 args.release ();
10745 return NULL;
10747 else if (integer_zerop (step))
10749 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10750 "ignoring zero linear step");
10751 args.release ();
10752 return NULL;
10754 else
10756 clone_info->args[argno].arg_type
10757 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
10758 clone_info->args[argno].linear_step = tree_to_shwi (step);
10761 break;
10763 case OMP_CLAUSE_UNIFORM:
10765 tree decl = OMP_CLAUSE_DECL (t);
10766 int argno = tree_to_uhwi (decl);
10767 clone_info->args[argno].arg_type
10768 = SIMD_CLONE_ARG_TYPE_UNIFORM;
10769 break;
10771 case OMP_CLAUSE_ALIGNED:
10773 tree decl = OMP_CLAUSE_DECL (t);
10774 int argno = tree_to_uhwi (decl);
10775 clone_info->args[argno].alignment
10776 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
10777 break;
10779 default:
10780 break;
10783 args.release ();
10784 return clone_info;
10787 /* Given a SIMD clone in NODE, calculate the characteristic data
10788 type and return the coresponding type. The characteristic data
10789 type is computed as described in the Intel Vector ABI. */
10791 static tree
10792 simd_clone_compute_base_data_type (struct cgraph_node *node,
10793 struct cgraph_simd_clone *clone_info)
10795 tree type = integer_type_node;
10796 tree fndecl = node->decl;
10798 /* a) For non-void function, the characteristic data type is the
10799 return type. */
10800 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
10801 type = TREE_TYPE (TREE_TYPE (fndecl));
10803 /* b) If the function has any non-uniform, non-linear parameters,
10804 then the characteristic data type is the type of the first
10805 such parameter. */
10806 else
10808 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
10809 for (unsigned int i = 0; i < clone_info->nargs; ++i)
10810 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
10812 type = map[i];
10813 break;
10815 map.release ();
10818 /* c) If the characteristic data type determined by a) or b) above
10819 is struct, union, or class type which is pass-by-value (except
10820 for the type that maps to the built-in complex data type), the
10821 characteristic data type is int. */
10822 if (RECORD_OR_UNION_TYPE_P (type)
10823 && !aggregate_value_p (type, NULL)
10824 && TREE_CODE (type) != COMPLEX_TYPE)
10825 return integer_type_node;
10827 /* d) If none of the above three classes is applicable, the
10828 characteristic data type is int. */
10830 return type;
10832 /* e) For Intel Xeon Phi native and offload compilation, if the
10833 resulting characteristic data type is 8-bit or 16-bit integer
10834 data type, the characteristic data type is int. */
10835 /* Well, we don't handle Xeon Phi yet. */
10838 static tree
10839 simd_clone_mangle (struct cgraph_node *node,
10840 struct cgraph_simd_clone *clone_info)
10842 char vecsize_mangle = clone_info->vecsize_mangle;
10843 char mask = clone_info->inbranch ? 'M' : 'N';
10844 unsigned int simdlen = clone_info->simdlen;
10845 unsigned int n;
10846 pretty_printer pp;
10848 gcc_assert (vecsize_mangle && simdlen);
10850 pp_string (&pp, "_ZGV");
10851 pp_character (&pp, vecsize_mangle);
10852 pp_character (&pp, mask);
10853 pp_decimal_int (&pp, simdlen);
10855 for (n = 0; n < clone_info->nargs; ++n)
10857 struct cgraph_simd_clone_arg arg = clone_info->args[n];
10859 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
10860 pp_character (&pp, 'u');
10861 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
10863 gcc_assert (arg.linear_step != 0);
10864 pp_character (&pp, 'l');
10865 if (arg.linear_step > 1)
10866 pp_unsigned_wide_integer (&pp, arg.linear_step);
10867 else if (arg.linear_step < 0)
10869 pp_character (&pp, 'n');
10870 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
10871 arg.linear_step));
10874 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
10876 pp_character (&pp, 's');
10877 pp_unsigned_wide_integer (&pp, arg.linear_step);
10879 else
10880 pp_character (&pp, 'v');
10881 if (arg.alignment)
10883 pp_character (&pp, 'a');
10884 pp_decimal_int (&pp, arg.alignment);
10888 pp_underscore (&pp);
10889 pp_string (&pp,
10890 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
10891 const char *str = pp_formatted_text (&pp);
10893 /* If there already is a SIMD clone with the same mangled name, don't
10894 add another one. This can happen e.g. for
10895 #pragma omp declare simd
10896 #pragma omp declare simd simdlen(8)
10897 int foo (int, int);
10898 if the simdlen is assumed to be 8 for the first one, etc. */
10899 for (struct cgraph_node *clone = node->simd_clones; clone;
10900 clone = clone->simdclone->next_clone)
10901 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
10902 str) == 0)
10903 return NULL_TREE;
10905 return get_identifier (str);
10908 /* Create a simd clone of OLD_NODE and return it. */
10910 static struct cgraph_node *
10911 simd_clone_create (struct cgraph_node *old_node)
10913 struct cgraph_node *new_node;
10914 if (old_node->definition)
10915 new_node = cgraph_function_versioning (old_node, vNULL, NULL, NULL, false,
10916 NULL, NULL, "simdclone");
10917 else
10919 tree old_decl = old_node->decl;
10920 tree new_decl = copy_node (old_node->decl);
10921 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
10922 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
10923 SET_DECL_RTL (new_decl, NULL);
10924 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
10925 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
10926 new_node
10927 = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL);
10928 cgraph_call_function_insertion_hooks (new_node);
10930 if (new_node == NULL)
10931 return new_node;
10933 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
10935 /* The function cgraph_function_versioning () will force the new
10936 symbol local. Undo this, and inherit external visability from
10937 the old node. */
10938 new_node->local.local = old_node->local.local;
10939 new_node->externally_visible = old_node->externally_visible;
10941 return new_node;
10944 /* Adjust the return type of the given function to its appropriate
10945 vector counterpart. Returns a simd array to be used throughout the
10946 function as a return value. */
10948 static tree
10949 simd_clone_adjust_return_type (struct cgraph_node *node)
10951 tree fndecl = node->decl;
10952 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
10953 unsigned int veclen;
10954 tree t;
10956 /* Adjust the function return type. */
10957 if (orig_rettype == void_type_node)
10958 return NULL_TREE;
10959 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
10960 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
10961 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
10962 veclen = node->simdclone->vecsize_int;
10963 else
10964 veclen = node->simdclone->vecsize_float;
10965 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
10966 if (veclen > node->simdclone->simdlen)
10967 veclen = node->simdclone->simdlen;
10968 if (veclen == node->simdclone->simdlen)
10969 TREE_TYPE (TREE_TYPE (fndecl))
10970 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
10971 node->simdclone->simdlen);
10972 else
10974 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
10975 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
10976 TREE_TYPE (TREE_TYPE (fndecl)) = t;
10978 if (!node->definition)
10979 return NULL_TREE;
10981 t = DECL_RESULT (fndecl);
10982 /* Adjust the DECL_RESULT. */
10983 gcc_assert (TREE_TYPE (t) != void_type_node);
10984 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
10985 relayout_decl (t);
10987 tree atype = build_array_type_nelts (orig_rettype,
10988 node->simdclone->simdlen);
10989 if (veclen != node->simdclone->simdlen)
10990 return build1 (VIEW_CONVERT_EXPR, atype, t);
10992 /* Set up a SIMD array to use as the return value. */
10993 tree retval = create_tmp_var_raw (atype, "retval");
10994 gimple_add_tmp_var (retval);
10995 return retval;
10998 /* Each vector argument has a corresponding array to be used locally
10999 as part of the eventual loop. Create such temporary array and
11000 return it.
11002 PREFIX is the prefix to be used for the temporary.
11004 TYPE is the inner element type.
11006 SIMDLEN is the number of elements. */
11008 static tree
11009 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11011 tree atype = build_array_type_nelts (type, simdlen);
11012 tree avar = create_tmp_var_raw (atype, prefix);
11013 gimple_add_tmp_var (avar);
11014 return avar;
11017 /* Modify the function argument types to their corresponding vector
11018 counterparts if appropriate. Also, create one array for each simd
11019 argument to be used locally when using the function arguments as
11020 part of the loop.
11022 NODE is the function whose arguments are to be adjusted.
11024 Returns an adjustment vector that will be filled describing how the
11025 argument types will be adjusted. */
11027 static ipa_parm_adjustment_vec
11028 simd_clone_adjust_argument_types (struct cgraph_node *node)
11030 vec<tree> args;
11031 ipa_parm_adjustment_vec adjustments;
11033 if (node->definition)
11034 args = ipa_get_vector_of_formal_parms (node->decl);
11035 else
11036 args = simd_clone_vector_of_formal_parm_types (node->decl);
11037 adjustments.create (args.length ());
11038 unsigned i, j, veclen;
11039 struct ipa_parm_adjustment adj;
11040 for (i = 0; i < node->simdclone->nargs; ++i)
11042 memset (&adj, 0, sizeof (adj));
11043 tree parm = args[i];
11044 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11045 adj.base_index = i;
11046 adj.base = parm;
11048 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11049 node->simdclone->args[i].orig_type = parm_type;
11051 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11053 /* No adjustment necessary for scalar arguments. */
11054 adj.op = IPA_PARM_OP_COPY;
11056 else
11058 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11059 veclen = node->simdclone->vecsize_int;
11060 else
11061 veclen = node->simdclone->vecsize_float;
11062 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11063 if (veclen > node->simdclone->simdlen)
11064 veclen = node->simdclone->simdlen;
11065 adj.arg_prefix = "simd";
11066 adj.type = build_vector_type (parm_type, veclen);
11067 node->simdclone->args[i].vector_type = adj.type;
11068 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11070 adjustments.safe_push (adj);
11071 if (j == veclen)
11073 memset (&adj, 0, sizeof (adj));
11074 adj.op = IPA_PARM_OP_NEW;
11075 adj.arg_prefix = "simd";
11076 adj.base_index = i;
11077 adj.type = node->simdclone->args[i].vector_type;
11081 if (node->definition)
11082 node->simdclone->args[i].simd_array
11083 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11084 parm_type, node->simdclone->simdlen);
11086 adjustments.safe_push (adj);
11089 if (node->simdclone->inbranch)
11091 tree base_type
11092 = simd_clone_compute_base_data_type (node->simdclone->origin,
11093 node->simdclone);
11095 memset (&adj, 0, sizeof (adj));
11096 adj.op = IPA_PARM_OP_NEW;
11097 adj.arg_prefix = "mask";
11099 adj.base_index = i;
11100 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11101 veclen = node->simdclone->vecsize_int;
11102 else
11103 veclen = node->simdclone->vecsize_float;
11104 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11105 if (veclen > node->simdclone->simdlen)
11106 veclen = node->simdclone->simdlen;
11107 adj.type = build_vector_type (base_type, veclen);
11108 adjustments.safe_push (adj);
11110 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11111 adjustments.safe_push (adj);
11113 /* We have previously allocated one extra entry for the mask. Use
11114 it and fill it. */
11115 struct cgraph_simd_clone *sc = node->simdclone;
11116 sc->nargs++;
11117 if (node->definition)
11119 sc->args[i].orig_arg
11120 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11121 sc->args[i].simd_array
11122 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11124 sc->args[i].orig_type = base_type;
11125 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11128 if (node->definition)
11129 ipa_modify_formal_parameters (node->decl, adjustments);
11130 else
11132 tree new_arg_types = NULL_TREE, new_reversed;
11133 bool last_parm_void = false;
11134 if (args.length () > 0 && args.last () == void_type_node)
11135 last_parm_void = true;
11137 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11138 j = adjustments.length ();
11139 for (i = 0; i < j; i++)
11141 struct ipa_parm_adjustment *adj = &adjustments[i];
11142 tree ptype;
11143 if (adj->op == IPA_PARM_OP_COPY)
11144 ptype = args[adj->base_index];
11145 else
11146 ptype = adj->type;
11147 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11149 new_reversed = nreverse (new_arg_types);
11150 if (last_parm_void)
11152 if (new_reversed)
11153 TREE_CHAIN (new_arg_types) = void_list_node;
11154 else
11155 new_reversed = void_list_node;
11158 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11159 TYPE_ARG_TYPES (new_type) = new_reversed;
11160 TREE_TYPE (node->decl) = new_type;
11162 adjustments.release ();
11164 args.release ();
11165 return adjustments;
11168 /* Initialize and copy the function arguments in NODE to their
11169 corresponding local simd arrays. Returns a fresh gimple_seq with
11170 the instruction sequence generated. */
11172 static gimple_seq
11173 simd_clone_init_simd_arrays (struct cgraph_node *node,
11174 ipa_parm_adjustment_vec adjustments)
11176 gimple_seq seq = NULL;
11177 unsigned i = 0, j = 0, k;
11179 for (tree arg = DECL_ARGUMENTS (node->decl);
11180 arg;
11181 arg = DECL_CHAIN (arg), i++, j++)
11183 if (adjustments[j].op == IPA_PARM_OP_COPY)
11184 continue;
11186 node->simdclone->args[i].vector_arg = arg;
11188 tree array = node->simdclone->args[i].simd_array;
11189 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11191 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11192 tree ptr = build_fold_addr_expr (array);
11193 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11194 build_int_cst (ptype, 0));
11195 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11196 gimplify_and_add (t, &seq);
11198 else
11200 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11201 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11202 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11204 tree ptr = build_fold_addr_expr (array);
11205 int elemsize;
11206 if (k)
11208 arg = DECL_CHAIN (arg);
11209 j++;
11211 elemsize
11212 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11213 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11214 build_int_cst (ptype, k * elemsize));
11215 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11216 gimplify_and_add (t, &seq);
11220 return seq;
11223 /* Callback info for ipa_simd_modify_stmt_ops below. */
11225 struct modify_stmt_info {
11226 ipa_parm_adjustment_vec adjustments;
11227 gimple stmt;
11228 /* True if the parent statement was modified by
11229 ipa_simd_modify_stmt_ops. */
11230 bool modified;
11233 /* Callback for walk_gimple_op.
11235 Adjust operands from a given statement as specified in the
11236 adjustments vector in the callback data. */
11238 static tree
11239 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11241 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11242 if (!SSA_VAR_P (*tp))
11244 /* Make sure we treat subtrees as a RHS. This makes sure that
11245 when examining the `*foo' in *foo=x, the `foo' get treated as
11246 a use properly. */
11247 wi->is_lhs = false;
11248 wi->val_only = true;
11249 if (TYPE_P (*tp))
11250 *walk_subtrees = 0;
11251 return NULL_TREE;
11253 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11254 struct ipa_parm_adjustment *cand
11255 = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11256 if (!cand)
11257 return NULL_TREE;
11259 tree t = *tp;
11260 tree repl = make_ssa_name (TREE_TYPE (t), NULL);
11262 gimple stmt;
11263 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11264 if (wi->is_lhs)
11266 stmt = gimple_build_assign (unshare_expr (cand->new_decl), repl);
11267 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
11268 SSA_NAME_DEF_STMT (repl) = info->stmt;
11270 else
11272 /* You'd think we could skip the extra SSA variable when
11273 wi->val_only=true, but we may have `*var' which will get
11274 replaced into `*var_array[iter]' and will likely be something
11275 not gimple. */
11276 stmt = gimple_build_assign (repl, unshare_expr (cand->new_decl));
11277 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11280 if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11282 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11283 *tp = vce;
11285 else
11286 *tp = repl;
11288 info->modified = true;
11289 wi->is_lhs = false;
11290 wi->val_only = true;
11291 return NULL_TREE;
11294 /* Traverse the function body and perform all modifications as
11295 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11296 modified such that the replacement/reduction value will now be an
11297 offset into the corresponding simd_array.
11299 This function will replace all function argument uses with their
11300 corresponding simd array elements, and ajust the return values
11301 accordingly. */
11303 static void
11304 ipa_simd_modify_function_body (struct cgraph_node *node,
11305 ipa_parm_adjustment_vec adjustments,
11306 tree retval_array, tree iter)
11308 basic_block bb;
11309 unsigned int i, j;
11311 /* Re-use the adjustments array, but this time use it to replace
11312 every function argument use to an offset into the corresponding
11313 simd_array. */
11314 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11316 if (!node->simdclone->args[i].vector_arg)
11317 continue;
11319 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11320 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11321 adjustments[j].new_decl
11322 = build4 (ARRAY_REF,
11323 basetype,
11324 node->simdclone->args[i].simd_array,
11325 iter,
11326 NULL_TREE, NULL_TREE);
11327 if (adjustments[j].op == IPA_PARM_OP_NONE
11328 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11329 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11332 struct modify_stmt_info info;
11333 info.adjustments = adjustments;
11335 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
11337 gimple_stmt_iterator gsi;
11339 gsi = gsi_start_bb (bb);
11340 while (!gsi_end_p (gsi))
11342 gimple stmt = gsi_stmt (gsi);
11343 info.stmt = stmt;
11344 struct walk_stmt_info wi;
11346 memset (&wi, 0, sizeof (wi));
11347 info.modified = false;
11348 wi.info = &info;
11349 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
11351 if (gimple_code (stmt) == GIMPLE_RETURN)
11353 tree retval = gimple_return_retval (stmt);
11354 if (!retval)
11356 gsi_remove (&gsi, true);
11357 continue;
11360 /* Replace `return foo' with `retval_array[iter] = foo'. */
11361 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
11362 retval_array, iter, NULL, NULL);
11363 stmt = gimple_build_assign (ref, retval);
11364 gsi_replace (&gsi, stmt, true);
11365 info.modified = true;
11368 if (info.modified)
11370 update_stmt (stmt);
11371 if (maybe_clean_eh_stmt (stmt))
11372 gimple_purge_dead_eh_edges (gimple_bb (stmt));
11374 gsi_next (&gsi);
11379 /* Adjust the argument types in NODE to their appropriate vector
11380 counterparts. */
11382 static void
11383 simd_clone_adjust (struct cgraph_node *node)
11385 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
11387 targetm.simd_clone.adjust (node);
11389 tree retval = simd_clone_adjust_return_type (node);
11390 ipa_parm_adjustment_vec adjustments
11391 = simd_clone_adjust_argument_types (node);
11393 push_gimplify_context ();
11395 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
11397 /* Adjust all uses of vector arguments accordingly. Adjust all
11398 return values accordingly. */
11399 tree iter = create_tmp_var (unsigned_type_node, "iter");
11400 tree iter1 = make_ssa_name (iter, NULL);
11401 tree iter2 = make_ssa_name (iter, NULL);
11402 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
11404 /* Initialize the iteration variable. */
11405 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11406 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
11407 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
11408 /* Insert the SIMD array and iv initialization at function
11409 entry. */
11410 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
11412 pop_gimplify_context (NULL);
11414 /* Create a new BB right before the original exit BB, to hold the
11415 iteration increment and the condition/branch. */
11416 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
11417 basic_block incr_bb = create_empty_bb (orig_exit);
11418 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11419 flag. Set it now to be a FALLTHRU_EDGE. */
11420 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
11421 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
11422 for (unsigned i = 0;
11423 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
11425 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
11426 redirect_edge_succ (e, incr_bb);
11428 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
11429 e->probability = REG_BR_PROB_BASE;
11430 gsi = gsi_last_bb (incr_bb);
11431 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
11432 build_int_cst (unsigned_type_node,
11433 1));
11434 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11436 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
11437 struct loop *loop = alloc_loop ();
11438 cfun->has_force_vect_loops = true;
11439 loop->safelen = node->simdclone->simdlen;
11440 loop->force_vect = true;
11441 loop->header = body_bb;
11442 add_bb_to_loop (incr_bb, loop);
11444 /* Branch around the body if the mask applies. */
11445 if (node->simdclone->inbranch)
11447 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
11448 tree mask_array
11449 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
11450 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
11451 tree aref = build4 (ARRAY_REF,
11452 TREE_TYPE (TREE_TYPE (mask_array)),
11453 mask_array, iter1,
11454 NULL, NULL);
11455 g = gimple_build_assign (mask, aref);
11456 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11457 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
11458 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
11460 aref = build1 (VIEW_CONVERT_EXPR,
11461 build_nonstandard_integer_type (bitsize, 0), mask);
11462 mask = make_ssa_name (TREE_TYPE (aref), NULL);
11463 g = gimple_build_assign (mask, aref);
11464 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11467 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
11468 NULL, NULL);
11469 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11470 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
11471 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
11474 /* Generate the condition. */
11475 g = gimple_build_cond (LT_EXPR,
11476 iter2,
11477 build_int_cst (unsigned_type_node,
11478 node->simdclone->simdlen),
11479 NULL, NULL);
11480 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11481 e = split_block (incr_bb, gsi_stmt (gsi));
11482 basic_block latch_bb = e->dest;
11483 basic_block new_exit_bb = e->dest;
11484 new_exit_bb = split_block (latch_bb, NULL)->dest;
11485 loop->latch = latch_bb;
11487 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
11489 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
11490 /* The successor of incr_bb is already pointing to latch_bb; just
11491 change the flags.
11492 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
11493 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
11495 gimple phi = create_phi_node (iter1, body_bb);
11496 edge preheader_edge = find_edge (entry_bb, body_bb);
11497 edge latch_edge = single_succ_edge (latch_bb);
11498 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
11499 UNKNOWN_LOCATION);
11500 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11502 /* Generate the new return. */
11503 gsi = gsi_last_bb (new_exit_bb);
11504 if (retval
11505 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
11506 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
11507 retval = TREE_OPERAND (retval, 0);
11508 else if (retval)
11510 retval = build1 (VIEW_CONVERT_EXPR,
11511 TREE_TYPE (TREE_TYPE (node->decl)),
11512 retval);
11513 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
11514 false, GSI_CONTINUE_LINKING);
11516 g = gimple_build_return (retval);
11517 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11519 /* Handle aligned clauses by replacing default defs of the aligned
11520 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
11521 lhs. Handle linear by adding PHIs. */
11522 for (unsigned i = 0; i < node->simdclone->nargs; i++)
11523 if (node->simdclone->args[i].alignment
11524 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
11525 && (node->simdclone->args[i].alignment
11526 & (node->simdclone->args[i].alignment - 1)) == 0
11527 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
11528 == POINTER_TYPE)
11530 unsigned int alignment = node->simdclone->args[i].alignment;
11531 tree orig_arg = node->simdclone->args[i].orig_arg;
11532 tree def = ssa_default_def (cfun, orig_arg);
11533 if (!has_zero_uses (def))
11535 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
11536 gimple_seq seq = NULL;
11537 bool need_cvt = false;
11538 gimple call
11539 = gimple_build_call (fn, 2, def, size_int (alignment));
11540 g = call;
11541 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
11542 ptr_type_node))
11543 need_cvt = true;
11544 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
11545 gimple_call_set_lhs (g, t);
11546 gimple_seq_add_stmt_without_update (&seq, g);
11547 if (need_cvt)
11549 t = make_ssa_name (orig_arg, NULL);
11550 g = gimple_build_assign_with_ops (NOP_EXPR, t,
11551 gimple_call_lhs (g),
11552 NULL_TREE);
11553 gimple_seq_add_stmt_without_update (&seq, g);
11555 gsi_insert_seq_on_edge_immediate
11556 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
11558 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11559 int freq = compute_call_stmt_bb_frequency (current_function_decl,
11560 entry_bb);
11561 cgraph_create_edge (node, cgraph_get_create_node (fn),
11562 call, entry_bb->count, freq);
11564 imm_use_iterator iter;
11565 use_operand_p use_p;
11566 gimple use_stmt;
11567 tree repl = gimple_get_lhs (g);
11568 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11569 if (is_gimple_debug (use_stmt) || use_stmt == call)
11570 continue;
11571 else
11572 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11573 SET_USE (use_p, repl);
11576 else if (node->simdclone->args[i].arg_type
11577 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11579 tree orig_arg = node->simdclone->args[i].orig_arg;
11580 tree def = ssa_default_def (cfun, orig_arg);
11581 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11582 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
11583 if (!has_zero_uses (def))
11585 iter1 = make_ssa_name (orig_arg, NULL);
11586 iter2 = make_ssa_name (orig_arg, NULL);
11587 phi = create_phi_node (iter1, body_bb);
11588 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
11589 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11590 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11591 ? PLUS_EXPR : POINTER_PLUS_EXPR;
11592 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11593 ? TREE_TYPE (orig_arg) : sizetype;
11594 tree addcst
11595 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
11596 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
11597 gsi = gsi_last_bb (incr_bb);
11598 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
11600 imm_use_iterator iter;
11601 use_operand_p use_p;
11602 gimple use_stmt;
11603 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11604 if (use_stmt == phi)
11605 continue;
11606 else
11607 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11608 SET_USE (use_p, iter1);
11612 calculate_dominance_info (CDI_DOMINATORS);
11613 add_loop (loop, loop->header->loop_father);
11614 update_ssa (TODO_update_ssa);
11616 pop_cfun ();
11619 /* If the function in NODE is tagged as an elemental SIMD function,
11620 create the appropriate SIMD clones. */
11622 static void
11623 expand_simd_clones (struct cgraph_node *node)
11625 if (lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
11626 return;
11628 tree attr = lookup_attribute ("omp declare simd",
11629 DECL_ATTRIBUTES (node->decl));
11630 if (!attr || targetm.simd_clone.compute_vecsize_and_simdlen == NULL)
11631 return;
11632 /* Ignore
11633 #pragma omp declare simd
11634 extern int foo ();
11635 in C, there we don't know the argument types at all. */
11636 if (!node->definition
11637 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
11638 return;
11642 /* Start with parsing the "omp declare simd" attribute(s). */
11643 bool inbranch_clause_specified;
11644 struct cgraph_simd_clone *clone_info
11645 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
11646 &inbranch_clause_specified);
11647 if (clone_info == NULL)
11648 continue;
11650 int orig_simdlen = clone_info->simdlen;
11651 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
11652 /* The target can return 0 (no simd clones should be created),
11653 1 (just one ISA of simd clones should be created) or higher
11654 count of ISA variants. In that case, clone_info is initialized
11655 for the first ISA variant. */
11656 int count
11657 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
11658 base_type, 0);
11659 if (count == 0)
11660 continue;
11662 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
11663 also create one inbranch and one !inbranch clone of it. */
11664 for (int i = 0; i < count * 2; i++)
11666 struct cgraph_simd_clone *clone = clone_info;
11667 if (inbranch_clause_specified && (i & 1) != 0)
11668 continue;
11670 if (i != 0)
11672 clone = simd_clone_struct_alloc (clone_info->nargs
11673 - clone_info->inbranch
11674 + ((i & 1) != 0));
11675 simd_clone_struct_copy (clone, clone_info);
11676 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
11677 and simd_clone_adjust_argument_types did to the first
11678 clone's info. */
11679 clone->nargs -= clone_info->inbranch;
11680 clone->simdlen = orig_simdlen;
11681 /* And call the target hook again to get the right ISA. */
11682 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
11683 base_type,
11684 i / 2);
11685 if ((i & 1) != 0)
11686 clone->inbranch = 1;
11689 /* simd_clone_mangle might fail if such a clone has been created
11690 already. */
11691 tree id = simd_clone_mangle (node, clone);
11692 if (id == NULL_TREE)
11693 continue;
11695 /* Only when we are sure we want to create the clone actually
11696 clone the function (or definitions) or create another
11697 extern FUNCTION_DECL (for prototypes without definitions). */
11698 struct cgraph_node *n = simd_clone_create (node);
11699 if (n == NULL)
11700 continue;
11702 n->simdclone = clone;
11703 clone->origin = node;
11704 clone->next_clone = NULL;
11705 if (node->simd_clones == NULL)
11707 clone->prev_clone = n;
11708 node->simd_clones = n;
11710 else
11712 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
11713 clone->prev_clone->simdclone->next_clone = n;
11714 node->simd_clones->simdclone->prev_clone = n;
11716 change_decl_assembler_name (n->decl, id);
11717 /* And finally adjust the return type, parameters and for
11718 definitions also function body. */
11719 if (node->definition)
11720 simd_clone_adjust (n);
11721 else
11723 simd_clone_adjust_return_type (n);
11724 simd_clone_adjust_argument_types (n);
11728 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
11731 /* Entry point for IPA simd clone creation pass. */
11733 static unsigned int
11734 ipa_omp_simd_clone (void)
11736 struct cgraph_node *node;
11737 FOR_EACH_FUNCTION (node)
11738 expand_simd_clones (node);
11739 return 0;
11742 namespace {
11744 const pass_data pass_data_omp_simd_clone =
11746 SIMPLE_IPA_PASS, /* type */
11747 "simdclone", /* name */
11748 OPTGROUP_NONE, /* optinfo_flags */
11749 true, /* has_gate */
11750 true, /* has_execute */
11751 TV_NONE, /* tv_id */
11752 ( PROP_ssa | PROP_cfg ), /* properties_required */
11753 0, /* properties_provided */
11754 0, /* properties_destroyed */
11755 0, /* todo_flags_start */
11756 0, /* todo_flags_finish */
11759 class pass_omp_simd_clone : public simple_ipa_opt_pass
11761 public:
11762 pass_omp_simd_clone(gcc::context *ctxt)
11763 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
11766 /* opt_pass methods: */
11767 bool gate () { return flag_openmp || flag_openmp_simd
11768 || flag_enable_cilkplus; }
11769 unsigned int execute () { return ipa_omp_simd_clone (); }
11772 } // anon namespace
11774 simple_ipa_opt_pass *
11775 make_pass_omp_simd_clone (gcc::context *ctxt)
11777 return new pass_omp_simd_clone (ctxt);
11780 #include "gt-omp-low.h"