* lto-partition.c (add_symbol_to_partition_1,
[official-gcc.git] / gcc / omp-low.c
blob91c8656ee9cb04c4d9c59761411653bf4c22cb81
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005-2014 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "stringpool.h"
30 #include "stor-layout.h"
31 #include "rtl.h"
32 #include "pointer-set.h"
33 #include "basic-block.h"
34 #include "tree-ssa-alias.h"
35 #include "internal-fn.h"
36 #include "gimple-fold.h"
37 #include "gimple-expr.h"
38 #include "is-a.h"
39 #include "gimple.h"
40 #include "gimplify.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "gimple-walk.h"
44 #include "tree-iterator.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47 #include "diagnostic-core.h"
48 #include "gimple-ssa.h"
49 #include "cgraph.h"
50 #include "tree-cfg.h"
51 #include "tree-phinodes.h"
52 #include "ssa-iterators.h"
53 #include "tree-ssanames.h"
54 #include "tree-into-ssa.h"
55 #include "expr.h"
56 #include "tree-dfa.h"
57 #include "tree-ssa.h"
58 #include "flags.h"
59 #include "function.h"
60 #include "expr.h"
61 #include "tree-pass.h"
62 #include "except.h"
63 #include "splay-tree.h"
64 #include "optabs.h"
65 #include "cfgloop.h"
66 #include "target.h"
67 #include "omp-low.h"
68 #include "gimple-low.h"
69 #include "tree-cfgcleanup.h"
70 #include "pretty-print.h"
71 #include "ipa-prop.h"
72 #include "tree-nested.h"
73 #include "tree-eh.h"
76 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
77 phases. The first phase scans the function looking for OMP statements
78 and then for variables that must be replaced to satisfy data sharing
79 clauses. The second phase expands code for the constructs, as well as
80 re-gimplifying things when variables have been replaced with complex
81 expressions.
83 Final code generation is done by pass_expand_omp. The flowgraph is
84 scanned for parallel regions which are then moved to a new
85 function, to be invoked by the thread library. */
87 /* Parallel region information. Every parallel and workshare
88 directive is enclosed between two markers, the OMP_* directive
89 and a corresponding OMP_RETURN statement. */
91 struct omp_region
93 /* The enclosing region. */
94 struct omp_region *outer;
96 /* First child region. */
97 struct omp_region *inner;
99 /* Next peer region. */
100 struct omp_region *next;
102 /* Block containing the omp directive as its last stmt. */
103 basic_block entry;
105 /* Block containing the OMP_RETURN as its last stmt. */
106 basic_block exit;
108 /* Block containing the OMP_CONTINUE as its last stmt. */
109 basic_block cont;
111 /* If this is a combined parallel+workshare region, this is a list
112 of additional arguments needed by the combined parallel+workshare
113 library call. */
114 vec<tree, va_gc> *ws_args;
116 /* The code for the omp directive of this region. */
117 enum gimple_code type;
119 /* Schedule kind, only used for OMP_FOR type regions. */
120 enum omp_clause_schedule_kind sched_kind;
122 /* True if this is a combined parallel+workshare region. */
123 bool is_combined_parallel;
126 /* Context structure. Used to store information about each parallel
127 directive in the code. */
129 typedef struct omp_context
131 /* This field must be at the beginning, as we do "inheritance": Some
132 callback functions for tree-inline.c (e.g., omp_copy_decl)
133 receive a copy_body_data pointer that is up-casted to an
134 omp_context pointer. */
135 copy_body_data cb;
137 /* The tree of contexts corresponding to the encountered constructs. */
138 struct omp_context *outer;
139 gimple stmt;
141 /* Map variables to fields in a structure that allows communication
142 between sending and receiving threads. */
143 splay_tree field_map;
144 tree record_type;
145 tree sender_decl;
146 tree receiver_decl;
148 /* These are used just by task contexts, if task firstprivate fn is
149 needed. srecord_type is used to communicate from the thread
150 that encountered the task construct to task firstprivate fn,
151 record_type is allocated by GOMP_task, initialized by task firstprivate
152 fn and passed to the task body fn. */
153 splay_tree sfield_map;
154 tree srecord_type;
156 /* A chain of variables to add to the top-level block surrounding the
157 construct. In the case of a parallel, this is in the child function. */
158 tree block_vars;
160 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
161 barriers should jump to during omplower pass. */
162 tree cancel_label;
164 /* What to do with variables with implicitly determined sharing
165 attributes. */
166 enum omp_clause_default_kind default_kind;
168 /* Nesting depth of this context. Used to beautify error messages re
169 invalid gotos. The outermost ctx is depth 1, with depth 0 being
170 reserved for the main body of the function. */
171 int depth;
173 /* True if this parallel directive is nested within another. */
174 bool is_nested;
176 /* True if this construct can be cancelled. */
177 bool cancellable;
178 } omp_context;
181 struct omp_for_data_loop
183 tree v, n1, n2, step;
184 enum tree_code cond_code;
187 /* A structure describing the main elements of a parallel loop. */
189 struct omp_for_data
191 struct omp_for_data_loop loop;
192 tree chunk_size;
193 gimple for_stmt;
194 tree pre, iter_type;
195 int collapse;
196 bool have_nowait, have_ordered;
197 enum omp_clause_schedule_kind sched_kind;
198 struct omp_for_data_loop *loops;
202 static splay_tree all_contexts;
203 static int taskreg_nesting_level;
204 static int target_nesting_level;
205 static struct omp_region *root_omp_region;
206 static bitmap task_shared_vars;
208 static void scan_omp (gimple_seq *, omp_context *);
209 static tree scan_omp_1_op (tree *, int *, void *);
211 #define WALK_SUBSTMTS \
212 case GIMPLE_BIND: \
213 case GIMPLE_TRY: \
214 case GIMPLE_CATCH: \
215 case GIMPLE_EH_FILTER: \
216 case GIMPLE_TRANSACTION: \
217 /* The sub-statements for these should be walked. */ \
218 *handled_ops_p = false; \
219 break;
221 /* Convenience function for calling scan_omp_1_op on tree operands. */
223 static inline tree
224 scan_omp_op (tree *tp, omp_context *ctx)
226 struct walk_stmt_info wi;
228 memset (&wi, 0, sizeof (wi));
229 wi.info = ctx;
230 wi.want_locations = true;
232 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
235 static void lower_omp (gimple_seq *, omp_context *);
236 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
237 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
239 /* Find an OpenMP clause of type KIND within CLAUSES. */
241 tree
242 find_omp_clause (tree clauses, enum omp_clause_code kind)
244 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
245 if (OMP_CLAUSE_CODE (clauses) == kind)
246 return clauses;
248 return NULL_TREE;
251 /* Return true if CTX is for an omp parallel. */
253 static inline bool
254 is_parallel_ctx (omp_context *ctx)
256 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
260 /* Return true if CTX is for an omp task. */
262 static inline bool
263 is_task_ctx (omp_context *ctx)
265 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
269 /* Return true if CTX is for an omp parallel or omp task. */
271 static inline bool
272 is_taskreg_ctx (omp_context *ctx)
274 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
275 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
279 /* Return true if REGION is a combined parallel+workshare region. */
281 static inline bool
282 is_combined_parallel (struct omp_region *region)
284 return region->is_combined_parallel;
288 /* Extract the header elements of parallel loop FOR_STMT and store
289 them into *FD. */
291 static void
292 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
293 struct omp_for_data_loop *loops)
295 tree t, var, *collapse_iter, *collapse_count;
296 tree count = NULL_TREE, iter_type = long_integer_type_node;
297 struct omp_for_data_loop *loop;
298 int i;
299 struct omp_for_data_loop dummy_loop;
300 location_t loc = gimple_location (for_stmt);
301 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_KIND_SIMD;
302 bool distribute = gimple_omp_for_kind (for_stmt)
303 == GF_OMP_FOR_KIND_DISTRIBUTE;
305 fd->for_stmt = for_stmt;
306 fd->pre = NULL;
307 fd->collapse = gimple_omp_for_collapse (for_stmt);
308 if (fd->collapse > 1)
309 fd->loops = loops;
310 else
311 fd->loops = &fd->loop;
313 fd->have_nowait = distribute || simd;
314 fd->have_ordered = false;
315 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
316 fd->chunk_size = NULL_TREE;
317 collapse_iter = NULL;
318 collapse_count = NULL;
320 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
321 switch (OMP_CLAUSE_CODE (t))
323 case OMP_CLAUSE_NOWAIT:
324 fd->have_nowait = true;
325 break;
326 case OMP_CLAUSE_ORDERED:
327 fd->have_ordered = true;
328 break;
329 case OMP_CLAUSE_SCHEDULE:
330 gcc_assert (!distribute);
331 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
332 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
333 break;
334 case OMP_CLAUSE_DIST_SCHEDULE:
335 gcc_assert (distribute);
336 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
337 break;
338 case OMP_CLAUSE_COLLAPSE:
339 if (fd->collapse > 1)
341 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
342 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
344 default:
345 break;
348 /* FIXME: for now map schedule(auto) to schedule(static).
349 There should be analysis to determine whether all iterations
350 are approximately the same amount of work (then schedule(static)
351 is best) or if it varies (then schedule(dynamic,N) is better). */
352 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
354 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
355 gcc_assert (fd->chunk_size == NULL);
357 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
358 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
359 gcc_assert (fd->chunk_size == NULL);
360 else if (fd->chunk_size == NULL)
362 /* We only need to compute a default chunk size for ordered
363 static loops and dynamic loops. */
364 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
365 || fd->have_ordered)
366 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
367 ? integer_zero_node : integer_one_node;
370 for (i = 0; i < fd->collapse; i++)
372 if (fd->collapse == 1)
373 loop = &fd->loop;
374 else if (loops != NULL)
375 loop = loops + i;
376 else
377 loop = &dummy_loop;
379 loop->v = gimple_omp_for_index (for_stmt, i);
380 gcc_assert (SSA_VAR_P (loop->v));
381 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
382 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
383 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
384 loop->n1 = gimple_omp_for_initial (for_stmt, i);
386 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
387 loop->n2 = gimple_omp_for_final (for_stmt, i);
388 switch (loop->cond_code)
390 case LT_EXPR:
391 case GT_EXPR:
392 break;
393 case NE_EXPR:
394 gcc_assert (gimple_omp_for_kind (for_stmt)
395 == GF_OMP_FOR_KIND_CILKSIMD);
396 break;
397 case LE_EXPR:
398 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
399 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
400 else
401 loop->n2 = fold_build2_loc (loc,
402 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
403 build_int_cst (TREE_TYPE (loop->n2), 1));
404 loop->cond_code = LT_EXPR;
405 break;
406 case GE_EXPR:
407 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
408 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
409 else
410 loop->n2 = fold_build2_loc (loc,
411 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
412 build_int_cst (TREE_TYPE (loop->n2), 1));
413 loop->cond_code = GT_EXPR;
414 break;
415 default:
416 gcc_unreachable ();
419 t = gimple_omp_for_incr (for_stmt, i);
420 gcc_assert (TREE_OPERAND (t, 0) == var);
421 switch (TREE_CODE (t))
423 case PLUS_EXPR:
424 loop->step = TREE_OPERAND (t, 1);
425 break;
426 case POINTER_PLUS_EXPR:
427 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
428 break;
429 case MINUS_EXPR:
430 loop->step = TREE_OPERAND (t, 1);
431 loop->step = fold_build1_loc (loc,
432 NEGATE_EXPR, TREE_TYPE (loop->step),
433 loop->step);
434 break;
435 default:
436 gcc_unreachable ();
439 if (simd
440 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
441 && !fd->have_ordered))
443 if (fd->collapse == 1)
444 iter_type = TREE_TYPE (loop->v);
445 else if (i == 0
446 || TYPE_PRECISION (iter_type)
447 < TYPE_PRECISION (TREE_TYPE (loop->v)))
448 iter_type
449 = build_nonstandard_integer_type
450 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
452 else if (iter_type != long_long_unsigned_type_node)
454 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
455 iter_type = long_long_unsigned_type_node;
456 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
457 && TYPE_PRECISION (TREE_TYPE (loop->v))
458 >= TYPE_PRECISION (iter_type))
460 tree n;
462 if (loop->cond_code == LT_EXPR)
463 n = fold_build2_loc (loc,
464 PLUS_EXPR, TREE_TYPE (loop->v),
465 loop->n2, loop->step);
466 else
467 n = loop->n1;
468 if (TREE_CODE (n) != INTEGER_CST
469 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
470 iter_type = long_long_unsigned_type_node;
472 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
473 > TYPE_PRECISION (iter_type))
475 tree n1, n2;
477 if (loop->cond_code == LT_EXPR)
479 n1 = loop->n1;
480 n2 = fold_build2_loc (loc,
481 PLUS_EXPR, TREE_TYPE (loop->v),
482 loop->n2, loop->step);
484 else
486 n1 = fold_build2_loc (loc,
487 MINUS_EXPR, TREE_TYPE (loop->v),
488 loop->n2, loop->step);
489 n2 = loop->n1;
491 if (TREE_CODE (n1) != INTEGER_CST
492 || TREE_CODE (n2) != INTEGER_CST
493 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
494 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
495 iter_type = long_long_unsigned_type_node;
499 if (collapse_count && *collapse_count == NULL)
501 t = fold_binary (loop->cond_code, boolean_type_node,
502 fold_convert (TREE_TYPE (loop->v), loop->n1),
503 fold_convert (TREE_TYPE (loop->v), loop->n2));
504 if (t && integer_zerop (t))
505 count = build_zero_cst (long_long_unsigned_type_node);
506 else if ((i == 0 || count != NULL_TREE)
507 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
508 && TREE_CONSTANT (loop->n1)
509 && TREE_CONSTANT (loop->n2)
510 && TREE_CODE (loop->step) == INTEGER_CST)
512 tree itype = TREE_TYPE (loop->v);
514 if (POINTER_TYPE_P (itype))
515 itype = signed_type_for (itype);
516 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
517 t = fold_build2_loc (loc,
518 PLUS_EXPR, itype,
519 fold_convert_loc (loc, itype, loop->step), t);
520 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
521 fold_convert_loc (loc, itype, loop->n2));
522 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
523 fold_convert_loc (loc, itype, loop->n1));
524 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
525 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
526 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
527 fold_build1_loc (loc, NEGATE_EXPR, itype,
528 fold_convert_loc (loc, itype,
529 loop->step)));
530 else
531 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
532 fold_convert_loc (loc, itype, loop->step));
533 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
534 if (count != NULL_TREE)
535 count = fold_build2_loc (loc,
536 MULT_EXPR, long_long_unsigned_type_node,
537 count, t);
538 else
539 count = t;
540 if (TREE_CODE (count) != INTEGER_CST)
541 count = NULL_TREE;
543 else if (count && !integer_zerop (count))
544 count = NULL_TREE;
548 if (count
549 && !simd
550 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
551 || fd->have_ordered))
553 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
554 iter_type = long_long_unsigned_type_node;
555 else
556 iter_type = long_integer_type_node;
558 else if (collapse_iter && *collapse_iter != NULL)
559 iter_type = TREE_TYPE (*collapse_iter);
560 fd->iter_type = iter_type;
561 if (collapse_iter && *collapse_iter == NULL)
562 *collapse_iter = create_tmp_var (iter_type, ".iter");
563 if (collapse_count && *collapse_count == NULL)
565 if (count)
566 *collapse_count = fold_convert_loc (loc, iter_type, count);
567 else
568 *collapse_count = create_tmp_var (iter_type, ".count");
571 if (fd->collapse > 1)
573 fd->loop.v = *collapse_iter;
574 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
575 fd->loop.n2 = *collapse_count;
576 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
577 fd->loop.cond_code = LT_EXPR;
582 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
583 is the immediate dominator of PAR_ENTRY_BB, return true if there
584 are no data dependencies that would prevent expanding the parallel
585 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
587 When expanding a combined parallel+workshare region, the call to
588 the child function may need additional arguments in the case of
589 GIMPLE_OMP_FOR regions. In some cases, these arguments are
590 computed out of variables passed in from the parent to the child
591 via 'struct .omp_data_s'. For instance:
593 #pragma omp parallel for schedule (guided, i * 4)
594 for (j ...)
596 Is lowered into:
598 # BLOCK 2 (PAR_ENTRY_BB)
599 .omp_data_o.i = i;
600 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
602 # BLOCK 3 (WS_ENTRY_BB)
603 .omp_data_i = &.omp_data_o;
604 D.1667 = .omp_data_i->i;
605 D.1598 = D.1667 * 4;
606 #pragma omp for schedule (guided, D.1598)
608 When we outline the parallel region, the call to the child function
609 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
610 that value is computed *after* the call site. So, in principle we
611 cannot do the transformation.
613 To see whether the code in WS_ENTRY_BB blocks the combined
614 parallel+workshare call, we collect all the variables used in the
615 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
616 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
617 call.
619 FIXME. If we had the SSA form built at this point, we could merely
620 hoist the code in block 3 into block 2 and be done with it. But at
621 this point we don't have dataflow information and though we could
622 hack something up here, it is really not worth the aggravation. */
624 static bool
625 workshare_safe_to_combine_p (basic_block ws_entry_bb)
627 struct omp_for_data fd;
628 gimple ws_stmt = last_stmt (ws_entry_bb);
630 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
631 return true;
633 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
635 extract_omp_for_data (ws_stmt, &fd, NULL);
637 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
638 return false;
639 if (fd.iter_type != long_integer_type_node)
640 return false;
642 /* FIXME. We give up too easily here. If any of these arguments
643 are not constants, they will likely involve variables that have
644 been mapped into fields of .omp_data_s for sharing with the child
645 function. With appropriate data flow, it would be possible to
646 see through this. */
647 if (!is_gimple_min_invariant (fd.loop.n1)
648 || !is_gimple_min_invariant (fd.loop.n2)
649 || !is_gimple_min_invariant (fd.loop.step)
650 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
651 return false;
653 return true;
657 /* Collect additional arguments needed to emit a combined
658 parallel+workshare call. WS_STMT is the workshare directive being
659 expanded. */
661 static vec<tree, va_gc> *
662 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
664 tree t;
665 location_t loc = gimple_location (ws_stmt);
666 vec<tree, va_gc> *ws_args;
668 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
670 struct omp_for_data fd;
671 tree n1, n2;
673 extract_omp_for_data (ws_stmt, &fd, NULL);
674 n1 = fd.loop.n1;
675 n2 = fd.loop.n2;
677 if (gimple_omp_for_combined_into_p (ws_stmt))
679 tree innerc
680 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
681 OMP_CLAUSE__LOOPTEMP_);
682 gcc_assert (innerc);
683 n1 = OMP_CLAUSE_DECL (innerc);
684 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
685 OMP_CLAUSE__LOOPTEMP_);
686 gcc_assert (innerc);
687 n2 = OMP_CLAUSE_DECL (innerc);
690 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
692 t = fold_convert_loc (loc, long_integer_type_node, n1);
693 ws_args->quick_push (t);
695 t = fold_convert_loc (loc, long_integer_type_node, n2);
696 ws_args->quick_push (t);
698 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
699 ws_args->quick_push (t);
701 if (fd.chunk_size)
703 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
704 ws_args->quick_push (t);
707 return ws_args;
709 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
711 /* Number of sections is equal to the number of edges from the
712 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
713 the exit of the sections region. */
714 basic_block bb = single_succ (gimple_bb (ws_stmt));
715 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
716 vec_alloc (ws_args, 1);
717 ws_args->quick_push (t);
718 return ws_args;
721 gcc_unreachable ();
725 /* Discover whether REGION is a combined parallel+workshare region. */
727 static void
728 determine_parallel_type (struct omp_region *region)
730 basic_block par_entry_bb, par_exit_bb;
731 basic_block ws_entry_bb, ws_exit_bb;
733 if (region == NULL || region->inner == NULL
734 || region->exit == NULL || region->inner->exit == NULL
735 || region->inner->cont == NULL)
736 return;
738 /* We only support parallel+for and parallel+sections. */
739 if (region->type != GIMPLE_OMP_PARALLEL
740 || (region->inner->type != GIMPLE_OMP_FOR
741 && region->inner->type != GIMPLE_OMP_SECTIONS))
742 return;
744 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
745 WS_EXIT_BB -> PAR_EXIT_BB. */
746 par_entry_bb = region->entry;
747 par_exit_bb = region->exit;
748 ws_entry_bb = region->inner->entry;
749 ws_exit_bb = region->inner->exit;
751 if (single_succ (par_entry_bb) == ws_entry_bb
752 && single_succ (ws_exit_bb) == par_exit_bb
753 && workshare_safe_to_combine_p (ws_entry_bb)
754 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
755 || (last_and_only_stmt (ws_entry_bb)
756 && last_and_only_stmt (par_exit_bb))))
758 gimple par_stmt = last_stmt (par_entry_bb);
759 gimple ws_stmt = last_stmt (ws_entry_bb);
761 if (region->inner->type == GIMPLE_OMP_FOR)
763 /* If this is a combined parallel loop, we need to determine
764 whether or not to use the combined library calls. There
765 are two cases where we do not apply the transformation:
766 static loops and any kind of ordered loop. In the first
767 case, we already open code the loop so there is no need
768 to do anything else. In the latter case, the combined
769 parallel loop call would still need extra synchronization
770 to implement ordered semantics, so there would not be any
771 gain in using the combined call. */
772 tree clauses = gimple_omp_for_clauses (ws_stmt);
773 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
774 if (c == NULL
775 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
776 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
778 region->is_combined_parallel = false;
779 region->inner->is_combined_parallel = false;
780 return;
784 region->is_combined_parallel = true;
785 region->inner->is_combined_parallel = true;
786 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
791 /* Return true if EXPR is variable sized. */
793 static inline bool
794 is_variable_sized (const_tree expr)
796 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
799 /* Return true if DECL is a reference type. */
801 static inline bool
802 is_reference (tree decl)
804 return lang_hooks.decls.omp_privatize_by_reference (decl);
807 /* Lookup variables in the decl or field splay trees. The "maybe" form
808 allows for the variable form to not have been entered, otherwise we
809 assert that the variable must have been entered. */
811 static inline tree
812 lookup_decl (tree var, omp_context *ctx)
814 tree *n;
815 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
816 return *n;
819 static inline tree
820 maybe_lookup_decl (const_tree var, omp_context *ctx)
822 tree *n;
823 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
824 return n ? *n : NULL_TREE;
827 static inline tree
828 lookup_field (tree var, omp_context *ctx)
830 splay_tree_node n;
831 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
832 return (tree) n->value;
835 static inline tree
836 lookup_sfield (tree var, omp_context *ctx)
838 splay_tree_node n;
839 n = splay_tree_lookup (ctx->sfield_map
840 ? ctx->sfield_map : ctx->field_map,
841 (splay_tree_key) var);
842 return (tree) n->value;
845 static inline tree
846 maybe_lookup_field (tree var, omp_context *ctx)
848 splay_tree_node n;
849 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
850 return n ? (tree) n->value : NULL_TREE;
853 /* Return true if DECL should be copied by pointer. SHARED_CTX is
854 the parallel context if DECL is to be shared. */
856 static bool
857 use_pointer_for_field (tree decl, omp_context *shared_ctx)
859 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
860 return true;
862 /* We can only use copy-in/copy-out semantics for shared variables
863 when we know the value is not accessible from an outer scope. */
864 if (shared_ctx)
866 /* ??? Trivially accessible from anywhere. But why would we even
867 be passing an address in this case? Should we simply assert
868 this to be false, or should we have a cleanup pass that removes
869 these from the list of mappings? */
870 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
871 return true;
873 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
874 without analyzing the expression whether or not its location
875 is accessible to anyone else. In the case of nested parallel
876 regions it certainly may be. */
877 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
878 return true;
880 /* Do not use copy-in/copy-out for variables that have their
881 address taken. */
882 if (TREE_ADDRESSABLE (decl))
883 return true;
885 /* lower_send_shared_vars only uses copy-in, but not copy-out
886 for these. */
887 if (TREE_READONLY (decl)
888 || ((TREE_CODE (decl) == RESULT_DECL
889 || TREE_CODE (decl) == PARM_DECL)
890 && DECL_BY_REFERENCE (decl)))
891 return false;
893 /* Disallow copy-in/out in nested parallel if
894 decl is shared in outer parallel, otherwise
895 each thread could store the shared variable
896 in its own copy-in location, making the
897 variable no longer really shared. */
898 if (shared_ctx->is_nested)
900 omp_context *up;
902 for (up = shared_ctx->outer; up; up = up->outer)
903 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
904 break;
906 if (up)
908 tree c;
910 for (c = gimple_omp_taskreg_clauses (up->stmt);
911 c; c = OMP_CLAUSE_CHAIN (c))
912 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
913 && OMP_CLAUSE_DECL (c) == decl)
914 break;
916 if (c)
917 goto maybe_mark_addressable_and_ret;
921 /* For tasks avoid using copy-in/out. As tasks can be
922 deferred or executed in different thread, when GOMP_task
923 returns, the task hasn't necessarily terminated. */
924 if (is_task_ctx (shared_ctx))
926 tree outer;
927 maybe_mark_addressable_and_ret:
928 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
929 if (is_gimple_reg (outer))
931 /* Taking address of OUTER in lower_send_shared_vars
932 might need regimplification of everything that uses the
933 variable. */
934 if (!task_shared_vars)
935 task_shared_vars = BITMAP_ALLOC (NULL);
936 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
937 TREE_ADDRESSABLE (outer) = 1;
939 return true;
943 return false;
946 /* Construct a new automatic decl similar to VAR. */
948 static tree
949 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
951 tree copy = copy_var_decl (var, name, type);
953 DECL_CONTEXT (copy) = current_function_decl;
954 DECL_CHAIN (copy) = ctx->block_vars;
955 ctx->block_vars = copy;
957 return copy;
960 static tree
961 omp_copy_decl_1 (tree var, omp_context *ctx)
963 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
966 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
967 as appropriate. */
968 static tree
969 omp_build_component_ref (tree obj, tree field)
971 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
972 if (TREE_THIS_VOLATILE (field))
973 TREE_THIS_VOLATILE (ret) |= 1;
974 if (TREE_READONLY (field))
975 TREE_READONLY (ret) |= 1;
976 return ret;
979 /* Build tree nodes to access the field for VAR on the receiver side. */
981 static tree
982 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
984 tree x, field = lookup_field (var, ctx);
986 /* If the receiver record type was remapped in the child function,
987 remap the field into the new record type. */
988 x = maybe_lookup_field (field, ctx);
989 if (x != NULL)
990 field = x;
992 x = build_simple_mem_ref (ctx->receiver_decl);
993 x = omp_build_component_ref (x, field);
994 if (by_ref)
995 x = build_simple_mem_ref (x);
997 return x;
1000 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1001 of a parallel, this is a component reference; for workshare constructs
1002 this is some variable. */
1004 static tree
1005 build_outer_var_ref (tree var, omp_context *ctx)
1007 tree x;
1009 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1010 x = var;
1011 else if (is_variable_sized (var))
1013 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1014 x = build_outer_var_ref (x, ctx);
1015 x = build_simple_mem_ref (x);
1017 else if (is_taskreg_ctx (ctx))
1019 bool by_ref = use_pointer_for_field (var, NULL);
1020 x = build_receiver_ref (var, by_ref, ctx);
1022 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1023 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
1025 /* #pragma omp simd isn't a worksharing construct, and can reference even
1026 private vars in its linear etc. clauses. */
1027 x = NULL_TREE;
1028 if (ctx->outer && is_taskreg_ctx (ctx))
1029 x = lookup_decl (var, ctx->outer);
1030 else if (ctx->outer)
1031 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1032 if (x == NULL_TREE)
1033 x = var;
1035 else if (ctx->outer)
1036 x = lookup_decl (var, ctx->outer);
1037 else if (is_reference (var))
1038 /* This can happen with orphaned constructs. If var is reference, it is
1039 possible it is shared and as such valid. */
1040 x = var;
1041 else
1042 gcc_unreachable ();
1044 if (is_reference (var))
1045 x = build_simple_mem_ref (x);
1047 return x;
1050 /* Build tree nodes to access the field for VAR on the sender side. */
1052 static tree
1053 build_sender_ref (tree var, omp_context *ctx)
1055 tree field = lookup_sfield (var, ctx);
1056 return omp_build_component_ref (ctx->sender_decl, field);
1059 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1061 static void
1062 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1064 tree field, type, sfield = NULL_TREE;
1066 gcc_assert ((mask & 1) == 0
1067 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1068 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1069 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1071 type = TREE_TYPE (var);
1072 if (mask & 4)
1074 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1075 type = build_pointer_type (build_pointer_type (type));
1077 else if (by_ref)
1078 type = build_pointer_type (type);
1079 else if ((mask & 3) == 1 && is_reference (var))
1080 type = TREE_TYPE (type);
1082 field = build_decl (DECL_SOURCE_LOCATION (var),
1083 FIELD_DECL, DECL_NAME (var), type);
1085 /* Remember what variable this field was created for. This does have a
1086 side effect of making dwarf2out ignore this member, so for helpful
1087 debugging we clear it later in delete_omp_context. */
1088 DECL_ABSTRACT_ORIGIN (field) = var;
1089 if (type == TREE_TYPE (var))
1091 DECL_ALIGN (field) = DECL_ALIGN (var);
1092 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1093 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1095 else
1096 DECL_ALIGN (field) = TYPE_ALIGN (type);
1098 if ((mask & 3) == 3)
1100 insert_field_into_struct (ctx->record_type, field);
1101 if (ctx->srecord_type)
1103 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1104 FIELD_DECL, DECL_NAME (var), type);
1105 DECL_ABSTRACT_ORIGIN (sfield) = var;
1106 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1107 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1108 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1109 insert_field_into_struct (ctx->srecord_type, sfield);
1112 else
1114 if (ctx->srecord_type == NULL_TREE)
1116 tree t;
1118 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1119 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1120 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1122 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1123 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1124 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1125 insert_field_into_struct (ctx->srecord_type, sfield);
1126 splay_tree_insert (ctx->sfield_map,
1127 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1128 (splay_tree_value) sfield);
1131 sfield = field;
1132 insert_field_into_struct ((mask & 1) ? ctx->record_type
1133 : ctx->srecord_type, field);
1136 if (mask & 1)
1137 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1138 (splay_tree_value) field);
1139 if ((mask & 2) && ctx->sfield_map)
1140 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1141 (splay_tree_value) sfield);
1144 static tree
1145 install_var_local (tree var, omp_context *ctx)
1147 tree new_var = omp_copy_decl_1 (var, ctx);
1148 insert_decl_map (&ctx->cb, var, new_var);
1149 return new_var;
1152 /* Adjust the replacement for DECL in CTX for the new context. This means
1153 copying the DECL_VALUE_EXPR, and fixing up the type. */
1155 static void
1156 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1158 tree new_decl, size;
1160 new_decl = lookup_decl (decl, ctx);
1162 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1164 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1165 && DECL_HAS_VALUE_EXPR_P (decl))
1167 tree ve = DECL_VALUE_EXPR (decl);
1168 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1169 SET_DECL_VALUE_EXPR (new_decl, ve);
1170 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1173 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1175 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1176 if (size == error_mark_node)
1177 size = TYPE_SIZE (TREE_TYPE (new_decl));
1178 DECL_SIZE (new_decl) = size;
1180 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1181 if (size == error_mark_node)
1182 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1183 DECL_SIZE_UNIT (new_decl) = size;
1187 /* The callback for remap_decl. Search all containing contexts for a
1188 mapping of the variable; this avoids having to duplicate the splay
1189 tree ahead of time. We know a mapping doesn't already exist in the
1190 given context. Create new mappings to implement default semantics. */
1192 static tree
1193 omp_copy_decl (tree var, copy_body_data *cb)
1195 omp_context *ctx = (omp_context *) cb;
1196 tree new_var;
1198 if (TREE_CODE (var) == LABEL_DECL)
1200 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1201 DECL_CONTEXT (new_var) = current_function_decl;
1202 insert_decl_map (&ctx->cb, var, new_var);
1203 return new_var;
1206 while (!is_taskreg_ctx (ctx))
1208 ctx = ctx->outer;
1209 if (ctx == NULL)
1210 return var;
1211 new_var = maybe_lookup_decl (var, ctx);
1212 if (new_var)
1213 return new_var;
1216 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1217 return var;
1219 return error_mark_node;
1223 /* Debugging dumps for parallel regions. */
1224 void dump_omp_region (FILE *, struct omp_region *, int);
1225 void debug_omp_region (struct omp_region *);
1226 void debug_all_omp_regions (void);
1228 /* Dump the parallel region tree rooted at REGION. */
1230 void
1231 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1233 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1234 gimple_code_name[region->type]);
1236 if (region->inner)
1237 dump_omp_region (file, region->inner, indent + 4);
1239 if (region->cont)
1241 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1242 region->cont->index);
1245 if (region->exit)
1246 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1247 region->exit->index);
1248 else
1249 fprintf (file, "%*s[no exit marker]\n", indent, "");
1251 if (region->next)
1252 dump_omp_region (file, region->next, indent);
1255 DEBUG_FUNCTION void
1256 debug_omp_region (struct omp_region *region)
1258 dump_omp_region (stderr, region, 0);
1261 DEBUG_FUNCTION void
1262 debug_all_omp_regions (void)
1264 dump_omp_region (stderr, root_omp_region, 0);
1268 /* Create a new parallel region starting at STMT inside region PARENT. */
1270 static struct omp_region *
1271 new_omp_region (basic_block bb, enum gimple_code type,
1272 struct omp_region *parent)
1274 struct omp_region *region = XCNEW (struct omp_region);
1276 region->outer = parent;
1277 region->entry = bb;
1278 region->type = type;
1280 if (parent)
1282 /* This is a nested region. Add it to the list of inner
1283 regions in PARENT. */
1284 region->next = parent->inner;
1285 parent->inner = region;
1287 else
1289 /* This is a toplevel region. Add it to the list of toplevel
1290 regions in ROOT_OMP_REGION. */
1291 region->next = root_omp_region;
1292 root_omp_region = region;
1295 return region;
1298 /* Release the memory associated with the region tree rooted at REGION. */
1300 static void
1301 free_omp_region_1 (struct omp_region *region)
1303 struct omp_region *i, *n;
1305 for (i = region->inner; i ; i = n)
1307 n = i->next;
1308 free_omp_region_1 (i);
1311 free (region);
1314 /* Release the memory for the entire omp region tree. */
1316 void
1317 free_omp_regions (void)
1319 struct omp_region *r, *n;
1320 for (r = root_omp_region; r ; r = n)
1322 n = r->next;
1323 free_omp_region_1 (r);
1325 root_omp_region = NULL;
1329 /* Create a new context, with OUTER_CTX being the surrounding context. */
1331 static omp_context *
1332 new_omp_context (gimple stmt, omp_context *outer_ctx)
1334 omp_context *ctx = XCNEW (omp_context);
1336 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1337 (splay_tree_value) ctx);
1338 ctx->stmt = stmt;
1340 if (outer_ctx)
1342 ctx->outer = outer_ctx;
1343 ctx->cb = outer_ctx->cb;
1344 ctx->cb.block = NULL;
1345 ctx->depth = outer_ctx->depth + 1;
1347 else
1349 ctx->cb.src_fn = current_function_decl;
1350 ctx->cb.dst_fn = current_function_decl;
1351 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1352 gcc_checking_assert (ctx->cb.src_node);
1353 ctx->cb.dst_node = ctx->cb.src_node;
1354 ctx->cb.src_cfun = cfun;
1355 ctx->cb.copy_decl = omp_copy_decl;
1356 ctx->cb.eh_lp_nr = 0;
1357 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1358 ctx->depth = 1;
1361 ctx->cb.decl_map = pointer_map_create ();
1363 return ctx;
1366 static gimple_seq maybe_catch_exception (gimple_seq);
1368 /* Finalize task copyfn. */
1370 static void
1371 finalize_task_copyfn (gimple task_stmt)
1373 struct function *child_cfun;
1374 tree child_fn;
1375 gimple_seq seq = NULL, new_seq;
1376 gimple bind;
1378 child_fn = gimple_omp_task_copy_fn (task_stmt);
1379 if (child_fn == NULL_TREE)
1380 return;
1382 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1383 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1385 push_cfun (child_cfun);
1386 bind = gimplify_body (child_fn, false);
1387 gimple_seq_add_stmt (&seq, bind);
1388 new_seq = maybe_catch_exception (seq);
1389 if (new_seq != seq)
1391 bind = gimple_build_bind (NULL, new_seq, NULL);
1392 seq = NULL;
1393 gimple_seq_add_stmt (&seq, bind);
1395 gimple_set_body (child_fn, seq);
1396 pop_cfun ();
1398 /* Inform the callgraph about the new function. */
1399 cgraph_add_new_function (child_fn, false);
1402 /* Destroy a omp_context data structures. Called through the splay tree
1403 value delete callback. */
1405 static void
1406 delete_omp_context (splay_tree_value value)
1408 omp_context *ctx = (omp_context *) value;
1410 pointer_map_destroy (ctx->cb.decl_map);
1412 if (ctx->field_map)
1413 splay_tree_delete (ctx->field_map);
1414 if (ctx->sfield_map)
1415 splay_tree_delete (ctx->sfield_map);
1417 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1418 it produces corrupt debug information. */
1419 if (ctx->record_type)
1421 tree t;
1422 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1423 DECL_ABSTRACT_ORIGIN (t) = NULL;
1425 if (ctx->srecord_type)
1427 tree t;
1428 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1429 DECL_ABSTRACT_ORIGIN (t) = NULL;
1432 if (is_task_ctx (ctx))
1433 finalize_task_copyfn (ctx->stmt);
1435 XDELETE (ctx);
1438 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1439 context. */
1441 static void
1442 fixup_child_record_type (omp_context *ctx)
1444 tree f, type = ctx->record_type;
1446 /* ??? It isn't sufficient to just call remap_type here, because
1447 variably_modified_type_p doesn't work the way we expect for
1448 record types. Testing each field for whether it needs remapping
1449 and creating a new record by hand works, however. */
1450 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1451 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1452 break;
1453 if (f)
1455 tree name, new_fields = NULL;
1457 type = lang_hooks.types.make_type (RECORD_TYPE);
1458 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1459 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1460 TYPE_DECL, name, type);
1461 TYPE_NAME (type) = name;
1463 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1465 tree new_f = copy_node (f);
1466 DECL_CONTEXT (new_f) = type;
1467 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1468 DECL_CHAIN (new_f) = new_fields;
1469 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1470 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1471 &ctx->cb, NULL);
1472 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1473 &ctx->cb, NULL);
1474 new_fields = new_f;
1476 /* Arrange to be able to look up the receiver field
1477 given the sender field. */
1478 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1479 (splay_tree_value) new_f);
1481 TYPE_FIELDS (type) = nreverse (new_fields);
1482 layout_type (type);
1485 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1488 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1489 specified by CLAUSES. */
1491 static void
1492 scan_sharing_clauses (tree clauses, omp_context *ctx)
1494 tree c, decl;
1495 bool scan_array_reductions = false;
1497 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1499 bool by_ref;
1501 switch (OMP_CLAUSE_CODE (c))
1503 case OMP_CLAUSE_PRIVATE:
1504 decl = OMP_CLAUSE_DECL (c);
1505 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1506 goto do_private;
1507 else if (!is_variable_sized (decl))
1508 install_var_local (decl, ctx);
1509 break;
1511 case OMP_CLAUSE_SHARED:
1512 /* Ignore shared directives in teams construct. */
1513 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1514 break;
1515 gcc_assert (is_taskreg_ctx (ctx));
1516 decl = OMP_CLAUSE_DECL (c);
1517 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1518 || !is_variable_sized (decl));
1519 /* Global variables don't need to be copied,
1520 the receiver side will use them directly. */
1521 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1522 break;
1523 by_ref = use_pointer_for_field (decl, ctx);
1524 if (! TREE_READONLY (decl)
1525 || TREE_ADDRESSABLE (decl)
1526 || by_ref
1527 || is_reference (decl))
1529 install_var_field (decl, by_ref, 3, ctx);
1530 install_var_local (decl, ctx);
1531 break;
1533 /* We don't need to copy const scalar vars back. */
1534 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1535 goto do_private;
1537 case OMP_CLAUSE_LASTPRIVATE:
1538 /* Let the corresponding firstprivate clause create
1539 the variable. */
1540 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1541 break;
1542 /* FALLTHRU */
1544 case OMP_CLAUSE_FIRSTPRIVATE:
1545 case OMP_CLAUSE_REDUCTION:
1546 case OMP_CLAUSE_LINEAR:
1547 decl = OMP_CLAUSE_DECL (c);
1548 do_private:
1549 if (is_variable_sized (decl))
1551 if (is_task_ctx (ctx))
1552 install_var_field (decl, false, 1, ctx);
1553 break;
1555 else if (is_taskreg_ctx (ctx))
1557 bool global
1558 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1559 by_ref = use_pointer_for_field (decl, NULL);
1561 if (is_task_ctx (ctx)
1562 && (global || by_ref || is_reference (decl)))
1564 install_var_field (decl, false, 1, ctx);
1565 if (!global)
1566 install_var_field (decl, by_ref, 2, ctx);
1568 else if (!global)
1569 install_var_field (decl, by_ref, 3, ctx);
1571 install_var_local (decl, ctx);
1572 break;
1574 case OMP_CLAUSE__LOOPTEMP_:
1575 gcc_assert (is_parallel_ctx (ctx));
1576 decl = OMP_CLAUSE_DECL (c);
1577 install_var_field (decl, false, 3, ctx);
1578 install_var_local (decl, ctx);
1579 break;
1581 case OMP_CLAUSE_COPYPRIVATE:
1582 case OMP_CLAUSE_COPYIN:
1583 decl = OMP_CLAUSE_DECL (c);
1584 by_ref = use_pointer_for_field (decl, NULL);
1585 install_var_field (decl, by_ref, 3, ctx);
1586 break;
1588 case OMP_CLAUSE_DEFAULT:
1589 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1590 break;
1592 case OMP_CLAUSE_FINAL:
1593 case OMP_CLAUSE_IF:
1594 case OMP_CLAUSE_NUM_THREADS:
1595 case OMP_CLAUSE_NUM_TEAMS:
1596 case OMP_CLAUSE_THREAD_LIMIT:
1597 case OMP_CLAUSE_DEVICE:
1598 case OMP_CLAUSE_SCHEDULE:
1599 case OMP_CLAUSE_DIST_SCHEDULE:
1600 case OMP_CLAUSE_DEPEND:
1601 if (ctx->outer)
1602 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1603 break;
1605 case OMP_CLAUSE_TO:
1606 case OMP_CLAUSE_FROM:
1607 case OMP_CLAUSE_MAP:
1608 if (ctx->outer)
1609 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1610 decl = OMP_CLAUSE_DECL (c);
1611 /* Global variables with "omp declare target" attribute
1612 don't need to be copied, the receiver side will use them
1613 directly. */
1614 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1615 && DECL_P (decl)
1616 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1617 && lookup_attribute ("omp declare target",
1618 DECL_ATTRIBUTES (decl)))
1619 break;
1620 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1621 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1623 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1624 #pragma omp target data, there is nothing to map for
1625 those. */
1626 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1627 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1628 break;
1630 if (DECL_P (decl))
1632 if (DECL_SIZE (decl)
1633 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1635 tree decl2 = DECL_VALUE_EXPR (decl);
1636 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1637 decl2 = TREE_OPERAND (decl2, 0);
1638 gcc_assert (DECL_P (decl2));
1639 install_var_field (decl2, true, 3, ctx);
1640 install_var_local (decl2, ctx);
1641 install_var_local (decl, ctx);
1643 else
1645 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1646 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1647 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1648 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1649 install_var_field (decl, true, 7, ctx);
1650 else
1651 install_var_field (decl, true, 3, ctx);
1652 if (gimple_omp_target_kind (ctx->stmt)
1653 == GF_OMP_TARGET_KIND_REGION)
1654 install_var_local (decl, ctx);
1657 else
1659 tree base = get_base_address (decl);
1660 tree nc = OMP_CLAUSE_CHAIN (c);
1661 if (DECL_P (base)
1662 && nc != NULL_TREE
1663 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1664 && OMP_CLAUSE_DECL (nc) == base
1665 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1666 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1668 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1669 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1671 else
1673 gcc_assert (!splay_tree_lookup (ctx->field_map,
1674 (splay_tree_key) decl));
1675 tree field
1676 = build_decl (OMP_CLAUSE_LOCATION (c),
1677 FIELD_DECL, NULL_TREE, ptr_type_node);
1678 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1679 insert_field_into_struct (ctx->record_type, field);
1680 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1681 (splay_tree_value) field);
1684 break;
1686 case OMP_CLAUSE_NOWAIT:
1687 case OMP_CLAUSE_ORDERED:
1688 case OMP_CLAUSE_COLLAPSE:
1689 case OMP_CLAUSE_UNTIED:
1690 case OMP_CLAUSE_MERGEABLE:
1691 case OMP_CLAUSE_PROC_BIND:
1692 case OMP_CLAUSE_SAFELEN:
1693 break;
1695 case OMP_CLAUSE_ALIGNED:
1696 decl = OMP_CLAUSE_DECL (c);
1697 if (is_global_var (decl)
1698 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1699 install_var_local (decl, ctx);
1700 break;
1702 default:
1703 gcc_unreachable ();
1707 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1709 switch (OMP_CLAUSE_CODE (c))
1711 case OMP_CLAUSE_LASTPRIVATE:
1712 /* Let the corresponding firstprivate clause create
1713 the variable. */
1714 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1715 scan_array_reductions = true;
1716 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1717 break;
1718 /* FALLTHRU */
1720 case OMP_CLAUSE_PRIVATE:
1721 case OMP_CLAUSE_FIRSTPRIVATE:
1722 case OMP_CLAUSE_REDUCTION:
1723 case OMP_CLAUSE_LINEAR:
1724 decl = OMP_CLAUSE_DECL (c);
1725 if (is_variable_sized (decl))
1726 install_var_local (decl, ctx);
1727 fixup_remapped_decl (decl, ctx,
1728 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1729 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1730 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1731 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1732 scan_array_reductions = true;
1733 break;
1735 case OMP_CLAUSE_SHARED:
1736 /* Ignore shared directives in teams construct. */
1737 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1738 break;
1739 decl = OMP_CLAUSE_DECL (c);
1740 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1741 fixup_remapped_decl (decl, ctx, false);
1742 break;
1744 case OMP_CLAUSE_MAP:
1745 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1746 break;
1747 decl = OMP_CLAUSE_DECL (c);
1748 if (DECL_P (decl)
1749 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1750 && lookup_attribute ("omp declare target",
1751 DECL_ATTRIBUTES (decl)))
1752 break;
1753 if (DECL_P (decl))
1755 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1756 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1757 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1759 tree new_decl = lookup_decl (decl, ctx);
1760 TREE_TYPE (new_decl)
1761 = remap_type (TREE_TYPE (decl), &ctx->cb);
1763 else if (DECL_SIZE (decl)
1764 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1766 tree decl2 = DECL_VALUE_EXPR (decl);
1767 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1768 decl2 = TREE_OPERAND (decl2, 0);
1769 gcc_assert (DECL_P (decl2));
1770 fixup_remapped_decl (decl2, ctx, false);
1771 fixup_remapped_decl (decl, ctx, true);
1773 else
1774 fixup_remapped_decl (decl, ctx, false);
1776 break;
1778 case OMP_CLAUSE_COPYPRIVATE:
1779 case OMP_CLAUSE_COPYIN:
1780 case OMP_CLAUSE_DEFAULT:
1781 case OMP_CLAUSE_IF:
1782 case OMP_CLAUSE_NUM_THREADS:
1783 case OMP_CLAUSE_NUM_TEAMS:
1784 case OMP_CLAUSE_THREAD_LIMIT:
1785 case OMP_CLAUSE_DEVICE:
1786 case OMP_CLAUSE_SCHEDULE:
1787 case OMP_CLAUSE_DIST_SCHEDULE:
1788 case OMP_CLAUSE_NOWAIT:
1789 case OMP_CLAUSE_ORDERED:
1790 case OMP_CLAUSE_COLLAPSE:
1791 case OMP_CLAUSE_UNTIED:
1792 case OMP_CLAUSE_FINAL:
1793 case OMP_CLAUSE_MERGEABLE:
1794 case OMP_CLAUSE_PROC_BIND:
1795 case OMP_CLAUSE_SAFELEN:
1796 case OMP_CLAUSE_ALIGNED:
1797 case OMP_CLAUSE_DEPEND:
1798 case OMP_CLAUSE__LOOPTEMP_:
1799 case OMP_CLAUSE_TO:
1800 case OMP_CLAUSE_FROM:
1801 break;
1803 default:
1804 gcc_unreachable ();
1808 if (scan_array_reductions)
1809 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1810 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1811 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1813 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1814 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1816 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1817 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1818 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1821 /* Create a new name for omp child function. Returns an identifier. */
1823 static tree
1824 create_omp_child_function_name (bool task_copy)
1826 return (clone_function_name (current_function_decl,
1827 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1830 /* Build a decl for the omp child function. It'll not contain a body
1831 yet, just the bare decl. */
1833 static void
1834 create_omp_child_function (omp_context *ctx, bool task_copy)
1836 tree decl, type, name, t;
1838 name = create_omp_child_function_name (task_copy);
1839 if (task_copy)
1840 type = build_function_type_list (void_type_node, ptr_type_node,
1841 ptr_type_node, NULL_TREE);
1842 else
1843 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1845 decl = build_decl (gimple_location (ctx->stmt),
1846 FUNCTION_DECL, name, type);
1848 if (!task_copy)
1849 ctx->cb.dst_fn = decl;
1850 else
1851 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1853 TREE_STATIC (decl) = 1;
1854 TREE_USED (decl) = 1;
1855 DECL_ARTIFICIAL (decl) = 1;
1856 DECL_NAMELESS (decl) = 1;
1857 DECL_IGNORED_P (decl) = 0;
1858 TREE_PUBLIC (decl) = 0;
1859 DECL_UNINLINABLE (decl) = 1;
1860 DECL_EXTERNAL (decl) = 0;
1861 DECL_CONTEXT (decl) = NULL_TREE;
1862 DECL_INITIAL (decl) = make_node (BLOCK);
1863 bool target_p = false;
1864 if (lookup_attribute ("omp declare target",
1865 DECL_ATTRIBUTES (current_function_decl)))
1866 target_p = true;
1867 else
1869 omp_context *octx;
1870 for (octx = ctx; octx; octx = octx->outer)
1871 if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
1872 && gimple_omp_target_kind (octx->stmt)
1873 == GF_OMP_TARGET_KIND_REGION)
1875 target_p = true;
1876 break;
1879 if (target_p)
1880 DECL_ATTRIBUTES (decl)
1881 = tree_cons (get_identifier ("omp declare target"),
1882 NULL_TREE, DECL_ATTRIBUTES (decl));
1884 t = build_decl (DECL_SOURCE_LOCATION (decl),
1885 RESULT_DECL, NULL_TREE, void_type_node);
1886 DECL_ARTIFICIAL (t) = 1;
1887 DECL_IGNORED_P (t) = 1;
1888 DECL_CONTEXT (t) = decl;
1889 DECL_RESULT (decl) = t;
1891 t = build_decl (DECL_SOURCE_LOCATION (decl),
1892 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1893 DECL_ARTIFICIAL (t) = 1;
1894 DECL_NAMELESS (t) = 1;
1895 DECL_ARG_TYPE (t) = ptr_type_node;
1896 DECL_CONTEXT (t) = current_function_decl;
1897 TREE_USED (t) = 1;
1898 DECL_ARGUMENTS (decl) = t;
1899 if (!task_copy)
1900 ctx->receiver_decl = t;
1901 else
1903 t = build_decl (DECL_SOURCE_LOCATION (decl),
1904 PARM_DECL, get_identifier (".omp_data_o"),
1905 ptr_type_node);
1906 DECL_ARTIFICIAL (t) = 1;
1907 DECL_NAMELESS (t) = 1;
1908 DECL_ARG_TYPE (t) = ptr_type_node;
1909 DECL_CONTEXT (t) = current_function_decl;
1910 TREE_USED (t) = 1;
1911 TREE_ADDRESSABLE (t) = 1;
1912 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1913 DECL_ARGUMENTS (decl) = t;
1916 /* Allocate memory for the function structure. The call to
1917 allocate_struct_function clobbers CFUN, so we need to restore
1918 it afterward. */
1919 push_struct_function (decl);
1920 cfun->function_end_locus = gimple_location (ctx->stmt);
1921 pop_cfun ();
1924 /* Callback for walk_gimple_seq. Check if combined parallel
1925 contains gimple_omp_for_combined_into_p OMP_FOR. */
1927 static tree
1928 find_combined_for (gimple_stmt_iterator *gsi_p,
1929 bool *handled_ops_p,
1930 struct walk_stmt_info *wi)
1932 gimple stmt = gsi_stmt (*gsi_p);
1934 *handled_ops_p = true;
1935 switch (gimple_code (stmt))
1937 WALK_SUBSTMTS;
1939 case GIMPLE_OMP_FOR:
1940 if (gimple_omp_for_combined_into_p (stmt)
1941 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
1943 wi->info = stmt;
1944 return integer_zero_node;
1946 break;
1947 default:
1948 break;
1950 return NULL;
1953 /* Scan an OpenMP parallel directive. */
1955 static void
1956 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1958 omp_context *ctx;
1959 tree name;
1960 gimple stmt = gsi_stmt (*gsi);
1962 /* Ignore parallel directives with empty bodies, unless there
1963 are copyin clauses. */
1964 if (optimize > 0
1965 && empty_body_p (gimple_omp_body (stmt))
1966 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1967 OMP_CLAUSE_COPYIN) == NULL)
1969 gsi_replace (gsi, gimple_build_nop (), false);
1970 return;
1973 if (gimple_omp_parallel_combined_p (stmt))
1975 gimple for_stmt;
1976 struct walk_stmt_info wi;
1978 memset (&wi, 0, sizeof (wi));
1979 wi.val_only = true;
1980 walk_gimple_seq (gimple_omp_body (stmt),
1981 find_combined_for, NULL, &wi);
1982 for_stmt = (gimple) wi.info;
1983 if (for_stmt)
1985 struct omp_for_data fd;
1986 extract_omp_for_data (for_stmt, &fd, NULL);
1987 /* We need two temporaries with fd.loop.v type (istart/iend)
1988 and then (fd.collapse - 1) temporaries with the same
1989 type for count2 ... countN-1 vars if not constant. */
1990 size_t count = 2, i;
1991 tree type = fd.iter_type;
1992 if (fd.collapse > 1
1993 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
1994 count += fd.collapse - 1;
1995 for (i = 0; i < count; i++)
1997 tree temp = create_tmp_var (type, NULL);
1998 tree c = build_omp_clause (UNKNOWN_LOCATION,
1999 OMP_CLAUSE__LOOPTEMP_);
2000 OMP_CLAUSE_DECL (c) = temp;
2001 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2002 gimple_omp_parallel_set_clauses (stmt, c);
2007 ctx = new_omp_context (stmt, outer_ctx);
2008 if (taskreg_nesting_level > 1)
2009 ctx->is_nested = true;
2010 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2011 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2012 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2013 name = create_tmp_var_name (".omp_data_s");
2014 name = build_decl (gimple_location (stmt),
2015 TYPE_DECL, name, ctx->record_type);
2016 DECL_ARTIFICIAL (name) = 1;
2017 DECL_NAMELESS (name) = 1;
2018 TYPE_NAME (ctx->record_type) = name;
2019 create_omp_child_function (ctx, false);
2020 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2022 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2023 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2025 if (TYPE_FIELDS (ctx->record_type) == NULL)
2026 ctx->record_type = ctx->receiver_decl = NULL;
2027 else
2029 layout_type (ctx->record_type);
2030 fixup_child_record_type (ctx);
2034 /* Scan an OpenMP task directive. */
2036 static void
2037 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2039 omp_context *ctx;
2040 tree name, t;
2041 gimple stmt = gsi_stmt (*gsi);
2042 location_t loc = gimple_location (stmt);
2044 /* Ignore task directives with empty bodies. */
2045 if (optimize > 0
2046 && empty_body_p (gimple_omp_body (stmt)))
2048 gsi_replace (gsi, gimple_build_nop (), false);
2049 return;
2052 ctx = new_omp_context (stmt, outer_ctx);
2053 if (taskreg_nesting_level > 1)
2054 ctx->is_nested = true;
2055 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2056 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2057 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2058 name = create_tmp_var_name (".omp_data_s");
2059 name = build_decl (gimple_location (stmt),
2060 TYPE_DECL, name, ctx->record_type);
2061 DECL_ARTIFICIAL (name) = 1;
2062 DECL_NAMELESS (name) = 1;
2063 TYPE_NAME (ctx->record_type) = name;
2064 create_omp_child_function (ctx, false);
2065 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2067 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2069 if (ctx->srecord_type)
2071 name = create_tmp_var_name (".omp_data_a");
2072 name = build_decl (gimple_location (stmt),
2073 TYPE_DECL, name, ctx->srecord_type);
2074 DECL_ARTIFICIAL (name) = 1;
2075 DECL_NAMELESS (name) = 1;
2076 TYPE_NAME (ctx->srecord_type) = name;
2077 create_omp_child_function (ctx, true);
2080 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2082 if (TYPE_FIELDS (ctx->record_type) == NULL)
2084 ctx->record_type = ctx->receiver_decl = NULL;
2085 t = build_int_cst (long_integer_type_node, 0);
2086 gimple_omp_task_set_arg_size (stmt, t);
2087 t = build_int_cst (long_integer_type_node, 1);
2088 gimple_omp_task_set_arg_align (stmt, t);
2090 else
2092 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2093 /* Move VLA fields to the end. */
2094 p = &TYPE_FIELDS (ctx->record_type);
2095 while (*p)
2096 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2097 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2099 *q = *p;
2100 *p = TREE_CHAIN (*p);
2101 TREE_CHAIN (*q) = NULL_TREE;
2102 q = &TREE_CHAIN (*q);
2104 else
2105 p = &DECL_CHAIN (*p);
2106 *p = vla_fields;
2107 layout_type (ctx->record_type);
2108 fixup_child_record_type (ctx);
2109 if (ctx->srecord_type)
2110 layout_type (ctx->srecord_type);
2111 t = fold_convert_loc (loc, long_integer_type_node,
2112 TYPE_SIZE_UNIT (ctx->record_type));
2113 gimple_omp_task_set_arg_size (stmt, t);
2114 t = build_int_cst (long_integer_type_node,
2115 TYPE_ALIGN_UNIT (ctx->record_type));
2116 gimple_omp_task_set_arg_align (stmt, t);
2121 /* Scan an OpenMP loop directive. */
2123 static void
2124 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2126 omp_context *ctx;
2127 size_t i;
2129 ctx = new_omp_context (stmt, outer_ctx);
2131 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2133 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2134 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2136 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2137 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2138 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2139 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2141 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2144 /* Scan an OpenMP sections directive. */
2146 static void
2147 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2149 omp_context *ctx;
2151 ctx = new_omp_context (stmt, outer_ctx);
2152 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2153 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2156 /* Scan an OpenMP single directive. */
2158 static void
2159 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2161 omp_context *ctx;
2162 tree name;
2164 ctx = new_omp_context (stmt, outer_ctx);
2165 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2166 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2167 name = create_tmp_var_name (".omp_copy_s");
2168 name = build_decl (gimple_location (stmt),
2169 TYPE_DECL, name, ctx->record_type);
2170 TYPE_NAME (ctx->record_type) = name;
2172 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2173 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2175 if (TYPE_FIELDS (ctx->record_type) == NULL)
2176 ctx->record_type = NULL;
2177 else
2178 layout_type (ctx->record_type);
2181 /* Scan an OpenMP target{, data, update} directive. */
2183 static void
2184 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2186 omp_context *ctx;
2187 tree name;
2188 int kind = gimple_omp_target_kind (stmt);
2190 ctx = new_omp_context (stmt, outer_ctx);
2191 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2192 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2193 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2194 name = create_tmp_var_name (".omp_data_t");
2195 name = build_decl (gimple_location (stmt),
2196 TYPE_DECL, name, ctx->record_type);
2197 DECL_ARTIFICIAL (name) = 1;
2198 DECL_NAMELESS (name) = 1;
2199 TYPE_NAME (ctx->record_type) = name;
2200 if (kind == GF_OMP_TARGET_KIND_REGION)
2202 create_omp_child_function (ctx, false);
2203 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2206 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2207 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2209 if (TYPE_FIELDS (ctx->record_type) == NULL)
2210 ctx->record_type = ctx->receiver_decl = NULL;
2211 else
2213 TYPE_FIELDS (ctx->record_type)
2214 = nreverse (TYPE_FIELDS (ctx->record_type));
2215 #ifdef ENABLE_CHECKING
2216 tree field;
2217 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2218 for (field = TYPE_FIELDS (ctx->record_type);
2219 field;
2220 field = DECL_CHAIN (field))
2221 gcc_assert (DECL_ALIGN (field) == align);
2222 #endif
2223 layout_type (ctx->record_type);
2224 if (kind == GF_OMP_TARGET_KIND_REGION)
2225 fixup_child_record_type (ctx);
2229 /* Scan an OpenMP teams directive. */
2231 static void
2232 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2234 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2235 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2236 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2239 /* Check OpenMP nesting restrictions. */
2240 static bool
2241 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2243 if (ctx != NULL)
2245 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2246 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2248 error_at (gimple_location (stmt),
2249 "OpenMP constructs may not be nested inside simd region");
2250 return false;
2252 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2254 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2255 || (gimple_omp_for_kind (stmt)
2256 != GF_OMP_FOR_KIND_DISTRIBUTE))
2257 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2259 error_at (gimple_location (stmt),
2260 "only distribute or parallel constructs are allowed to "
2261 "be closely nested inside teams construct");
2262 return false;
2266 switch (gimple_code (stmt))
2268 case GIMPLE_OMP_FOR:
2269 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_KIND_SIMD)
2270 return true;
2271 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2273 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2275 error_at (gimple_location (stmt),
2276 "distribute construct must be closely nested inside "
2277 "teams construct");
2278 return false;
2280 return true;
2282 /* FALLTHRU */
2283 case GIMPLE_CALL:
2284 if (is_gimple_call (stmt)
2285 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2286 == BUILT_IN_GOMP_CANCEL
2287 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2288 == BUILT_IN_GOMP_CANCELLATION_POINT))
2290 const char *bad = NULL;
2291 const char *kind = NULL;
2292 if (ctx == NULL)
2294 error_at (gimple_location (stmt), "orphaned %qs construct",
2295 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2296 == BUILT_IN_GOMP_CANCEL
2297 ? "#pragma omp cancel"
2298 : "#pragma omp cancellation point");
2299 return false;
2301 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2302 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2303 : 0)
2305 case 1:
2306 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2307 bad = "#pragma omp parallel";
2308 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2309 == BUILT_IN_GOMP_CANCEL
2310 && !integer_zerop (gimple_call_arg (stmt, 1)))
2311 ctx->cancellable = true;
2312 kind = "parallel";
2313 break;
2314 case 2:
2315 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2316 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2317 bad = "#pragma omp for";
2318 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2319 == BUILT_IN_GOMP_CANCEL
2320 && !integer_zerop (gimple_call_arg (stmt, 1)))
2322 ctx->cancellable = true;
2323 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2324 OMP_CLAUSE_NOWAIT))
2325 warning_at (gimple_location (stmt), 0,
2326 "%<#pragma omp cancel for%> inside "
2327 "%<nowait%> for construct");
2328 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2329 OMP_CLAUSE_ORDERED))
2330 warning_at (gimple_location (stmt), 0,
2331 "%<#pragma omp cancel for%> inside "
2332 "%<ordered%> for construct");
2334 kind = "for";
2335 break;
2336 case 4:
2337 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2338 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2339 bad = "#pragma omp sections";
2340 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2341 == BUILT_IN_GOMP_CANCEL
2342 && !integer_zerop (gimple_call_arg (stmt, 1)))
2344 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2346 ctx->cancellable = true;
2347 if (find_omp_clause (gimple_omp_sections_clauses
2348 (ctx->stmt),
2349 OMP_CLAUSE_NOWAIT))
2350 warning_at (gimple_location (stmt), 0,
2351 "%<#pragma omp cancel sections%> inside "
2352 "%<nowait%> sections construct");
2354 else
2356 gcc_assert (ctx->outer
2357 && gimple_code (ctx->outer->stmt)
2358 == GIMPLE_OMP_SECTIONS);
2359 ctx->outer->cancellable = true;
2360 if (find_omp_clause (gimple_omp_sections_clauses
2361 (ctx->outer->stmt),
2362 OMP_CLAUSE_NOWAIT))
2363 warning_at (gimple_location (stmt), 0,
2364 "%<#pragma omp cancel sections%> inside "
2365 "%<nowait%> sections construct");
2368 kind = "sections";
2369 break;
2370 case 8:
2371 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2372 bad = "#pragma omp task";
2373 else
2374 ctx->cancellable = true;
2375 kind = "taskgroup";
2376 break;
2377 default:
2378 error_at (gimple_location (stmt), "invalid arguments");
2379 return false;
2381 if (bad)
2383 error_at (gimple_location (stmt),
2384 "%<%s %s%> construct not closely nested inside of %qs",
2385 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2386 == BUILT_IN_GOMP_CANCEL
2387 ? "#pragma omp cancel"
2388 : "#pragma omp cancellation point", kind, bad);
2389 return false;
2392 /* FALLTHRU */
2393 case GIMPLE_OMP_SECTIONS:
2394 case GIMPLE_OMP_SINGLE:
2395 for (; ctx != NULL; ctx = ctx->outer)
2396 switch (gimple_code (ctx->stmt))
2398 case GIMPLE_OMP_FOR:
2399 case GIMPLE_OMP_SECTIONS:
2400 case GIMPLE_OMP_SINGLE:
2401 case GIMPLE_OMP_ORDERED:
2402 case GIMPLE_OMP_MASTER:
2403 case GIMPLE_OMP_TASK:
2404 case GIMPLE_OMP_CRITICAL:
2405 if (is_gimple_call (stmt))
2407 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2408 != BUILT_IN_GOMP_BARRIER)
2409 return true;
2410 error_at (gimple_location (stmt),
2411 "barrier region may not be closely nested inside "
2412 "of work-sharing, critical, ordered, master or "
2413 "explicit task region");
2414 return false;
2416 error_at (gimple_location (stmt),
2417 "work-sharing region may not be closely nested inside "
2418 "of work-sharing, critical, ordered, master or explicit "
2419 "task region");
2420 return false;
2421 case GIMPLE_OMP_PARALLEL:
2422 return true;
2423 default:
2424 break;
2426 break;
2427 case GIMPLE_OMP_MASTER:
2428 for (; ctx != NULL; ctx = ctx->outer)
2429 switch (gimple_code (ctx->stmt))
2431 case GIMPLE_OMP_FOR:
2432 case GIMPLE_OMP_SECTIONS:
2433 case GIMPLE_OMP_SINGLE:
2434 case GIMPLE_OMP_TASK:
2435 error_at (gimple_location (stmt),
2436 "master region may not be closely nested inside "
2437 "of work-sharing or explicit task region");
2438 return false;
2439 case GIMPLE_OMP_PARALLEL:
2440 return true;
2441 default:
2442 break;
2444 break;
2445 case GIMPLE_OMP_ORDERED:
2446 for (; ctx != NULL; ctx = ctx->outer)
2447 switch (gimple_code (ctx->stmt))
2449 case GIMPLE_OMP_CRITICAL:
2450 case GIMPLE_OMP_TASK:
2451 error_at (gimple_location (stmt),
2452 "ordered region may not be closely nested inside "
2453 "of critical or explicit task region");
2454 return false;
2455 case GIMPLE_OMP_FOR:
2456 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2457 OMP_CLAUSE_ORDERED) == NULL)
2459 error_at (gimple_location (stmt),
2460 "ordered region must be closely nested inside "
2461 "a loop region with an ordered clause");
2462 return false;
2464 return true;
2465 case GIMPLE_OMP_PARALLEL:
2466 error_at (gimple_location (stmt),
2467 "ordered region must be closely nested inside "
2468 "a loop region with an ordered clause");
2469 return false;
2470 default:
2471 break;
2473 break;
2474 case GIMPLE_OMP_CRITICAL:
2475 for (; ctx != NULL; ctx = ctx->outer)
2476 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2477 && (gimple_omp_critical_name (stmt)
2478 == gimple_omp_critical_name (ctx->stmt)))
2480 error_at (gimple_location (stmt),
2481 "critical region may not be nested inside a critical "
2482 "region with the same name");
2483 return false;
2485 break;
2486 case GIMPLE_OMP_TEAMS:
2487 if (ctx == NULL
2488 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2489 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2491 error_at (gimple_location (stmt),
2492 "teams construct not closely nested inside of target "
2493 "region");
2494 return false;
2496 break;
2497 default:
2498 break;
2500 return true;
2504 /* Helper function scan_omp.
2506 Callback for walk_tree or operators in walk_gimple_stmt used to
2507 scan for OpenMP directives in TP. */
2509 static tree
2510 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2512 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2513 omp_context *ctx = (omp_context *) wi->info;
2514 tree t = *tp;
2516 switch (TREE_CODE (t))
2518 case VAR_DECL:
2519 case PARM_DECL:
2520 case LABEL_DECL:
2521 case RESULT_DECL:
2522 if (ctx)
2523 *tp = remap_decl (t, &ctx->cb);
2524 break;
2526 default:
2527 if (ctx && TYPE_P (t))
2528 *tp = remap_type (t, &ctx->cb);
2529 else if (!DECL_P (t))
2531 *walk_subtrees = 1;
2532 if (ctx)
2534 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2535 if (tem != TREE_TYPE (t))
2537 if (TREE_CODE (t) == INTEGER_CST)
2538 *tp = build_int_cst_wide (tem,
2539 TREE_INT_CST_LOW (t),
2540 TREE_INT_CST_HIGH (t));
2541 else
2542 TREE_TYPE (t) = tem;
2546 break;
2549 return NULL_TREE;
2552 /* Return true if FNDECL is a setjmp or a longjmp. */
2554 static bool
2555 setjmp_or_longjmp_p (const_tree fndecl)
2557 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2558 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2559 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2560 return true;
2562 tree declname = DECL_NAME (fndecl);
2563 if (!declname)
2564 return false;
2565 const char *name = IDENTIFIER_POINTER (declname);
2566 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2570 /* Helper function for scan_omp.
2572 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2573 the current statement in GSI. */
2575 static tree
2576 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2577 struct walk_stmt_info *wi)
2579 gimple stmt = gsi_stmt (*gsi);
2580 omp_context *ctx = (omp_context *) wi->info;
2582 if (gimple_has_location (stmt))
2583 input_location = gimple_location (stmt);
2585 /* Check the OpenMP nesting restrictions. */
2586 bool remove = false;
2587 if (is_gimple_omp (stmt))
2588 remove = !check_omp_nesting_restrictions (stmt, ctx);
2589 else if (is_gimple_call (stmt))
2591 tree fndecl = gimple_call_fndecl (stmt);
2592 if (fndecl)
2594 if (setjmp_or_longjmp_p (fndecl)
2595 && ctx
2596 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2597 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2599 remove = true;
2600 error_at (gimple_location (stmt),
2601 "setjmp/longjmp inside simd construct");
2603 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2604 switch (DECL_FUNCTION_CODE (fndecl))
2606 case BUILT_IN_GOMP_BARRIER:
2607 case BUILT_IN_GOMP_CANCEL:
2608 case BUILT_IN_GOMP_CANCELLATION_POINT:
2609 case BUILT_IN_GOMP_TASKYIELD:
2610 case BUILT_IN_GOMP_TASKWAIT:
2611 case BUILT_IN_GOMP_TASKGROUP_START:
2612 case BUILT_IN_GOMP_TASKGROUP_END:
2613 remove = !check_omp_nesting_restrictions (stmt, ctx);
2614 break;
2615 default:
2616 break;
2620 if (remove)
2622 stmt = gimple_build_nop ();
2623 gsi_replace (gsi, stmt, false);
2626 *handled_ops_p = true;
2628 switch (gimple_code (stmt))
2630 case GIMPLE_OMP_PARALLEL:
2631 taskreg_nesting_level++;
2632 scan_omp_parallel (gsi, ctx);
2633 taskreg_nesting_level--;
2634 break;
2636 case GIMPLE_OMP_TASK:
2637 taskreg_nesting_level++;
2638 scan_omp_task (gsi, ctx);
2639 taskreg_nesting_level--;
2640 break;
2642 case GIMPLE_OMP_FOR:
2643 scan_omp_for (stmt, ctx);
2644 break;
2646 case GIMPLE_OMP_SECTIONS:
2647 scan_omp_sections (stmt, ctx);
2648 break;
2650 case GIMPLE_OMP_SINGLE:
2651 scan_omp_single (stmt, ctx);
2652 break;
2654 case GIMPLE_OMP_SECTION:
2655 case GIMPLE_OMP_MASTER:
2656 case GIMPLE_OMP_TASKGROUP:
2657 case GIMPLE_OMP_ORDERED:
2658 case GIMPLE_OMP_CRITICAL:
2659 ctx = new_omp_context (stmt, ctx);
2660 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2661 break;
2663 case GIMPLE_OMP_TARGET:
2664 scan_omp_target (stmt, ctx);
2665 break;
2667 case GIMPLE_OMP_TEAMS:
2668 scan_omp_teams (stmt, ctx);
2669 break;
2671 case GIMPLE_BIND:
2673 tree var;
2675 *handled_ops_p = false;
2676 if (ctx)
2677 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2678 insert_decl_map (&ctx->cb, var, var);
2680 break;
2681 default:
2682 *handled_ops_p = false;
2683 break;
2686 return NULL_TREE;
2690 /* Scan all the statements starting at the current statement. CTX
2691 contains context information about the OpenMP directives and
2692 clauses found during the scan. */
2694 static void
2695 scan_omp (gimple_seq *body_p, omp_context *ctx)
2697 location_t saved_location;
2698 struct walk_stmt_info wi;
2700 memset (&wi, 0, sizeof (wi));
2701 wi.info = ctx;
2702 wi.want_locations = true;
2704 saved_location = input_location;
2705 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2706 input_location = saved_location;
2709 /* Re-gimplification and code generation routines. */
2711 /* Build a call to GOMP_barrier. */
2713 static gimple
2714 build_omp_barrier (tree lhs)
2716 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2717 : BUILT_IN_GOMP_BARRIER);
2718 gimple g = gimple_build_call (fndecl, 0);
2719 if (lhs)
2720 gimple_call_set_lhs (g, lhs);
2721 return g;
2724 /* If a context was created for STMT when it was scanned, return it. */
2726 static omp_context *
2727 maybe_lookup_ctx (gimple stmt)
2729 splay_tree_node n;
2730 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2731 return n ? (omp_context *) n->value : NULL;
2735 /* Find the mapping for DECL in CTX or the immediately enclosing
2736 context that has a mapping for DECL.
2738 If CTX is a nested parallel directive, we may have to use the decl
2739 mappings created in CTX's parent context. Suppose that we have the
2740 following parallel nesting (variable UIDs showed for clarity):
2742 iD.1562 = 0;
2743 #omp parallel shared(iD.1562) -> outer parallel
2744 iD.1562 = iD.1562 + 1;
2746 #omp parallel shared (iD.1562) -> inner parallel
2747 iD.1562 = iD.1562 - 1;
2749 Each parallel structure will create a distinct .omp_data_s structure
2750 for copying iD.1562 in/out of the directive:
2752 outer parallel .omp_data_s.1.i -> iD.1562
2753 inner parallel .omp_data_s.2.i -> iD.1562
2755 A shared variable mapping will produce a copy-out operation before
2756 the parallel directive and a copy-in operation after it. So, in
2757 this case we would have:
2759 iD.1562 = 0;
2760 .omp_data_o.1.i = iD.1562;
2761 #omp parallel shared(iD.1562) -> outer parallel
2762 .omp_data_i.1 = &.omp_data_o.1
2763 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2765 .omp_data_o.2.i = iD.1562; -> **
2766 #omp parallel shared(iD.1562) -> inner parallel
2767 .omp_data_i.2 = &.omp_data_o.2
2768 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2771 ** This is a problem. The symbol iD.1562 cannot be referenced
2772 inside the body of the outer parallel region. But since we are
2773 emitting this copy operation while expanding the inner parallel
2774 directive, we need to access the CTX structure of the outer
2775 parallel directive to get the correct mapping:
2777 .omp_data_o.2.i = .omp_data_i.1->i
2779 Since there may be other workshare or parallel directives enclosing
2780 the parallel directive, it may be necessary to walk up the context
2781 parent chain. This is not a problem in general because nested
2782 parallelism happens only rarely. */
2784 static tree
2785 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2787 tree t;
2788 omp_context *up;
2790 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2791 t = maybe_lookup_decl (decl, up);
2793 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2795 return t ? t : decl;
2799 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2800 in outer contexts. */
2802 static tree
2803 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2805 tree t = NULL;
2806 omp_context *up;
2808 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2809 t = maybe_lookup_decl (decl, up);
2811 return t ? t : decl;
2815 /* Construct the initialization value for reduction CLAUSE. */
2817 tree
2818 omp_reduction_init (tree clause, tree type)
2820 location_t loc = OMP_CLAUSE_LOCATION (clause);
2821 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2823 case PLUS_EXPR:
2824 case MINUS_EXPR:
2825 case BIT_IOR_EXPR:
2826 case BIT_XOR_EXPR:
2827 case TRUTH_OR_EXPR:
2828 case TRUTH_ORIF_EXPR:
2829 case TRUTH_XOR_EXPR:
2830 case NE_EXPR:
2831 return build_zero_cst (type);
2833 case MULT_EXPR:
2834 case TRUTH_AND_EXPR:
2835 case TRUTH_ANDIF_EXPR:
2836 case EQ_EXPR:
2837 return fold_convert_loc (loc, type, integer_one_node);
2839 case BIT_AND_EXPR:
2840 return fold_convert_loc (loc, type, integer_minus_one_node);
2842 case MAX_EXPR:
2843 if (SCALAR_FLOAT_TYPE_P (type))
2845 REAL_VALUE_TYPE max, min;
2846 if (HONOR_INFINITIES (TYPE_MODE (type)))
2848 real_inf (&max);
2849 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2851 else
2852 real_maxval (&min, 1, TYPE_MODE (type));
2853 return build_real (type, min);
2855 else
2857 gcc_assert (INTEGRAL_TYPE_P (type));
2858 return TYPE_MIN_VALUE (type);
2861 case MIN_EXPR:
2862 if (SCALAR_FLOAT_TYPE_P (type))
2864 REAL_VALUE_TYPE max;
2865 if (HONOR_INFINITIES (TYPE_MODE (type)))
2866 real_inf (&max);
2867 else
2868 real_maxval (&max, 0, TYPE_MODE (type));
2869 return build_real (type, max);
2871 else
2873 gcc_assert (INTEGRAL_TYPE_P (type));
2874 return TYPE_MAX_VALUE (type);
2877 default:
2878 gcc_unreachable ();
2882 /* Return alignment to be assumed for var in CLAUSE, which should be
2883 OMP_CLAUSE_ALIGNED. */
2885 static tree
2886 omp_clause_aligned_alignment (tree clause)
2888 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
2889 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
2891 /* Otherwise return implementation defined alignment. */
2892 unsigned int al = 1;
2893 enum machine_mode mode, vmode;
2894 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2895 if (vs)
2896 vs = 1 << floor_log2 (vs);
2897 static enum mode_class classes[]
2898 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
2899 for (int i = 0; i < 4; i += 2)
2900 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
2901 mode != VOIDmode;
2902 mode = GET_MODE_WIDER_MODE (mode))
2904 vmode = targetm.vectorize.preferred_simd_mode (mode);
2905 if (GET_MODE_CLASS (vmode) != classes[i + 1])
2906 continue;
2907 while (vs
2908 && GET_MODE_SIZE (vmode) < vs
2909 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
2910 vmode = GET_MODE_2XWIDER_MODE (vmode);
2912 tree type = lang_hooks.types.type_for_mode (mode, 1);
2913 if (type == NULL_TREE || TYPE_MODE (type) != mode)
2914 continue;
2915 type = build_vector_type (type, GET_MODE_SIZE (vmode)
2916 / GET_MODE_SIZE (mode));
2917 if (TYPE_MODE (type) != vmode)
2918 continue;
2919 if (TYPE_ALIGN_UNIT (type) > al)
2920 al = TYPE_ALIGN_UNIT (type);
2922 return build_int_cst (integer_type_node, al);
2925 /* Return maximum possible vectorization factor for the target. */
2927 static int
2928 omp_max_vf (void)
2930 if (!optimize
2931 || optimize_debug
2932 || (!flag_tree_loop_vectorize
2933 && (global_options_set.x_flag_tree_loop_vectorize
2934 || global_options_set.x_flag_tree_vectorize)))
2935 return 1;
2937 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2938 if (vs)
2940 vs = 1 << floor_log2 (vs);
2941 return vs;
2943 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
2944 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
2945 return GET_MODE_NUNITS (vqimode);
2946 return 1;
2949 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2950 privatization. */
2952 static bool
2953 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
2954 tree &idx, tree &lane, tree &ivar, tree &lvar)
2956 if (max_vf == 0)
2958 max_vf = omp_max_vf ();
2959 if (max_vf > 1)
2961 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2962 OMP_CLAUSE_SAFELEN);
2963 if (c
2964 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
2965 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
2967 if (max_vf > 1)
2969 idx = create_tmp_var (unsigned_type_node, NULL);
2970 lane = create_tmp_var (unsigned_type_node, NULL);
2973 if (max_vf == 1)
2974 return false;
2976 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
2977 tree avar = create_tmp_var_raw (atype, NULL);
2978 if (TREE_ADDRESSABLE (new_var))
2979 TREE_ADDRESSABLE (avar) = 1;
2980 DECL_ATTRIBUTES (avar)
2981 = tree_cons (get_identifier ("omp simd array"), NULL,
2982 DECL_ATTRIBUTES (avar));
2983 gimple_add_tmp_var (avar);
2984 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
2985 NULL_TREE, NULL_TREE);
2986 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
2987 NULL_TREE, NULL_TREE);
2988 if (DECL_P (new_var))
2990 SET_DECL_VALUE_EXPR (new_var, lvar);
2991 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2993 return true;
2996 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
2997 from the receiver (aka child) side and initializers for REFERENCE_TYPE
2998 private variables. Initialization statements go in ILIST, while calls
2999 to destructors go in DLIST. */
3001 static void
3002 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3003 omp_context *ctx, struct omp_for_data *fd)
3005 tree c, dtor, copyin_seq, x, ptr;
3006 bool copyin_by_ref = false;
3007 bool lastprivate_firstprivate = false;
3008 bool reduction_omp_orig_ref = false;
3009 int pass;
3010 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3011 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD);
3012 int max_vf = 0;
3013 tree lane = NULL_TREE, idx = NULL_TREE;
3014 tree ivar = NULL_TREE, lvar = NULL_TREE;
3015 gimple_seq llist[2] = { NULL, NULL };
3017 copyin_seq = NULL;
3019 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3020 with data sharing clauses referencing variable sized vars. That
3021 is unnecessarily hard to support and very unlikely to result in
3022 vectorized code anyway. */
3023 if (is_simd)
3024 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3025 switch (OMP_CLAUSE_CODE (c))
3027 case OMP_CLAUSE_REDUCTION:
3028 case OMP_CLAUSE_PRIVATE:
3029 case OMP_CLAUSE_FIRSTPRIVATE:
3030 case OMP_CLAUSE_LASTPRIVATE:
3031 case OMP_CLAUSE_LINEAR:
3032 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3033 max_vf = 1;
3034 break;
3035 default:
3036 continue;
3039 /* Do all the fixed sized types in the first pass, and the variable sized
3040 types in the second pass. This makes sure that the scalar arguments to
3041 the variable sized types are processed before we use them in the
3042 variable sized operations. */
3043 for (pass = 0; pass < 2; ++pass)
3045 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3047 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3048 tree var, new_var;
3049 bool by_ref;
3050 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3052 switch (c_kind)
3054 case OMP_CLAUSE_PRIVATE:
3055 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3056 continue;
3057 break;
3058 case OMP_CLAUSE_SHARED:
3059 /* Ignore shared directives in teams construct. */
3060 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3061 continue;
3062 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3064 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3065 continue;
3067 case OMP_CLAUSE_FIRSTPRIVATE:
3068 case OMP_CLAUSE_COPYIN:
3069 case OMP_CLAUSE_LINEAR:
3070 break;
3071 case OMP_CLAUSE_REDUCTION:
3072 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3073 reduction_omp_orig_ref = true;
3074 break;
3075 case OMP_CLAUSE__LOOPTEMP_:
3076 /* Handle _looptemp_ clauses only on parallel. */
3077 if (fd)
3078 continue;
3079 break;
3080 case OMP_CLAUSE_LASTPRIVATE:
3081 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3083 lastprivate_firstprivate = true;
3084 if (pass != 0)
3085 continue;
3087 break;
3088 case OMP_CLAUSE_ALIGNED:
3089 if (pass == 0)
3090 continue;
3091 var = OMP_CLAUSE_DECL (c);
3092 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3093 && !is_global_var (var))
3095 new_var = maybe_lookup_decl (var, ctx);
3096 if (new_var == NULL_TREE)
3097 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3098 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3099 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3100 omp_clause_aligned_alignment (c));
3101 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3102 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3103 gimplify_and_add (x, ilist);
3105 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3106 && is_global_var (var))
3108 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3109 new_var = lookup_decl (var, ctx);
3110 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3111 t = build_fold_addr_expr_loc (clause_loc, t);
3112 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3113 t = build_call_expr_loc (clause_loc, t2, 2, t,
3114 omp_clause_aligned_alignment (c));
3115 t = fold_convert_loc (clause_loc, ptype, t);
3116 x = create_tmp_var (ptype, NULL);
3117 t = build2 (MODIFY_EXPR, ptype, x, t);
3118 gimplify_and_add (t, ilist);
3119 t = build_simple_mem_ref_loc (clause_loc, x);
3120 SET_DECL_VALUE_EXPR (new_var, t);
3121 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3123 continue;
3124 default:
3125 continue;
3128 new_var = var = OMP_CLAUSE_DECL (c);
3129 if (c_kind != OMP_CLAUSE_COPYIN)
3130 new_var = lookup_decl (var, ctx);
3132 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3134 if (pass != 0)
3135 continue;
3137 else if (is_variable_sized (var))
3139 /* For variable sized types, we need to allocate the
3140 actual storage here. Call alloca and store the
3141 result in the pointer decl that we created elsewhere. */
3142 if (pass == 0)
3143 continue;
3145 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3147 gimple stmt;
3148 tree tmp, atmp;
3150 ptr = DECL_VALUE_EXPR (new_var);
3151 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3152 ptr = TREE_OPERAND (ptr, 0);
3153 gcc_assert (DECL_P (ptr));
3154 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3156 /* void *tmp = __builtin_alloca */
3157 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3158 stmt = gimple_build_call (atmp, 1, x);
3159 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3160 gimple_add_tmp_var (tmp);
3161 gimple_call_set_lhs (stmt, tmp);
3163 gimple_seq_add_stmt (ilist, stmt);
3165 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3166 gimplify_assign (ptr, x, ilist);
3169 else if (is_reference (var))
3171 /* For references that are being privatized for Fortran,
3172 allocate new backing storage for the new pointer
3173 variable. This allows us to avoid changing all the
3174 code that expects a pointer to something that expects
3175 a direct variable. */
3176 if (pass == 0)
3177 continue;
3179 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3180 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3182 x = build_receiver_ref (var, false, ctx);
3183 x = build_fold_addr_expr_loc (clause_loc, x);
3185 else if (TREE_CONSTANT (x))
3187 /* For reduction with placeholder in SIMD loop,
3188 defer adding the initialization of the reference,
3189 because if we decide to use SIMD array for it,
3190 the initilization could cause expansion ICE. */
3191 if (c_kind == OMP_CLAUSE_REDUCTION
3192 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
3193 && is_simd)
3194 x = NULL_TREE;
3195 else
3197 const char *name = NULL;
3198 if (DECL_NAME (var))
3199 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3201 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3202 name);
3203 gimple_add_tmp_var (x);
3204 TREE_ADDRESSABLE (x) = 1;
3205 x = build_fold_addr_expr_loc (clause_loc, x);
3208 else
3210 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3211 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3214 if (x)
3216 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3217 gimplify_assign (new_var, x, ilist);
3220 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3222 else if (c_kind == OMP_CLAUSE_REDUCTION
3223 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3225 if (pass == 0)
3226 continue;
3228 else if (pass != 0)
3229 continue;
3231 switch (OMP_CLAUSE_CODE (c))
3233 case OMP_CLAUSE_SHARED:
3234 /* Ignore shared directives in teams construct. */
3235 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3236 continue;
3237 /* Shared global vars are just accessed directly. */
3238 if (is_global_var (new_var))
3239 break;
3240 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3241 needs to be delayed until after fixup_child_record_type so
3242 that we get the correct type during the dereference. */
3243 by_ref = use_pointer_for_field (var, ctx);
3244 x = build_receiver_ref (var, by_ref, ctx);
3245 SET_DECL_VALUE_EXPR (new_var, x);
3246 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3248 /* ??? If VAR is not passed by reference, and the variable
3249 hasn't been initialized yet, then we'll get a warning for
3250 the store into the omp_data_s structure. Ideally, we'd be
3251 able to notice this and not store anything at all, but
3252 we're generating code too early. Suppress the warning. */
3253 if (!by_ref)
3254 TREE_NO_WARNING (var) = 1;
3255 break;
3257 case OMP_CLAUSE_LASTPRIVATE:
3258 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3259 break;
3260 /* FALLTHRU */
3262 case OMP_CLAUSE_PRIVATE:
3263 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3264 x = build_outer_var_ref (var, ctx);
3265 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3267 if (is_task_ctx (ctx))
3268 x = build_receiver_ref (var, false, ctx);
3269 else
3270 x = build_outer_var_ref (var, ctx);
3272 else
3273 x = NULL;
3274 do_private:
3275 tree nx;
3276 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3277 if (is_simd)
3279 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3280 if ((TREE_ADDRESSABLE (new_var) || nx || y
3281 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3282 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3283 idx, lane, ivar, lvar))
3285 if (nx)
3286 x = lang_hooks.decls.omp_clause_default_ctor
3287 (c, unshare_expr (ivar), x);
3288 if (nx && x)
3289 gimplify_and_add (x, &llist[0]);
3290 if (y)
3292 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3293 if (y)
3295 gimple_seq tseq = NULL;
3297 dtor = y;
3298 gimplify_stmt (&dtor, &tseq);
3299 gimple_seq_add_seq (&llist[1], tseq);
3302 break;
3305 if (nx)
3306 gimplify_and_add (nx, ilist);
3307 /* FALLTHRU */
3309 do_dtor:
3310 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3311 if (x)
3313 gimple_seq tseq = NULL;
3315 dtor = x;
3316 gimplify_stmt (&dtor, &tseq);
3317 gimple_seq_add_seq (dlist, tseq);
3319 break;
3321 case OMP_CLAUSE_LINEAR:
3322 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3323 goto do_firstprivate;
3324 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3325 x = NULL;
3326 else
3327 x = build_outer_var_ref (var, ctx);
3328 goto do_private;
3330 case OMP_CLAUSE_FIRSTPRIVATE:
3331 if (is_task_ctx (ctx))
3333 if (is_reference (var) || is_variable_sized (var))
3334 goto do_dtor;
3335 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3336 ctx))
3337 || use_pointer_for_field (var, NULL))
3339 x = build_receiver_ref (var, false, ctx);
3340 SET_DECL_VALUE_EXPR (new_var, x);
3341 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3342 goto do_dtor;
3345 do_firstprivate:
3346 x = build_outer_var_ref (var, ctx);
3347 if (is_simd)
3349 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3350 && gimple_omp_for_combined_into_p (ctx->stmt))
3352 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3353 ? sizetype : TREE_TYPE (x);
3354 tree t = fold_convert (stept,
3355 OMP_CLAUSE_LINEAR_STEP (c));
3356 tree c = find_omp_clause (clauses,
3357 OMP_CLAUSE__LOOPTEMP_);
3358 gcc_assert (c);
3359 tree l = OMP_CLAUSE_DECL (c);
3360 if (fd->collapse == 1)
3362 tree n1 = fd->loop.n1;
3363 tree step = fd->loop.step;
3364 tree itype = TREE_TYPE (l);
3365 if (POINTER_TYPE_P (itype))
3366 itype = signed_type_for (itype);
3367 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3368 if (TYPE_UNSIGNED (itype)
3369 && fd->loop.cond_code == GT_EXPR)
3370 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3371 fold_build1 (NEGATE_EXPR,
3372 itype, l),
3373 fold_build1 (NEGATE_EXPR,
3374 itype, step));
3375 else
3376 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3378 t = fold_build2 (MULT_EXPR, stept,
3379 fold_convert (stept, l), t);
3380 if (POINTER_TYPE_P (TREE_TYPE (x)))
3381 x = fold_build2 (POINTER_PLUS_EXPR,
3382 TREE_TYPE (x), x, t);
3383 else
3384 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3387 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3388 || TREE_ADDRESSABLE (new_var))
3389 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3390 idx, lane, ivar, lvar))
3392 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3394 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3395 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3396 gimplify_and_add (x, ilist);
3397 gimple_stmt_iterator gsi
3398 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3399 gimple g
3400 = gimple_build_assign (unshare_expr (lvar), iv);
3401 gsi_insert_before_without_update (&gsi, g,
3402 GSI_SAME_STMT);
3403 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3404 ? sizetype : TREE_TYPE (x);
3405 tree t = fold_convert (stept,
3406 OMP_CLAUSE_LINEAR_STEP (c));
3407 enum tree_code code = PLUS_EXPR;
3408 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3409 code = POINTER_PLUS_EXPR;
3410 g = gimple_build_assign_with_ops (code, iv, iv, t);
3411 gsi_insert_before_without_update (&gsi, g,
3412 GSI_SAME_STMT);
3413 break;
3415 x = lang_hooks.decls.omp_clause_copy_ctor
3416 (c, unshare_expr (ivar), x);
3417 gimplify_and_add (x, &llist[0]);
3418 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3419 if (x)
3421 gimple_seq tseq = NULL;
3423 dtor = x;
3424 gimplify_stmt (&dtor, &tseq);
3425 gimple_seq_add_seq (&llist[1], tseq);
3427 break;
3430 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3431 gimplify_and_add (x, ilist);
3432 goto do_dtor;
3434 case OMP_CLAUSE__LOOPTEMP_:
3435 gcc_assert (is_parallel_ctx (ctx));
3436 x = build_outer_var_ref (var, ctx);
3437 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3438 gimplify_and_add (x, ilist);
3439 break;
3441 case OMP_CLAUSE_COPYIN:
3442 by_ref = use_pointer_for_field (var, NULL);
3443 x = build_receiver_ref (var, by_ref, ctx);
3444 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3445 append_to_statement_list (x, &copyin_seq);
3446 copyin_by_ref |= by_ref;
3447 break;
3449 case OMP_CLAUSE_REDUCTION:
3450 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3452 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3453 gimple tseq;
3454 x = build_outer_var_ref (var, ctx);
3456 if (is_reference (var)
3457 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3458 TREE_TYPE (x)))
3459 x = build_fold_addr_expr_loc (clause_loc, x);
3460 SET_DECL_VALUE_EXPR (placeholder, x);
3461 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3462 tree new_vard = new_var;
3463 if (is_reference (var))
3465 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3466 new_vard = TREE_OPERAND (new_var, 0);
3467 gcc_assert (DECL_P (new_vard));
3469 if (is_simd
3470 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3471 idx, lane, ivar, lvar))
3473 if (new_vard == new_var)
3475 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3476 SET_DECL_VALUE_EXPR (new_var, ivar);
3478 else
3480 SET_DECL_VALUE_EXPR (new_vard,
3481 build_fold_addr_expr (ivar));
3482 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3484 x = lang_hooks.decls.omp_clause_default_ctor
3485 (c, unshare_expr (ivar),
3486 build_outer_var_ref (var, ctx));
3487 if (x)
3488 gimplify_and_add (x, &llist[0]);
3489 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3491 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3492 lower_omp (&tseq, ctx);
3493 gimple_seq_add_seq (&llist[0], tseq);
3495 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3496 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3497 lower_omp (&tseq, ctx);
3498 gimple_seq_add_seq (&llist[1], tseq);
3499 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3500 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3501 if (new_vard == new_var)
3502 SET_DECL_VALUE_EXPR (new_var, lvar);
3503 else
3504 SET_DECL_VALUE_EXPR (new_vard,
3505 build_fold_addr_expr (lvar));
3506 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3507 if (x)
3509 tseq = NULL;
3510 dtor = x;
3511 gimplify_stmt (&dtor, &tseq);
3512 gimple_seq_add_seq (&llist[1], tseq);
3514 break;
3516 /* If this is a reference to constant size reduction var
3517 with placeholder, we haven't emitted the initializer
3518 for it because it is undesirable if SIMD arrays are used.
3519 But if they aren't used, we need to emit the deferred
3520 initialization now. */
3521 else if (is_reference (var) && is_simd)
3523 tree z
3524 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3525 if (TREE_CONSTANT (z))
3527 const char *name = NULL;
3528 if (DECL_NAME (var))
3529 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3531 z = create_tmp_var_raw
3532 (TREE_TYPE (TREE_TYPE (new_vard)), name);
3533 gimple_add_tmp_var (z);
3534 TREE_ADDRESSABLE (z) = 1;
3535 z = build_fold_addr_expr_loc (clause_loc, z);
3536 gimplify_assign (new_vard, z, ilist);
3539 x = lang_hooks.decls.omp_clause_default_ctor
3540 (c, new_var, unshare_expr (x));
3541 if (x)
3542 gimplify_and_add (x, ilist);
3543 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3545 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3546 lower_omp (&tseq, ctx);
3547 gimple_seq_add_seq (ilist, tseq);
3549 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3550 if (is_simd)
3552 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3553 lower_omp (&tseq, ctx);
3554 gimple_seq_add_seq (dlist, tseq);
3555 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3557 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3558 goto do_dtor;
3560 else
3562 x = omp_reduction_init (c, TREE_TYPE (new_var));
3563 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3564 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3566 /* reduction(-:var) sums up the partial results, so it
3567 acts identically to reduction(+:var). */
3568 if (code == MINUS_EXPR)
3569 code = PLUS_EXPR;
3571 if (is_simd
3572 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3573 idx, lane, ivar, lvar))
3575 tree ref = build_outer_var_ref (var, ctx);
3577 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3579 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3580 ref = build_outer_var_ref (var, ctx);
3581 gimplify_assign (ref, x, &llist[1]);
3583 else
3585 gimplify_assign (new_var, x, ilist);
3586 if (is_simd)
3588 tree ref = build_outer_var_ref (var, ctx);
3590 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3591 ref = build_outer_var_ref (var, ctx);
3592 gimplify_assign (ref, x, dlist);
3596 break;
3598 default:
3599 gcc_unreachable ();
3604 if (lane)
3606 tree uid = create_tmp_var (ptr_type_node, "simduid");
3607 /* Don't want uninit warnings on simduid, it is always uninitialized,
3608 but we use it not for the value, but for the DECL_UID only. */
3609 TREE_NO_WARNING (uid) = 1;
3610 gimple g
3611 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3612 gimple_call_set_lhs (g, lane);
3613 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3614 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3615 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3616 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3617 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3618 gimple_omp_for_set_clauses (ctx->stmt, c);
3619 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3620 build_int_cst (unsigned_type_node, 0),
3621 NULL_TREE);
3622 gimple_seq_add_stmt (ilist, g);
3623 for (int i = 0; i < 2; i++)
3624 if (llist[i])
3626 tree vf = create_tmp_var (unsigned_type_node, NULL);
3627 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3628 gimple_call_set_lhs (g, vf);
3629 gimple_seq *seq = i == 0 ? ilist : dlist;
3630 gimple_seq_add_stmt (seq, g);
3631 tree t = build_int_cst (unsigned_type_node, 0);
3632 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3633 gimple_seq_add_stmt (seq, g);
3634 tree body = create_artificial_label (UNKNOWN_LOCATION);
3635 tree header = create_artificial_label (UNKNOWN_LOCATION);
3636 tree end = create_artificial_label (UNKNOWN_LOCATION);
3637 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3638 gimple_seq_add_stmt (seq, gimple_build_label (body));
3639 gimple_seq_add_seq (seq, llist[i]);
3640 t = build_int_cst (unsigned_type_node, 1);
3641 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3642 gimple_seq_add_stmt (seq, g);
3643 gimple_seq_add_stmt (seq, gimple_build_label (header));
3644 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3645 gimple_seq_add_stmt (seq, g);
3646 gimple_seq_add_stmt (seq, gimple_build_label (end));
3650 /* The copyin sequence is not to be executed by the main thread, since
3651 that would result in self-copies. Perhaps not visible to scalars,
3652 but it certainly is to C++ operator=. */
3653 if (copyin_seq)
3655 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3657 x = build2 (NE_EXPR, boolean_type_node, x,
3658 build_int_cst (TREE_TYPE (x), 0));
3659 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3660 gimplify_and_add (x, ilist);
3663 /* If any copyin variable is passed by reference, we must ensure the
3664 master thread doesn't modify it before it is copied over in all
3665 threads. Similarly for variables in both firstprivate and
3666 lastprivate clauses we need to ensure the lastprivate copying
3667 happens after firstprivate copying in all threads. And similarly
3668 for UDRs if initializer expression refers to omp_orig. */
3669 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3671 /* Don't add any barrier for #pragma omp simd or
3672 #pragma omp distribute. */
3673 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3674 || gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_FOR)
3675 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3678 /* If max_vf is non-zero, then we can use only a vectorization factor
3679 up to the max_vf we chose. So stick it into the safelen clause. */
3680 if (max_vf)
3682 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3683 OMP_CLAUSE_SAFELEN);
3684 if (c == NULL_TREE
3685 || compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3686 max_vf) == 1)
3688 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3689 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3690 max_vf);
3691 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3692 gimple_omp_for_set_clauses (ctx->stmt, c);
3698 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3699 both parallel and workshare constructs. PREDICATE may be NULL if it's
3700 always true. */
3702 static void
3703 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3704 omp_context *ctx)
3706 tree x, c, label = NULL, orig_clauses = clauses;
3707 bool par_clauses = false;
3708 tree simduid = NULL, lastlane = NULL;
3710 /* Early exit if there are no lastprivate or linear clauses. */
3711 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3712 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3713 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3714 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3715 break;
3716 if (clauses == NULL)
3718 /* If this was a workshare clause, see if it had been combined
3719 with its parallel. In that case, look for the clauses on the
3720 parallel statement itself. */
3721 if (is_parallel_ctx (ctx))
3722 return;
3724 ctx = ctx->outer;
3725 if (ctx == NULL || !is_parallel_ctx (ctx))
3726 return;
3728 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3729 OMP_CLAUSE_LASTPRIVATE);
3730 if (clauses == NULL)
3731 return;
3732 par_clauses = true;
3735 if (predicate)
3737 gimple stmt;
3738 tree label_true, arm1, arm2;
3740 label = create_artificial_label (UNKNOWN_LOCATION);
3741 label_true = create_artificial_label (UNKNOWN_LOCATION);
3742 arm1 = TREE_OPERAND (predicate, 0);
3743 arm2 = TREE_OPERAND (predicate, 1);
3744 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3745 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3746 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3747 label_true, label);
3748 gimple_seq_add_stmt (stmt_list, stmt);
3749 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3752 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3753 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
3755 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3756 if (simduid)
3757 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3760 for (c = clauses; c ;)
3762 tree var, new_var;
3763 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3765 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3766 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3767 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3769 var = OMP_CLAUSE_DECL (c);
3770 new_var = lookup_decl (var, ctx);
3772 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3774 tree val = DECL_VALUE_EXPR (new_var);
3775 if (TREE_CODE (val) == ARRAY_REF
3776 && VAR_P (TREE_OPERAND (val, 0))
3777 && lookup_attribute ("omp simd array",
3778 DECL_ATTRIBUTES (TREE_OPERAND (val,
3779 0))))
3781 if (lastlane == NULL)
3783 lastlane = create_tmp_var (unsigned_type_node, NULL);
3784 gimple g
3785 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
3786 2, simduid,
3787 TREE_OPERAND (val, 1));
3788 gimple_call_set_lhs (g, lastlane);
3789 gimple_seq_add_stmt (stmt_list, g);
3791 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
3792 TREE_OPERAND (val, 0), lastlane,
3793 NULL_TREE, NULL_TREE);
3797 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3798 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
3800 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
3801 gimple_seq_add_seq (stmt_list,
3802 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3803 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
3806 x = build_outer_var_ref (var, ctx);
3807 if (is_reference (var))
3808 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3809 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
3810 gimplify_and_add (x, stmt_list);
3812 c = OMP_CLAUSE_CHAIN (c);
3813 if (c == NULL && !par_clauses)
3815 /* If this was a workshare clause, see if it had been combined
3816 with its parallel. In that case, continue looking for the
3817 clauses also on the parallel statement itself. */
3818 if (is_parallel_ctx (ctx))
3819 break;
3821 ctx = ctx->outer;
3822 if (ctx == NULL || !is_parallel_ctx (ctx))
3823 break;
3825 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3826 OMP_CLAUSE_LASTPRIVATE);
3827 par_clauses = true;
3831 if (label)
3832 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
3836 /* Generate code to implement the REDUCTION clauses. */
3838 static void
3839 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
3841 gimple_seq sub_seq = NULL;
3842 gimple stmt;
3843 tree x, c;
3844 int count = 0;
3846 /* SIMD reductions are handled in lower_rec_input_clauses. */
3847 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3848 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
3849 return;
3851 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3852 update in that case, otherwise use a lock. */
3853 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
3854 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
3856 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3858 /* Never use OMP_ATOMIC for array reductions or UDRs. */
3859 count = -1;
3860 break;
3862 count++;
3865 if (count == 0)
3866 return;
3868 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3870 tree var, ref, new_var;
3871 enum tree_code code;
3872 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3874 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
3875 continue;
3877 var = OMP_CLAUSE_DECL (c);
3878 new_var = lookup_decl (var, ctx);
3879 if (is_reference (var))
3880 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3881 ref = build_outer_var_ref (var, ctx);
3882 code = OMP_CLAUSE_REDUCTION_CODE (c);
3884 /* reduction(-:var) sums up the partial results, so it acts
3885 identically to reduction(+:var). */
3886 if (code == MINUS_EXPR)
3887 code = PLUS_EXPR;
3889 if (count == 1)
3891 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
3893 addr = save_expr (addr);
3894 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
3895 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
3896 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
3897 gimplify_and_add (x, stmt_seqp);
3898 return;
3901 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3903 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3905 if (is_reference (var)
3906 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3907 TREE_TYPE (ref)))
3908 ref = build_fold_addr_expr_loc (clause_loc, ref);
3909 SET_DECL_VALUE_EXPR (placeholder, ref);
3910 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3911 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
3912 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
3913 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3914 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
3916 else
3918 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3919 ref = build_outer_var_ref (var, ctx);
3920 gimplify_assign (ref, x, &sub_seq);
3924 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
3926 gimple_seq_add_stmt (stmt_seqp, stmt);
3928 gimple_seq_add_seq (stmt_seqp, sub_seq);
3930 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
3932 gimple_seq_add_stmt (stmt_seqp, stmt);
3936 /* Generate code to implement the COPYPRIVATE clauses. */
3938 static void
3939 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
3940 omp_context *ctx)
3942 tree c;
3944 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3946 tree var, new_var, ref, x;
3947 bool by_ref;
3948 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3950 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
3951 continue;
3953 var = OMP_CLAUSE_DECL (c);
3954 by_ref = use_pointer_for_field (var, NULL);
3956 ref = build_sender_ref (var, ctx);
3957 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
3958 if (by_ref)
3960 x = build_fold_addr_expr_loc (clause_loc, new_var);
3961 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
3963 gimplify_assign (ref, x, slist);
3965 ref = build_receiver_ref (var, false, ctx);
3966 if (by_ref)
3968 ref = fold_convert_loc (clause_loc,
3969 build_pointer_type (TREE_TYPE (new_var)),
3970 ref);
3971 ref = build_fold_indirect_ref_loc (clause_loc, ref);
3973 if (is_reference (var))
3975 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
3976 ref = build_simple_mem_ref_loc (clause_loc, ref);
3977 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3979 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
3980 gimplify_and_add (x, rlist);
3985 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
3986 and REDUCTION from the sender (aka parent) side. */
3988 static void
3989 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
3990 omp_context *ctx)
3992 tree c;
3994 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3996 tree val, ref, x, var;
3997 bool by_ref, do_in = false, do_out = false;
3998 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4000 switch (OMP_CLAUSE_CODE (c))
4002 case OMP_CLAUSE_PRIVATE:
4003 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4004 break;
4005 continue;
4006 case OMP_CLAUSE_FIRSTPRIVATE:
4007 case OMP_CLAUSE_COPYIN:
4008 case OMP_CLAUSE_LASTPRIVATE:
4009 case OMP_CLAUSE_REDUCTION:
4010 case OMP_CLAUSE__LOOPTEMP_:
4011 break;
4012 default:
4013 continue;
4016 val = OMP_CLAUSE_DECL (c);
4017 var = lookup_decl_in_outer_ctx (val, ctx);
4019 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4020 && is_global_var (var))
4021 continue;
4022 if (is_variable_sized (val))
4023 continue;
4024 by_ref = use_pointer_for_field (val, NULL);
4026 switch (OMP_CLAUSE_CODE (c))
4028 case OMP_CLAUSE_PRIVATE:
4029 case OMP_CLAUSE_FIRSTPRIVATE:
4030 case OMP_CLAUSE_COPYIN:
4031 case OMP_CLAUSE__LOOPTEMP_:
4032 do_in = true;
4033 break;
4035 case OMP_CLAUSE_LASTPRIVATE:
4036 if (by_ref || is_reference (val))
4038 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4039 continue;
4040 do_in = true;
4042 else
4044 do_out = true;
4045 if (lang_hooks.decls.omp_private_outer_ref (val))
4046 do_in = true;
4048 break;
4050 case OMP_CLAUSE_REDUCTION:
4051 do_in = true;
4052 do_out = !(by_ref || is_reference (val));
4053 break;
4055 default:
4056 gcc_unreachable ();
4059 if (do_in)
4061 ref = build_sender_ref (val, ctx);
4062 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4063 gimplify_assign (ref, x, ilist);
4064 if (is_task_ctx (ctx))
4065 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4068 if (do_out)
4070 ref = build_sender_ref (val, ctx);
4071 gimplify_assign (var, ref, olist);
4076 /* Generate code to implement SHARED from the sender (aka parent)
4077 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4078 list things that got automatically shared. */
4080 static void
4081 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4083 tree var, ovar, nvar, f, x, record_type;
4085 if (ctx->record_type == NULL)
4086 return;
4088 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4089 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4091 ovar = DECL_ABSTRACT_ORIGIN (f);
4092 nvar = maybe_lookup_decl (ovar, ctx);
4093 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4094 continue;
4096 /* If CTX is a nested parallel directive. Find the immediately
4097 enclosing parallel or workshare construct that contains a
4098 mapping for OVAR. */
4099 var = lookup_decl_in_outer_ctx (ovar, ctx);
4101 if (use_pointer_for_field (ovar, ctx))
4103 x = build_sender_ref (ovar, ctx);
4104 var = build_fold_addr_expr (var);
4105 gimplify_assign (x, var, ilist);
4107 else
4109 x = build_sender_ref (ovar, ctx);
4110 gimplify_assign (x, var, ilist);
4112 if (!TREE_READONLY (var)
4113 /* We don't need to receive a new reference to a result
4114 or parm decl. In fact we may not store to it as we will
4115 invalidate any pending RSO and generate wrong gimple
4116 during inlining. */
4117 && !((TREE_CODE (var) == RESULT_DECL
4118 || TREE_CODE (var) == PARM_DECL)
4119 && DECL_BY_REFERENCE (var)))
4121 x = build_sender_ref (ovar, ctx);
4122 gimplify_assign (var, x, olist);
4129 /* A convenience function to build an empty GIMPLE_COND with just the
4130 condition. */
4132 static gimple
4133 gimple_build_cond_empty (tree cond)
4135 enum tree_code pred_code;
4136 tree lhs, rhs;
4138 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4139 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4143 /* Build the function calls to GOMP_parallel_start etc to actually
4144 generate the parallel operation. REGION is the parallel region
4145 being expanded. BB is the block where to insert the code. WS_ARGS
4146 will be set if this is a call to a combined parallel+workshare
4147 construct, it contains the list of additional arguments needed by
4148 the workshare construct. */
4150 static void
4151 expand_parallel_call (struct omp_region *region, basic_block bb,
4152 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4154 tree t, t1, t2, val, cond, c, clauses, flags;
4155 gimple_stmt_iterator gsi;
4156 gimple stmt;
4157 enum built_in_function start_ix;
4158 int start_ix2;
4159 location_t clause_loc;
4160 vec<tree, va_gc> *args;
4162 clauses = gimple_omp_parallel_clauses (entry_stmt);
4164 /* Determine what flavor of GOMP_parallel we will be
4165 emitting. */
4166 start_ix = BUILT_IN_GOMP_PARALLEL;
4167 if (is_combined_parallel (region))
4169 switch (region->inner->type)
4171 case GIMPLE_OMP_FOR:
4172 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4173 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4174 + (region->inner->sched_kind
4175 == OMP_CLAUSE_SCHEDULE_RUNTIME
4176 ? 3 : region->inner->sched_kind));
4177 start_ix = (enum built_in_function)start_ix2;
4178 break;
4179 case GIMPLE_OMP_SECTIONS:
4180 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4181 break;
4182 default:
4183 gcc_unreachable ();
4187 /* By default, the value of NUM_THREADS is zero (selected at run time)
4188 and there is no conditional. */
4189 cond = NULL_TREE;
4190 val = build_int_cst (unsigned_type_node, 0);
4191 flags = build_int_cst (unsigned_type_node, 0);
4193 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4194 if (c)
4195 cond = OMP_CLAUSE_IF_EXPR (c);
4197 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4198 if (c)
4200 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4201 clause_loc = OMP_CLAUSE_LOCATION (c);
4203 else
4204 clause_loc = gimple_location (entry_stmt);
4206 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4207 if (c)
4208 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4210 /* Ensure 'val' is of the correct type. */
4211 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4213 /* If we found the clause 'if (cond)', build either
4214 (cond != 0) or (cond ? val : 1u). */
4215 if (cond)
4217 gimple_stmt_iterator gsi;
4219 cond = gimple_boolify (cond);
4221 if (integer_zerop (val))
4222 val = fold_build2_loc (clause_loc,
4223 EQ_EXPR, unsigned_type_node, cond,
4224 build_int_cst (TREE_TYPE (cond), 0));
4225 else
4227 basic_block cond_bb, then_bb, else_bb;
4228 edge e, e_then, e_else;
4229 tree tmp_then, tmp_else, tmp_join, tmp_var;
4231 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4232 if (gimple_in_ssa_p (cfun))
4234 tmp_then = make_ssa_name (tmp_var, NULL);
4235 tmp_else = make_ssa_name (tmp_var, NULL);
4236 tmp_join = make_ssa_name (tmp_var, NULL);
4238 else
4240 tmp_then = tmp_var;
4241 tmp_else = tmp_var;
4242 tmp_join = tmp_var;
4245 e = split_block (bb, NULL);
4246 cond_bb = e->src;
4247 bb = e->dest;
4248 remove_edge (e);
4250 then_bb = create_empty_bb (cond_bb);
4251 else_bb = create_empty_bb (then_bb);
4252 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4253 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4255 stmt = gimple_build_cond_empty (cond);
4256 gsi = gsi_start_bb (cond_bb);
4257 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4259 gsi = gsi_start_bb (then_bb);
4260 stmt = gimple_build_assign (tmp_then, val);
4261 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4263 gsi = gsi_start_bb (else_bb);
4264 stmt = gimple_build_assign
4265 (tmp_else, build_int_cst (unsigned_type_node, 1));
4266 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4268 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4269 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4270 if (current_loops)
4272 add_bb_to_loop (then_bb, cond_bb->loop_father);
4273 add_bb_to_loop (else_bb, cond_bb->loop_father);
4275 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4276 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4278 if (gimple_in_ssa_p (cfun))
4280 gimple phi = create_phi_node (tmp_join, bb);
4281 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4282 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4285 val = tmp_join;
4288 gsi = gsi_start_bb (bb);
4289 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4290 false, GSI_CONTINUE_LINKING);
4293 gsi = gsi_last_bb (bb);
4294 t = gimple_omp_parallel_data_arg (entry_stmt);
4295 if (t == NULL)
4296 t1 = null_pointer_node;
4297 else
4298 t1 = build_fold_addr_expr (t);
4299 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4301 vec_alloc (args, 4 + vec_safe_length (ws_args));
4302 args->quick_push (t2);
4303 args->quick_push (t1);
4304 args->quick_push (val);
4305 if (ws_args)
4306 args->splice (*ws_args);
4307 args->quick_push (flags);
4309 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4310 builtin_decl_explicit (start_ix), args);
4312 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4313 false, GSI_CONTINUE_LINKING);
4317 /* Build the function call to GOMP_task to actually
4318 generate the task operation. BB is the block where to insert the code. */
4320 static void
4321 expand_task_call (basic_block bb, gimple entry_stmt)
4323 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4324 gimple_stmt_iterator gsi;
4325 location_t loc = gimple_location (entry_stmt);
4327 clauses = gimple_omp_task_clauses (entry_stmt);
4329 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4330 if (c)
4331 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4332 else
4333 cond = boolean_true_node;
4335 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4336 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4337 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4338 flags = build_int_cst (unsigned_type_node,
4339 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4341 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4342 if (c)
4344 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4345 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4346 build_int_cst (unsigned_type_node, 2),
4347 build_int_cst (unsigned_type_node, 0));
4348 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4350 if (depend)
4351 depend = OMP_CLAUSE_DECL (depend);
4352 else
4353 depend = build_int_cst (ptr_type_node, 0);
4355 gsi = gsi_last_bb (bb);
4356 t = gimple_omp_task_data_arg (entry_stmt);
4357 if (t == NULL)
4358 t2 = null_pointer_node;
4359 else
4360 t2 = build_fold_addr_expr_loc (loc, t);
4361 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4362 t = gimple_omp_task_copy_fn (entry_stmt);
4363 if (t == NULL)
4364 t3 = null_pointer_node;
4365 else
4366 t3 = build_fold_addr_expr_loc (loc, t);
4368 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4369 8, t1, t2, t3,
4370 gimple_omp_task_arg_size (entry_stmt),
4371 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4372 depend);
4374 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4375 false, GSI_CONTINUE_LINKING);
4379 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4380 catch handler and return it. This prevents programs from violating the
4381 structured block semantics with throws. */
4383 static gimple_seq
4384 maybe_catch_exception (gimple_seq body)
4386 gimple g;
4387 tree decl;
4389 if (!flag_exceptions)
4390 return body;
4392 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4393 decl = lang_hooks.eh_protect_cleanup_actions ();
4394 else
4395 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4397 g = gimple_build_eh_must_not_throw (decl);
4398 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4399 GIMPLE_TRY_CATCH);
4401 return gimple_seq_alloc_with_stmt (g);
4404 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4406 static tree
4407 vec2chain (vec<tree, va_gc> *v)
4409 tree chain = NULL_TREE, t;
4410 unsigned ix;
4412 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4414 DECL_CHAIN (t) = chain;
4415 chain = t;
4418 return chain;
4422 /* Remove barriers in REGION->EXIT's block. Note that this is only
4423 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4424 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4425 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4426 removed. */
4428 static void
4429 remove_exit_barrier (struct omp_region *region)
4431 gimple_stmt_iterator gsi;
4432 basic_block exit_bb;
4433 edge_iterator ei;
4434 edge e;
4435 gimple stmt;
4436 int any_addressable_vars = -1;
4438 exit_bb = region->exit;
4440 /* If the parallel region doesn't return, we don't have REGION->EXIT
4441 block at all. */
4442 if (! exit_bb)
4443 return;
4445 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4446 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4447 statements that can appear in between are extremely limited -- no
4448 memory operations at all. Here, we allow nothing at all, so the
4449 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4450 gsi = gsi_last_bb (exit_bb);
4451 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4452 gsi_prev (&gsi);
4453 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4454 return;
4456 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4458 gsi = gsi_last_bb (e->src);
4459 if (gsi_end_p (gsi))
4460 continue;
4461 stmt = gsi_stmt (gsi);
4462 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4463 && !gimple_omp_return_nowait_p (stmt))
4465 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4466 in many cases. If there could be tasks queued, the barrier
4467 might be needed to let the tasks run before some local
4468 variable of the parallel that the task uses as shared
4469 runs out of scope. The task can be spawned either
4470 from within current function (this would be easy to check)
4471 or from some function it calls and gets passed an address
4472 of such a variable. */
4473 if (any_addressable_vars < 0)
4475 gimple parallel_stmt = last_stmt (region->entry);
4476 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4477 tree local_decls, block, decl;
4478 unsigned ix;
4480 any_addressable_vars = 0;
4481 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4482 if (TREE_ADDRESSABLE (decl))
4484 any_addressable_vars = 1;
4485 break;
4487 for (block = gimple_block (stmt);
4488 !any_addressable_vars
4489 && block
4490 && TREE_CODE (block) == BLOCK;
4491 block = BLOCK_SUPERCONTEXT (block))
4493 for (local_decls = BLOCK_VARS (block);
4494 local_decls;
4495 local_decls = DECL_CHAIN (local_decls))
4496 if (TREE_ADDRESSABLE (local_decls))
4498 any_addressable_vars = 1;
4499 break;
4501 if (block == gimple_block (parallel_stmt))
4502 break;
4505 if (!any_addressable_vars)
4506 gimple_omp_return_set_nowait (stmt);
4511 static void
4512 remove_exit_barriers (struct omp_region *region)
4514 if (region->type == GIMPLE_OMP_PARALLEL)
4515 remove_exit_barrier (region);
4517 if (region->inner)
4519 region = region->inner;
4520 remove_exit_barriers (region);
4521 while (region->next)
4523 region = region->next;
4524 remove_exit_barriers (region);
4529 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4530 calls. These can't be declared as const functions, but
4531 within one parallel body they are constant, so they can be
4532 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4533 which are declared const. Similarly for task body, except
4534 that in untied task omp_get_thread_num () can change at any task
4535 scheduling point. */
4537 static void
4538 optimize_omp_library_calls (gimple entry_stmt)
4540 basic_block bb;
4541 gimple_stmt_iterator gsi;
4542 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4543 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4544 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4545 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4546 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4547 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4548 OMP_CLAUSE_UNTIED) != NULL);
4550 FOR_EACH_BB_FN (bb, cfun)
4551 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4553 gimple call = gsi_stmt (gsi);
4554 tree decl;
4556 if (is_gimple_call (call)
4557 && (decl = gimple_call_fndecl (call))
4558 && DECL_EXTERNAL (decl)
4559 && TREE_PUBLIC (decl)
4560 && DECL_INITIAL (decl) == NULL)
4562 tree built_in;
4564 if (DECL_NAME (decl) == thr_num_id)
4566 /* In #pragma omp task untied omp_get_thread_num () can change
4567 during the execution of the task region. */
4568 if (untied_task)
4569 continue;
4570 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4572 else if (DECL_NAME (decl) == num_thr_id)
4573 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4574 else
4575 continue;
4577 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4578 || gimple_call_num_args (call) != 0)
4579 continue;
4581 if (flag_exceptions && !TREE_NOTHROW (decl))
4582 continue;
4584 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4585 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4586 TREE_TYPE (TREE_TYPE (built_in))))
4587 continue;
4589 gimple_call_set_fndecl (call, built_in);
4594 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4595 regimplified. */
4597 static tree
4598 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4600 tree t = *tp;
4602 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4603 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4604 return t;
4606 if (TREE_CODE (t) == ADDR_EXPR)
4607 recompute_tree_invariant_for_addr_expr (t);
4609 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4610 return NULL_TREE;
4613 /* Prepend TO = FROM assignment before *GSI_P. */
4615 static void
4616 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4618 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4619 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4620 true, GSI_SAME_STMT);
4621 gimple stmt = gimple_build_assign (to, from);
4622 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4623 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4624 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4626 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4627 gimple_regimplify_operands (stmt, &gsi);
4631 /* Expand the OpenMP parallel or task directive starting at REGION. */
4633 static void
4634 expand_omp_taskreg (struct omp_region *region)
4636 basic_block entry_bb, exit_bb, new_bb;
4637 struct function *child_cfun;
4638 tree child_fn, block, t;
4639 gimple_stmt_iterator gsi;
4640 gimple entry_stmt, stmt;
4641 edge e;
4642 vec<tree, va_gc> *ws_args;
4644 entry_stmt = last_stmt (region->entry);
4645 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4646 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4648 entry_bb = region->entry;
4649 exit_bb = region->exit;
4651 if (is_combined_parallel (region))
4652 ws_args = region->ws_args;
4653 else
4654 ws_args = NULL;
4656 if (child_cfun->cfg)
4658 /* Due to inlining, it may happen that we have already outlined
4659 the region, in which case all we need to do is make the
4660 sub-graph unreachable and emit the parallel call. */
4661 edge entry_succ_e, exit_succ_e;
4662 gimple_stmt_iterator gsi;
4664 entry_succ_e = single_succ_edge (entry_bb);
4666 gsi = gsi_last_bb (entry_bb);
4667 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4668 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4669 gsi_remove (&gsi, true);
4671 new_bb = entry_bb;
4672 if (exit_bb)
4674 exit_succ_e = single_succ_edge (exit_bb);
4675 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4677 remove_edge_and_dominated_blocks (entry_succ_e);
4679 else
4681 unsigned srcidx, dstidx, num;
4683 /* If the parallel region needs data sent from the parent
4684 function, then the very first statement (except possible
4685 tree profile counter updates) of the parallel body
4686 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4687 &.OMP_DATA_O is passed as an argument to the child function,
4688 we need to replace it with the argument as seen by the child
4689 function.
4691 In most cases, this will end up being the identity assignment
4692 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4693 a function call that has been inlined, the original PARM_DECL
4694 .OMP_DATA_I may have been converted into a different local
4695 variable. In which case, we need to keep the assignment. */
4696 if (gimple_omp_taskreg_data_arg (entry_stmt))
4698 basic_block entry_succ_bb = single_succ (entry_bb);
4699 gimple_stmt_iterator gsi;
4700 tree arg, narg;
4701 gimple parcopy_stmt = NULL;
4703 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4705 gimple stmt;
4707 gcc_assert (!gsi_end_p (gsi));
4708 stmt = gsi_stmt (gsi);
4709 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4710 continue;
4712 if (gimple_num_ops (stmt) == 2)
4714 tree arg = gimple_assign_rhs1 (stmt);
4716 /* We're ignore the subcode because we're
4717 effectively doing a STRIP_NOPS. */
4719 if (TREE_CODE (arg) == ADDR_EXPR
4720 && TREE_OPERAND (arg, 0)
4721 == gimple_omp_taskreg_data_arg (entry_stmt))
4723 parcopy_stmt = stmt;
4724 break;
4729 gcc_assert (parcopy_stmt != NULL);
4730 arg = DECL_ARGUMENTS (child_fn);
4732 if (!gimple_in_ssa_p (cfun))
4734 if (gimple_assign_lhs (parcopy_stmt) == arg)
4735 gsi_remove (&gsi, true);
4736 else
4738 /* ?? Is setting the subcode really necessary ?? */
4739 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
4740 gimple_assign_set_rhs1 (parcopy_stmt, arg);
4743 else
4745 /* If we are in ssa form, we must load the value from the default
4746 definition of the argument. That should not be defined now,
4747 since the argument is not used uninitialized. */
4748 gcc_assert (ssa_default_def (cfun, arg) == NULL);
4749 narg = make_ssa_name (arg, gimple_build_nop ());
4750 set_ssa_default_def (cfun, arg, narg);
4751 /* ?? Is setting the subcode really necessary ?? */
4752 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
4753 gimple_assign_set_rhs1 (parcopy_stmt, narg);
4754 update_stmt (parcopy_stmt);
4758 /* Declare local variables needed in CHILD_CFUN. */
4759 block = DECL_INITIAL (child_fn);
4760 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4761 /* The gimplifier could record temporaries in parallel/task block
4762 rather than in containing function's local_decls chain,
4763 which would mean cgraph missed finalizing them. Do it now. */
4764 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4765 if (TREE_CODE (t) == VAR_DECL
4766 && TREE_STATIC (t)
4767 && !DECL_EXTERNAL (t))
4768 varpool_finalize_decl (t);
4769 DECL_SAVED_TREE (child_fn) = NULL;
4770 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4771 gimple_set_body (child_fn, NULL);
4772 TREE_USED (block) = 1;
4774 /* Reset DECL_CONTEXT on function arguments. */
4775 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
4776 DECL_CONTEXT (t) = child_fn;
4778 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
4779 so that it can be moved to the child function. */
4780 gsi = gsi_last_bb (entry_bb);
4781 stmt = gsi_stmt (gsi);
4782 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
4783 || gimple_code (stmt) == GIMPLE_OMP_TASK));
4784 gsi_remove (&gsi, true);
4785 e = split_block (entry_bb, stmt);
4786 entry_bb = e->dest;
4787 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4789 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4790 if (exit_bb)
4792 gsi = gsi_last_bb (exit_bb);
4793 gcc_assert (!gsi_end_p (gsi)
4794 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4795 stmt = gimple_build_return (NULL);
4796 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4797 gsi_remove (&gsi, true);
4800 /* Move the parallel region into CHILD_CFUN. */
4802 if (gimple_in_ssa_p (cfun))
4804 init_tree_ssa (child_cfun);
4805 init_ssa_operands (child_cfun);
4806 child_cfun->gimple_df->in_ssa_p = true;
4807 block = NULL_TREE;
4809 else
4810 block = gimple_block (entry_stmt);
4812 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
4813 if (exit_bb)
4814 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
4815 /* When the OMP expansion process cannot guarantee an up-to-date
4816 loop tree arrange for the child function to fixup loops. */
4817 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
4818 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
4820 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
4821 num = vec_safe_length (child_cfun->local_decls);
4822 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
4824 t = (*child_cfun->local_decls)[srcidx];
4825 if (DECL_CONTEXT (t) == cfun->decl)
4826 continue;
4827 if (srcidx != dstidx)
4828 (*child_cfun->local_decls)[dstidx] = t;
4829 dstidx++;
4831 if (dstidx != num)
4832 vec_safe_truncate (child_cfun->local_decls, dstidx);
4834 /* Inform the callgraph about the new function. */
4835 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
4836 cgraph_add_new_function (child_fn, true);
4838 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4839 fixed in a following pass. */
4840 push_cfun (child_cfun);
4841 if (optimize)
4842 optimize_omp_library_calls (entry_stmt);
4843 rebuild_cgraph_edges ();
4845 /* Some EH regions might become dead, see PR34608. If
4846 pass_cleanup_cfg isn't the first pass to happen with the
4847 new child, these dead EH edges might cause problems.
4848 Clean them up now. */
4849 if (flag_exceptions)
4851 basic_block bb;
4852 bool changed = false;
4854 FOR_EACH_BB_FN (bb, cfun)
4855 changed |= gimple_purge_dead_eh_edges (bb);
4856 if (changed)
4857 cleanup_tree_cfg ();
4859 if (gimple_in_ssa_p (cfun))
4860 update_ssa (TODO_update_ssa);
4861 pop_cfun ();
4864 /* Emit a library call to launch the children threads. */
4865 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
4866 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
4867 else
4868 expand_task_call (new_bb, entry_stmt);
4869 if (gimple_in_ssa_p (cfun))
4870 update_ssa (TODO_update_ssa_only_virtuals);
4874 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4875 of the combined collapse > 1 loop constructs, generate code like:
4876 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4877 if (cond3 is <)
4878 adj = STEP3 - 1;
4879 else
4880 adj = STEP3 + 1;
4881 count3 = (adj + N32 - N31) / STEP3;
4882 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4883 if (cond2 is <)
4884 adj = STEP2 - 1;
4885 else
4886 adj = STEP2 + 1;
4887 count2 = (adj + N22 - N21) / STEP2;
4888 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4889 if (cond1 is <)
4890 adj = STEP1 - 1;
4891 else
4892 adj = STEP1 + 1;
4893 count1 = (adj + N12 - N11) / STEP1;
4894 count = count1 * count2 * count3;
4895 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4896 count = 0;
4897 and set ZERO_ITER_BB to that bb. If this isn't the outermost
4898 of the combined loop constructs, just initialize COUNTS array
4899 from the _looptemp_ clauses. */
4901 /* NOTE: It *could* be better to moosh all of the BBs together,
4902 creating one larger BB with all the computation and the unexpected
4903 jump at the end. I.e.
4905 bool zero3, zero2, zero1, zero;
4907 zero3 = N32 c3 N31;
4908 count3 = (N32 - N31) /[cl] STEP3;
4909 zero2 = N22 c2 N21;
4910 count2 = (N22 - N21) /[cl] STEP2;
4911 zero1 = N12 c1 N11;
4912 count1 = (N12 - N11) /[cl] STEP1;
4913 zero = zero3 || zero2 || zero1;
4914 count = count1 * count2 * count3;
4915 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4917 After all, we expect the zero=false, and thus we expect to have to
4918 evaluate all of the comparison expressions, so short-circuiting
4919 oughtn't be a win. Since the condition isn't protecting a
4920 denominator, we're not concerned about divide-by-zero, so we can
4921 fully evaluate count even if a numerator turned out to be wrong.
4923 It seems like putting this all together would create much better
4924 scheduling opportunities, and less pressure on the chip's branch
4925 predictor. */
4927 static void
4928 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4929 basic_block &entry_bb, tree *counts,
4930 basic_block &zero_iter_bb, int &first_zero_iter,
4931 basic_block &l2_dom_bb)
4933 tree t, type = TREE_TYPE (fd->loop.v);
4934 gimple stmt;
4935 edge e, ne;
4936 int i;
4938 /* Collapsed loops need work for expansion into SSA form. */
4939 gcc_assert (!gimple_in_ssa_p (cfun));
4941 if (gimple_omp_for_combined_into_p (fd->for_stmt)
4942 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
4944 /* First two _looptemp_ clauses are for istart/iend, counts[0]
4945 isn't supposed to be handled, as the inner loop doesn't
4946 use it. */
4947 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
4948 OMP_CLAUSE__LOOPTEMP_);
4949 gcc_assert (innerc);
4950 for (i = 0; i < fd->collapse; i++)
4952 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
4953 OMP_CLAUSE__LOOPTEMP_);
4954 gcc_assert (innerc);
4955 if (i)
4956 counts[i] = OMP_CLAUSE_DECL (innerc);
4957 else
4958 counts[0] = NULL_TREE;
4960 return;
4963 for (i = 0; i < fd->collapse; i++)
4965 tree itype = TREE_TYPE (fd->loops[i].v);
4967 if (SSA_VAR_P (fd->loop.n2)
4968 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
4969 fold_convert (itype, fd->loops[i].n1),
4970 fold_convert (itype, fd->loops[i].n2)))
4971 == NULL_TREE || !integer_onep (t)))
4973 tree n1, n2;
4974 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
4975 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
4976 true, GSI_SAME_STMT);
4977 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
4978 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
4979 true, GSI_SAME_STMT);
4980 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
4981 NULL_TREE, NULL_TREE);
4982 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4983 if (walk_tree (gimple_cond_lhs_ptr (stmt),
4984 expand_omp_regimplify_p, NULL, NULL)
4985 || walk_tree (gimple_cond_rhs_ptr (stmt),
4986 expand_omp_regimplify_p, NULL, NULL))
4988 *gsi = gsi_for_stmt (stmt);
4989 gimple_regimplify_operands (stmt, gsi);
4991 e = split_block (entry_bb, stmt);
4992 if (zero_iter_bb == NULL)
4994 first_zero_iter = i;
4995 zero_iter_bb = create_empty_bb (entry_bb);
4996 if (current_loops)
4997 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
4998 *gsi = gsi_after_labels (zero_iter_bb);
4999 stmt = gimple_build_assign (fd->loop.n2,
5000 build_zero_cst (type));
5001 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5002 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5003 entry_bb);
5005 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5006 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5007 e->flags = EDGE_TRUE_VALUE;
5008 e->probability = REG_BR_PROB_BASE - ne->probability;
5009 if (l2_dom_bb == NULL)
5010 l2_dom_bb = entry_bb;
5011 entry_bb = e->dest;
5012 *gsi = gsi_last_bb (entry_bb);
5015 if (POINTER_TYPE_P (itype))
5016 itype = signed_type_for (itype);
5017 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5018 ? -1 : 1));
5019 t = fold_build2 (PLUS_EXPR, itype,
5020 fold_convert (itype, fd->loops[i].step), t);
5021 t = fold_build2 (PLUS_EXPR, itype, t,
5022 fold_convert (itype, fd->loops[i].n2));
5023 t = fold_build2 (MINUS_EXPR, itype, t,
5024 fold_convert (itype, fd->loops[i].n1));
5025 /* ?? We could probably use CEIL_DIV_EXPR instead of
5026 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5027 generate the same code in the end because generically we
5028 don't know that the values involved must be negative for
5029 GT?? */
5030 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5031 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5032 fold_build1 (NEGATE_EXPR, itype, t),
5033 fold_build1 (NEGATE_EXPR, itype,
5034 fold_convert (itype,
5035 fd->loops[i].step)));
5036 else
5037 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5038 fold_convert (itype, fd->loops[i].step));
5039 t = fold_convert (type, t);
5040 if (TREE_CODE (t) == INTEGER_CST)
5041 counts[i] = t;
5042 else
5044 counts[i] = create_tmp_reg (type, ".count");
5045 expand_omp_build_assign (gsi, counts[i], t);
5047 if (SSA_VAR_P (fd->loop.n2))
5049 if (i == 0)
5050 t = counts[0];
5051 else
5052 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5053 expand_omp_build_assign (gsi, fd->loop.n2, t);
5059 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5060 T = V;
5061 V3 = N31 + (T % count3) * STEP3;
5062 T = T / count3;
5063 V2 = N21 + (T % count2) * STEP2;
5064 T = T / count2;
5065 V1 = N11 + T * STEP1;
5066 if this loop doesn't have an inner loop construct combined with it.
5067 If it does have an inner loop construct combined with it and the
5068 iteration count isn't known constant, store values from counts array
5069 into its _looptemp_ temporaries instead. */
5071 static void
5072 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5073 tree *counts, gimple inner_stmt, tree startvar)
5075 int i;
5076 if (gimple_omp_for_combined_p (fd->for_stmt))
5078 /* If fd->loop.n2 is constant, then no propagation of the counts
5079 is needed, they are constant. */
5080 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5081 return;
5083 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5084 ? gimple_omp_parallel_clauses (inner_stmt)
5085 : gimple_omp_for_clauses (inner_stmt);
5086 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5087 isn't supposed to be handled, as the inner loop doesn't
5088 use it. */
5089 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5090 gcc_assert (innerc);
5091 for (i = 0; i < fd->collapse; i++)
5093 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5094 OMP_CLAUSE__LOOPTEMP_);
5095 gcc_assert (innerc);
5096 if (i)
5098 tree tem = OMP_CLAUSE_DECL (innerc);
5099 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5100 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5101 false, GSI_CONTINUE_LINKING);
5102 gimple stmt = gimple_build_assign (tem, t);
5103 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5106 return;
5109 tree type = TREE_TYPE (fd->loop.v);
5110 tree tem = create_tmp_reg (type, ".tem");
5111 gimple stmt = gimple_build_assign (tem, startvar);
5112 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5114 for (i = fd->collapse - 1; i >= 0; i--)
5116 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5117 itype = vtype;
5118 if (POINTER_TYPE_P (vtype))
5119 itype = signed_type_for (vtype);
5120 if (i != 0)
5121 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5122 else
5123 t = tem;
5124 t = fold_convert (itype, t);
5125 t = fold_build2 (MULT_EXPR, itype, t,
5126 fold_convert (itype, fd->loops[i].step));
5127 if (POINTER_TYPE_P (vtype))
5128 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5129 else
5130 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5131 t = force_gimple_operand_gsi (gsi, t,
5132 DECL_P (fd->loops[i].v)
5133 && TREE_ADDRESSABLE (fd->loops[i].v),
5134 NULL_TREE, false,
5135 GSI_CONTINUE_LINKING);
5136 stmt = gimple_build_assign (fd->loops[i].v, t);
5137 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5138 if (i != 0)
5140 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5141 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5142 false, GSI_CONTINUE_LINKING);
5143 stmt = gimple_build_assign (tem, t);
5144 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5150 /* Helper function for expand_omp_for_*. Generate code like:
5151 L10:
5152 V3 += STEP3;
5153 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5154 L11:
5155 V3 = N31;
5156 V2 += STEP2;
5157 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5158 L12:
5159 V2 = N21;
5160 V1 += STEP1;
5161 goto BODY_BB; */
5163 static basic_block
5164 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5165 basic_block body_bb)
5167 basic_block last_bb, bb, collapse_bb = NULL;
5168 int i;
5169 gimple_stmt_iterator gsi;
5170 edge e;
5171 tree t;
5172 gimple stmt;
5174 last_bb = cont_bb;
5175 for (i = fd->collapse - 1; i >= 0; i--)
5177 tree vtype = TREE_TYPE (fd->loops[i].v);
5179 bb = create_empty_bb (last_bb);
5180 if (current_loops)
5181 add_bb_to_loop (bb, last_bb->loop_father);
5182 gsi = gsi_start_bb (bb);
5184 if (i < fd->collapse - 1)
5186 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5187 e->probability = REG_BR_PROB_BASE / 8;
5189 t = fd->loops[i + 1].n1;
5190 t = force_gimple_operand_gsi (&gsi, t,
5191 DECL_P (fd->loops[i + 1].v)
5192 && TREE_ADDRESSABLE (fd->loops[i
5193 + 1].v),
5194 NULL_TREE, false,
5195 GSI_CONTINUE_LINKING);
5196 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5197 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5199 else
5200 collapse_bb = bb;
5202 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5204 if (POINTER_TYPE_P (vtype))
5205 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5206 else
5207 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5208 t = force_gimple_operand_gsi (&gsi, t,
5209 DECL_P (fd->loops[i].v)
5210 && TREE_ADDRESSABLE (fd->loops[i].v),
5211 NULL_TREE, false, GSI_CONTINUE_LINKING);
5212 stmt = gimple_build_assign (fd->loops[i].v, t);
5213 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5215 if (i > 0)
5217 t = fd->loops[i].n2;
5218 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5219 false, GSI_CONTINUE_LINKING);
5220 tree v = fd->loops[i].v;
5221 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5222 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5223 false, GSI_CONTINUE_LINKING);
5224 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5225 stmt = gimple_build_cond_empty (t);
5226 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5227 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5228 e->probability = REG_BR_PROB_BASE * 7 / 8;
5230 else
5231 make_edge (bb, body_bb, EDGE_FALLTHRU);
5232 last_bb = bb;
5235 return collapse_bb;
5239 /* A subroutine of expand_omp_for. Generate code for a parallel
5240 loop with any schedule. Given parameters:
5242 for (V = N1; V cond N2; V += STEP) BODY;
5244 where COND is "<" or ">", we generate pseudocode
5246 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5247 if (more) goto L0; else goto L3;
5249 V = istart0;
5250 iend = iend0;
5252 BODY;
5253 V += STEP;
5254 if (V cond iend) goto L1; else goto L2;
5256 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5259 If this is a combined omp parallel loop, instead of the call to
5260 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5261 If this is gimple_omp_for_combined_p loop, then instead of assigning
5262 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5263 inner GIMPLE_OMP_FOR and V += STEP; and
5264 if (V cond iend) goto L1; else goto L2; are removed.
5266 For collapsed loops, given parameters:
5267 collapse(3)
5268 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5269 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5270 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5271 BODY;
5273 we generate pseudocode
5275 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5276 if (cond3 is <)
5277 adj = STEP3 - 1;
5278 else
5279 adj = STEP3 + 1;
5280 count3 = (adj + N32 - N31) / STEP3;
5281 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5282 if (cond2 is <)
5283 adj = STEP2 - 1;
5284 else
5285 adj = STEP2 + 1;
5286 count2 = (adj + N22 - N21) / STEP2;
5287 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5288 if (cond1 is <)
5289 adj = STEP1 - 1;
5290 else
5291 adj = STEP1 + 1;
5292 count1 = (adj + N12 - N11) / STEP1;
5293 count = count1 * count2 * count3;
5294 goto Z1;
5296 count = 0;
5298 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5299 if (more) goto L0; else goto L3;
5301 V = istart0;
5302 T = V;
5303 V3 = N31 + (T % count3) * STEP3;
5304 T = T / count3;
5305 V2 = N21 + (T % count2) * STEP2;
5306 T = T / count2;
5307 V1 = N11 + T * STEP1;
5308 iend = iend0;
5310 BODY;
5311 V += 1;
5312 if (V < iend) goto L10; else goto L2;
5313 L10:
5314 V3 += STEP3;
5315 if (V3 cond3 N32) goto L1; else goto L11;
5316 L11:
5317 V3 = N31;
5318 V2 += STEP2;
5319 if (V2 cond2 N22) goto L1; else goto L12;
5320 L12:
5321 V2 = N21;
5322 V1 += STEP1;
5323 goto L1;
5325 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5330 static void
5331 expand_omp_for_generic (struct omp_region *region,
5332 struct omp_for_data *fd,
5333 enum built_in_function start_fn,
5334 enum built_in_function next_fn,
5335 gimple inner_stmt)
5337 tree type, istart0, iend0, iend;
5338 tree t, vmain, vback, bias = NULL_TREE;
5339 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5340 basic_block l2_bb = NULL, l3_bb = NULL;
5341 gimple_stmt_iterator gsi;
5342 gimple stmt;
5343 bool in_combined_parallel = is_combined_parallel (region);
5344 bool broken_loop = region->cont == NULL;
5345 edge e, ne;
5346 tree *counts = NULL;
5347 int i;
5349 gcc_assert (!broken_loop || !in_combined_parallel);
5350 gcc_assert (fd->iter_type == long_integer_type_node
5351 || !in_combined_parallel);
5353 type = TREE_TYPE (fd->loop.v);
5354 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5355 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5356 TREE_ADDRESSABLE (istart0) = 1;
5357 TREE_ADDRESSABLE (iend0) = 1;
5359 /* See if we need to bias by LLONG_MIN. */
5360 if (fd->iter_type == long_long_unsigned_type_node
5361 && TREE_CODE (type) == INTEGER_TYPE
5362 && !TYPE_UNSIGNED (type))
5364 tree n1, n2;
5366 if (fd->loop.cond_code == LT_EXPR)
5368 n1 = fd->loop.n1;
5369 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5371 else
5373 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5374 n2 = fd->loop.n1;
5376 if (TREE_CODE (n1) != INTEGER_CST
5377 || TREE_CODE (n2) != INTEGER_CST
5378 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5379 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5382 entry_bb = region->entry;
5383 cont_bb = region->cont;
5384 collapse_bb = NULL;
5385 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5386 gcc_assert (broken_loop
5387 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5388 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5389 l1_bb = single_succ (l0_bb);
5390 if (!broken_loop)
5392 l2_bb = create_empty_bb (cont_bb);
5393 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5394 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5396 else
5397 l2_bb = NULL;
5398 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5399 exit_bb = region->exit;
5401 gsi = gsi_last_bb (entry_bb);
5403 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5404 if (fd->collapse > 1)
5406 int first_zero_iter = -1;
5407 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5409 counts = XALLOCAVEC (tree, fd->collapse);
5410 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5411 zero_iter_bb, first_zero_iter,
5412 l2_dom_bb);
5414 if (zero_iter_bb)
5416 /* Some counts[i] vars might be uninitialized if
5417 some loop has zero iterations. But the body shouldn't
5418 be executed in that case, so just avoid uninit warnings. */
5419 for (i = first_zero_iter; i < fd->collapse; i++)
5420 if (SSA_VAR_P (counts[i]))
5421 TREE_NO_WARNING (counts[i]) = 1;
5422 gsi_prev (&gsi);
5423 e = split_block (entry_bb, gsi_stmt (gsi));
5424 entry_bb = e->dest;
5425 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5426 gsi = gsi_last_bb (entry_bb);
5427 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5428 get_immediate_dominator (CDI_DOMINATORS,
5429 zero_iter_bb));
5432 if (in_combined_parallel)
5434 /* In a combined parallel loop, emit a call to
5435 GOMP_loop_foo_next. */
5436 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5437 build_fold_addr_expr (istart0),
5438 build_fold_addr_expr (iend0));
5440 else
5442 tree t0, t1, t2, t3, t4;
5443 /* If this is not a combined parallel loop, emit a call to
5444 GOMP_loop_foo_start in ENTRY_BB. */
5445 t4 = build_fold_addr_expr (iend0);
5446 t3 = build_fold_addr_expr (istart0);
5447 t2 = fold_convert (fd->iter_type, fd->loop.step);
5448 t1 = fd->loop.n2;
5449 t0 = fd->loop.n1;
5450 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5452 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5453 OMP_CLAUSE__LOOPTEMP_);
5454 gcc_assert (innerc);
5455 t0 = OMP_CLAUSE_DECL (innerc);
5456 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5457 OMP_CLAUSE__LOOPTEMP_);
5458 gcc_assert (innerc);
5459 t1 = OMP_CLAUSE_DECL (innerc);
5461 if (POINTER_TYPE_P (TREE_TYPE (t0))
5462 && TYPE_PRECISION (TREE_TYPE (t0))
5463 != TYPE_PRECISION (fd->iter_type))
5465 /* Avoid casting pointers to integer of a different size. */
5466 tree itype = signed_type_for (type);
5467 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5468 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5470 else
5472 t1 = fold_convert (fd->iter_type, t1);
5473 t0 = fold_convert (fd->iter_type, t0);
5475 if (bias)
5477 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5478 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5480 if (fd->iter_type == long_integer_type_node)
5482 if (fd->chunk_size)
5484 t = fold_convert (fd->iter_type, fd->chunk_size);
5485 t = build_call_expr (builtin_decl_explicit (start_fn),
5486 6, t0, t1, t2, t, t3, t4);
5488 else
5489 t = build_call_expr (builtin_decl_explicit (start_fn),
5490 5, t0, t1, t2, t3, t4);
5492 else
5494 tree t5;
5495 tree c_bool_type;
5496 tree bfn_decl;
5498 /* The GOMP_loop_ull_*start functions have additional boolean
5499 argument, true for < loops and false for > loops.
5500 In Fortran, the C bool type can be different from
5501 boolean_type_node. */
5502 bfn_decl = builtin_decl_explicit (start_fn);
5503 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5504 t5 = build_int_cst (c_bool_type,
5505 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5506 if (fd->chunk_size)
5508 tree bfn_decl = builtin_decl_explicit (start_fn);
5509 t = fold_convert (fd->iter_type, fd->chunk_size);
5510 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5512 else
5513 t = build_call_expr (builtin_decl_explicit (start_fn),
5514 6, t5, t0, t1, t2, t3, t4);
5517 if (TREE_TYPE (t) != boolean_type_node)
5518 t = fold_build2 (NE_EXPR, boolean_type_node,
5519 t, build_int_cst (TREE_TYPE (t), 0));
5520 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5521 true, GSI_SAME_STMT);
5522 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5524 /* Remove the GIMPLE_OMP_FOR statement. */
5525 gsi_remove (&gsi, true);
5527 /* Iteration setup for sequential loop goes in L0_BB. */
5528 tree startvar = fd->loop.v;
5529 tree endvar = NULL_TREE;
5531 if (gimple_omp_for_combined_p (fd->for_stmt))
5533 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5534 && gimple_omp_for_kind (inner_stmt)
5535 == GF_OMP_FOR_KIND_SIMD);
5536 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5537 OMP_CLAUSE__LOOPTEMP_);
5538 gcc_assert (innerc);
5539 startvar = OMP_CLAUSE_DECL (innerc);
5540 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5541 OMP_CLAUSE__LOOPTEMP_);
5542 gcc_assert (innerc);
5543 endvar = OMP_CLAUSE_DECL (innerc);
5546 gsi = gsi_start_bb (l0_bb);
5547 t = istart0;
5548 if (bias)
5549 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5550 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5551 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5552 t = fold_convert (TREE_TYPE (startvar), t);
5553 t = force_gimple_operand_gsi (&gsi, t,
5554 DECL_P (startvar)
5555 && TREE_ADDRESSABLE (startvar),
5556 NULL_TREE, false, GSI_CONTINUE_LINKING);
5557 stmt = gimple_build_assign (startvar, t);
5558 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5560 t = iend0;
5561 if (bias)
5562 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5563 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5564 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5565 t = fold_convert (TREE_TYPE (startvar), t);
5566 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5567 false, GSI_CONTINUE_LINKING);
5568 if (endvar)
5570 stmt = gimple_build_assign (endvar, iend);
5571 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5573 if (fd->collapse > 1)
5574 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5576 if (!broken_loop)
5578 /* Code to control the increment and predicate for the sequential
5579 loop goes in the CONT_BB. */
5580 gsi = gsi_last_bb (cont_bb);
5581 stmt = gsi_stmt (gsi);
5582 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5583 vmain = gimple_omp_continue_control_use (stmt);
5584 vback = gimple_omp_continue_control_def (stmt);
5586 if (!gimple_omp_for_combined_p (fd->for_stmt))
5588 if (POINTER_TYPE_P (type))
5589 t = fold_build_pointer_plus (vmain, fd->loop.step);
5590 else
5591 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5592 t = force_gimple_operand_gsi (&gsi, t,
5593 DECL_P (vback)
5594 && TREE_ADDRESSABLE (vback),
5595 NULL_TREE, true, GSI_SAME_STMT);
5596 stmt = gimple_build_assign (vback, t);
5597 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5599 t = build2 (fd->loop.cond_code, boolean_type_node,
5600 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5601 iend);
5602 stmt = gimple_build_cond_empty (t);
5603 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5606 /* Remove GIMPLE_OMP_CONTINUE. */
5607 gsi_remove (&gsi, true);
5609 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5610 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5612 /* Emit code to get the next parallel iteration in L2_BB. */
5613 gsi = gsi_start_bb (l2_bb);
5615 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5616 build_fold_addr_expr (istart0),
5617 build_fold_addr_expr (iend0));
5618 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5619 false, GSI_CONTINUE_LINKING);
5620 if (TREE_TYPE (t) != boolean_type_node)
5621 t = fold_build2 (NE_EXPR, boolean_type_node,
5622 t, build_int_cst (TREE_TYPE (t), 0));
5623 stmt = gimple_build_cond_empty (t);
5624 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5627 /* Add the loop cleanup function. */
5628 gsi = gsi_last_bb (exit_bb);
5629 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5630 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5631 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5632 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5633 else
5634 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5635 stmt = gimple_build_call (t, 0);
5636 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5637 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5638 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5639 gsi_remove (&gsi, true);
5641 /* Connect the new blocks. */
5642 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5643 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5645 if (!broken_loop)
5647 gimple_seq phis;
5649 e = find_edge (cont_bb, l3_bb);
5650 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5652 phis = phi_nodes (l3_bb);
5653 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5655 gimple phi = gsi_stmt (gsi);
5656 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5657 PHI_ARG_DEF_FROM_EDGE (phi, e));
5659 remove_edge (e);
5661 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5662 if (current_loops)
5663 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5664 e = find_edge (cont_bb, l1_bb);
5665 if (gimple_omp_for_combined_p (fd->for_stmt))
5667 remove_edge (e);
5668 e = NULL;
5670 else if (fd->collapse > 1)
5672 remove_edge (e);
5673 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5675 else
5676 e->flags = EDGE_TRUE_VALUE;
5677 if (e)
5679 e->probability = REG_BR_PROB_BASE * 7 / 8;
5680 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5682 else
5684 e = find_edge (cont_bb, l2_bb);
5685 e->flags = EDGE_FALLTHRU;
5687 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5689 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5690 recompute_dominator (CDI_DOMINATORS, l2_bb));
5691 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5692 recompute_dominator (CDI_DOMINATORS, l3_bb));
5693 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5694 recompute_dominator (CDI_DOMINATORS, l0_bb));
5695 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5696 recompute_dominator (CDI_DOMINATORS, l1_bb));
5698 struct loop *outer_loop = alloc_loop ();
5699 outer_loop->header = l0_bb;
5700 outer_loop->latch = l2_bb;
5701 add_loop (outer_loop, l0_bb->loop_father);
5703 if (!gimple_omp_for_combined_p (fd->for_stmt))
5705 struct loop *loop = alloc_loop ();
5706 loop->header = l1_bb;
5707 /* The loop may have multiple latches. */
5708 add_loop (loop, outer_loop);
5714 /* A subroutine of expand_omp_for. Generate code for a parallel
5715 loop with static schedule and no specified chunk size. Given
5716 parameters:
5718 for (V = N1; V cond N2; V += STEP) BODY;
5720 where COND is "<" or ">", we generate pseudocode
5722 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5723 if (cond is <)
5724 adj = STEP - 1;
5725 else
5726 adj = STEP + 1;
5727 if ((__typeof (V)) -1 > 0 && cond is >)
5728 n = -(adj + N2 - N1) / -STEP;
5729 else
5730 n = (adj + N2 - N1) / STEP;
5731 q = n / nthreads;
5732 tt = n % nthreads;
5733 if (threadid < tt) goto L3; else goto L4;
5735 tt = 0;
5736 q = q + 1;
5738 s0 = q * threadid + tt;
5739 e0 = s0 + q;
5740 V = s0 * STEP + N1;
5741 if (s0 >= e0) goto L2; else goto L0;
5743 e = e0 * STEP + N1;
5745 BODY;
5746 V += STEP;
5747 if (V cond e) goto L1;
5751 static void
5752 expand_omp_for_static_nochunk (struct omp_region *region,
5753 struct omp_for_data *fd,
5754 gimple inner_stmt)
5756 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
5757 tree type, itype, vmain, vback;
5758 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
5759 basic_block body_bb, cont_bb, collapse_bb = NULL;
5760 basic_block fin_bb;
5761 gimple_stmt_iterator gsi;
5762 gimple stmt;
5763 edge ep;
5764 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
5765 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
5766 bool broken_loop = region->cont == NULL;
5767 tree *counts = NULL;
5768 tree n1, n2, step;
5770 itype = type = TREE_TYPE (fd->loop.v);
5771 if (POINTER_TYPE_P (type))
5772 itype = signed_type_for (type);
5774 entry_bb = region->entry;
5775 cont_bb = region->cont;
5776 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5777 fin_bb = BRANCH_EDGE (entry_bb)->dest;
5778 gcc_assert (broken_loop
5779 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
5780 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5781 body_bb = single_succ (seq_start_bb);
5782 if (!broken_loop)
5784 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
5785 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5787 exit_bb = region->exit;
5789 /* Iteration space partitioning goes in ENTRY_BB. */
5790 gsi = gsi_last_bb (entry_bb);
5791 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5793 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
5795 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
5796 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
5799 if (fd->collapse > 1)
5801 int first_zero_iter = -1;
5802 basic_block l2_dom_bb = NULL;
5804 counts = XALLOCAVEC (tree, fd->collapse);
5805 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5806 fin_bb, first_zero_iter,
5807 l2_dom_bb);
5808 t = NULL_TREE;
5810 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
5811 t = integer_one_node;
5812 else
5813 t = fold_binary (fd->loop.cond_code, boolean_type_node,
5814 fold_convert (type, fd->loop.n1),
5815 fold_convert (type, fd->loop.n2));
5816 if (fd->collapse == 1
5817 && TYPE_UNSIGNED (type)
5818 && (t == NULL_TREE || !integer_onep (t)))
5820 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5821 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5822 true, GSI_SAME_STMT);
5823 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5824 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5825 true, GSI_SAME_STMT);
5826 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
5827 NULL_TREE, NULL_TREE);
5828 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5829 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5830 expand_omp_regimplify_p, NULL, NULL)
5831 || walk_tree (gimple_cond_rhs_ptr (stmt),
5832 expand_omp_regimplify_p, NULL, NULL))
5834 gsi = gsi_for_stmt (stmt);
5835 gimple_regimplify_operands (stmt, &gsi);
5837 ep = split_block (entry_bb, stmt);
5838 ep->flags = EDGE_TRUE_VALUE;
5839 entry_bb = ep->dest;
5840 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
5841 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
5842 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
5843 if (gimple_in_ssa_p (cfun))
5845 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
5846 for (gsi = gsi_start_phis (fin_bb);
5847 !gsi_end_p (gsi); gsi_next (&gsi))
5849 gimple phi = gsi_stmt (gsi);
5850 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
5851 ep, UNKNOWN_LOCATION);
5854 gsi = gsi_last_bb (entry_bb);
5857 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
5858 t = fold_convert (itype, t);
5859 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5860 true, GSI_SAME_STMT);
5862 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
5863 t = fold_convert (itype, t);
5864 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5865 true, GSI_SAME_STMT);
5867 n1 = fd->loop.n1;
5868 n2 = fd->loop.n2;
5869 step = fd->loop.step;
5870 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5872 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5873 OMP_CLAUSE__LOOPTEMP_);
5874 gcc_assert (innerc);
5875 n1 = OMP_CLAUSE_DECL (innerc);
5876 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5877 OMP_CLAUSE__LOOPTEMP_);
5878 gcc_assert (innerc);
5879 n2 = OMP_CLAUSE_DECL (innerc);
5881 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
5882 true, NULL_TREE, true, GSI_SAME_STMT);
5883 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
5884 true, NULL_TREE, true, GSI_SAME_STMT);
5885 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
5886 true, NULL_TREE, true, GSI_SAME_STMT);
5888 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
5889 t = fold_build2 (PLUS_EXPR, itype, step, t);
5890 t = fold_build2 (PLUS_EXPR, itype, t, n2);
5891 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
5892 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
5893 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5894 fold_build1 (NEGATE_EXPR, itype, t),
5895 fold_build1 (NEGATE_EXPR, itype, step));
5896 else
5897 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
5898 t = fold_convert (itype, t);
5899 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5901 q = create_tmp_reg (itype, "q");
5902 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
5903 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5904 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
5906 tt = create_tmp_reg (itype, "tt");
5907 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
5908 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5909 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
5911 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
5912 stmt = gimple_build_cond_empty (t);
5913 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5915 second_bb = split_block (entry_bb, stmt)->dest;
5916 gsi = gsi_last_bb (second_bb);
5917 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5919 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
5920 GSI_SAME_STMT);
5921 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
5922 build_int_cst (itype, 1));
5923 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5925 third_bb = split_block (second_bb, stmt)->dest;
5926 gsi = gsi_last_bb (third_bb);
5927 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5929 t = build2 (MULT_EXPR, itype, q, threadid);
5930 t = build2 (PLUS_EXPR, itype, t, tt);
5931 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5933 t = fold_build2 (PLUS_EXPR, itype, s0, q);
5934 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5936 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
5937 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5939 /* Remove the GIMPLE_OMP_FOR statement. */
5940 gsi_remove (&gsi, true);
5942 /* Setup code for sequential iteration goes in SEQ_START_BB. */
5943 gsi = gsi_start_bb (seq_start_bb);
5945 tree startvar = fd->loop.v;
5946 tree endvar = NULL_TREE;
5948 if (gimple_omp_for_combined_p (fd->for_stmt))
5950 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5951 ? gimple_omp_parallel_clauses (inner_stmt)
5952 : gimple_omp_for_clauses (inner_stmt);
5953 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5954 gcc_assert (innerc);
5955 startvar = OMP_CLAUSE_DECL (innerc);
5956 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5957 OMP_CLAUSE__LOOPTEMP_);
5958 gcc_assert (innerc);
5959 endvar = OMP_CLAUSE_DECL (innerc);
5961 t = fold_convert (itype, s0);
5962 t = fold_build2 (MULT_EXPR, itype, t, step);
5963 if (POINTER_TYPE_P (type))
5964 t = fold_build_pointer_plus (n1, t);
5965 else
5966 t = fold_build2 (PLUS_EXPR, type, t, n1);
5967 t = fold_convert (TREE_TYPE (startvar), t);
5968 t = force_gimple_operand_gsi (&gsi, t,
5969 DECL_P (startvar)
5970 && TREE_ADDRESSABLE (startvar),
5971 NULL_TREE, false, GSI_CONTINUE_LINKING);
5972 stmt = gimple_build_assign (startvar, t);
5973 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5975 t = fold_convert (itype, e0);
5976 t = fold_build2 (MULT_EXPR, itype, t, step);
5977 if (POINTER_TYPE_P (type))
5978 t = fold_build_pointer_plus (n1, t);
5979 else
5980 t = fold_build2 (PLUS_EXPR, type, t, n1);
5981 t = fold_convert (TREE_TYPE (startvar), t);
5982 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5983 false, GSI_CONTINUE_LINKING);
5984 if (endvar)
5986 stmt = gimple_build_assign (endvar, e);
5987 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5989 if (fd->collapse > 1)
5990 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5992 if (!broken_loop)
5994 /* The code controlling the sequential loop replaces the
5995 GIMPLE_OMP_CONTINUE. */
5996 gsi = gsi_last_bb (cont_bb);
5997 stmt = gsi_stmt (gsi);
5998 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5999 vmain = gimple_omp_continue_control_use (stmt);
6000 vback = gimple_omp_continue_control_def (stmt);
6002 if (!gimple_omp_for_combined_p (fd->for_stmt))
6004 if (POINTER_TYPE_P (type))
6005 t = fold_build_pointer_plus (vmain, step);
6006 else
6007 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6008 t = force_gimple_operand_gsi (&gsi, t,
6009 DECL_P (vback)
6010 && TREE_ADDRESSABLE (vback),
6011 NULL_TREE, true, GSI_SAME_STMT);
6012 stmt = gimple_build_assign (vback, t);
6013 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6015 t = build2 (fd->loop.cond_code, boolean_type_node,
6016 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6017 ? t : vback, e);
6018 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6021 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6022 gsi_remove (&gsi, true);
6024 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6025 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6028 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6029 gsi = gsi_last_bb (exit_bb);
6030 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6032 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6033 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6035 gsi_remove (&gsi, true);
6037 /* Connect all the blocks. */
6038 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6039 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6040 ep = find_edge (entry_bb, second_bb);
6041 ep->flags = EDGE_TRUE_VALUE;
6042 ep->probability = REG_BR_PROB_BASE / 4;
6043 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6044 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6046 if (!broken_loop)
6048 ep = find_edge (cont_bb, body_bb);
6049 if (gimple_omp_for_combined_p (fd->for_stmt))
6051 remove_edge (ep);
6052 ep = NULL;
6054 else if (fd->collapse > 1)
6056 remove_edge (ep);
6057 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6059 else
6060 ep->flags = EDGE_TRUE_VALUE;
6061 find_edge (cont_bb, fin_bb)->flags
6062 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6065 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6066 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6067 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6069 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6070 recompute_dominator (CDI_DOMINATORS, body_bb));
6071 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6072 recompute_dominator (CDI_DOMINATORS, fin_bb));
6074 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6076 struct loop *loop = alloc_loop ();
6077 loop->header = body_bb;
6078 if (collapse_bb == NULL)
6079 loop->latch = cont_bb;
6080 add_loop (loop, body_bb->loop_father);
6085 /* A subroutine of expand_omp_for. Generate code for a parallel
6086 loop with static schedule and a specified chunk size. Given
6087 parameters:
6089 for (V = N1; V cond N2; V += STEP) BODY;
6091 where COND is "<" or ">", we generate pseudocode
6093 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6094 if (cond is <)
6095 adj = STEP - 1;
6096 else
6097 adj = STEP + 1;
6098 if ((__typeof (V)) -1 > 0 && cond is >)
6099 n = -(adj + N2 - N1) / -STEP;
6100 else
6101 n = (adj + N2 - N1) / STEP;
6102 trip = 0;
6103 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6104 here so that V is defined
6105 if the loop is not entered
6107 s0 = (trip * nthreads + threadid) * CHUNK;
6108 e0 = min(s0 + CHUNK, n);
6109 if (s0 < n) goto L1; else goto L4;
6111 V = s0 * STEP + N1;
6112 e = e0 * STEP + N1;
6114 BODY;
6115 V += STEP;
6116 if (V cond e) goto L2; else goto L3;
6118 trip += 1;
6119 goto L0;
6123 static void
6124 expand_omp_for_static_chunk (struct omp_region *region,
6125 struct omp_for_data *fd, gimple inner_stmt)
6127 tree n, s0, e0, e, t;
6128 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6129 tree type, itype, v_main, v_back, v_extra;
6130 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6131 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6132 gimple_stmt_iterator si;
6133 gimple stmt;
6134 edge se;
6135 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6136 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6137 bool broken_loop = region->cont == NULL;
6138 tree *counts = NULL;
6139 tree n1, n2, step;
6141 itype = type = TREE_TYPE (fd->loop.v);
6142 if (POINTER_TYPE_P (type))
6143 itype = signed_type_for (type);
6145 entry_bb = region->entry;
6146 se = split_block (entry_bb, last_stmt (entry_bb));
6147 entry_bb = se->src;
6148 iter_part_bb = se->dest;
6149 cont_bb = region->cont;
6150 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6151 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6152 gcc_assert (broken_loop
6153 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6154 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6155 body_bb = single_succ (seq_start_bb);
6156 if (!broken_loop)
6158 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6159 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6160 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6162 exit_bb = region->exit;
6164 /* Trip and adjustment setup goes in ENTRY_BB. */
6165 si = gsi_last_bb (entry_bb);
6166 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
6168 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6170 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6171 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6174 if (fd->collapse > 1)
6176 int first_zero_iter = -1;
6177 basic_block l2_dom_bb = NULL;
6179 counts = XALLOCAVEC (tree, fd->collapse);
6180 expand_omp_for_init_counts (fd, &si, entry_bb, counts,
6181 fin_bb, first_zero_iter,
6182 l2_dom_bb);
6183 t = NULL_TREE;
6185 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6186 t = integer_one_node;
6187 else
6188 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6189 fold_convert (type, fd->loop.n1),
6190 fold_convert (type, fd->loop.n2));
6191 if (fd->collapse == 1
6192 && TYPE_UNSIGNED (type)
6193 && (t == NULL_TREE || !integer_onep (t)))
6195 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6196 n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
6197 true, GSI_SAME_STMT);
6198 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6199 n2 = force_gimple_operand_gsi (&si, n2, true, NULL_TREE,
6200 true, GSI_SAME_STMT);
6201 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6202 NULL_TREE, NULL_TREE);
6203 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6204 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6205 expand_omp_regimplify_p, NULL, NULL)
6206 || walk_tree (gimple_cond_rhs_ptr (stmt),
6207 expand_omp_regimplify_p, NULL, NULL))
6209 si = gsi_for_stmt (stmt);
6210 gimple_regimplify_operands (stmt, &si);
6212 se = split_block (entry_bb, stmt);
6213 se->flags = EDGE_TRUE_VALUE;
6214 entry_bb = se->dest;
6215 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6216 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6217 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6218 if (gimple_in_ssa_p (cfun))
6220 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6221 for (si = gsi_start_phis (fin_bb);
6222 !gsi_end_p (si); gsi_next (&si))
6224 gimple phi = gsi_stmt (si);
6225 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6226 se, UNKNOWN_LOCATION);
6229 si = gsi_last_bb (entry_bb);
6232 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6233 t = fold_convert (itype, t);
6234 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6235 true, GSI_SAME_STMT);
6237 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6238 t = fold_convert (itype, t);
6239 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6240 true, GSI_SAME_STMT);
6242 n1 = fd->loop.n1;
6243 n2 = fd->loop.n2;
6244 step = fd->loop.step;
6245 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6247 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6248 OMP_CLAUSE__LOOPTEMP_);
6249 gcc_assert (innerc);
6250 n1 = OMP_CLAUSE_DECL (innerc);
6251 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6252 OMP_CLAUSE__LOOPTEMP_);
6253 gcc_assert (innerc);
6254 n2 = OMP_CLAUSE_DECL (innerc);
6256 n1 = force_gimple_operand_gsi (&si, fold_convert (type, n1),
6257 true, NULL_TREE, true, GSI_SAME_STMT);
6258 n2 = force_gimple_operand_gsi (&si, fold_convert (itype, n2),
6259 true, NULL_TREE, true, GSI_SAME_STMT);
6260 step = force_gimple_operand_gsi (&si, fold_convert (itype, step),
6261 true, NULL_TREE, true, GSI_SAME_STMT);
6262 fd->chunk_size
6263 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
6264 true, NULL_TREE, true, GSI_SAME_STMT);
6266 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6267 t = fold_build2 (PLUS_EXPR, itype, step, t);
6268 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6269 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6270 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6271 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6272 fold_build1 (NEGATE_EXPR, itype, t),
6273 fold_build1 (NEGATE_EXPR, itype, step));
6274 else
6275 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6276 t = fold_convert (itype, t);
6277 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6278 true, GSI_SAME_STMT);
6280 trip_var = create_tmp_reg (itype, ".trip");
6281 if (gimple_in_ssa_p (cfun))
6283 trip_init = make_ssa_name (trip_var, NULL);
6284 trip_main = make_ssa_name (trip_var, NULL);
6285 trip_back = make_ssa_name (trip_var, NULL);
6287 else
6289 trip_init = trip_var;
6290 trip_main = trip_var;
6291 trip_back = trip_var;
6294 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6295 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6297 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6298 t = fold_build2 (MULT_EXPR, itype, t, step);
6299 if (POINTER_TYPE_P (type))
6300 t = fold_build_pointer_plus (n1, t);
6301 else
6302 t = fold_build2 (PLUS_EXPR, type, t, n1);
6303 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6304 true, GSI_SAME_STMT);
6306 /* Remove the GIMPLE_OMP_FOR. */
6307 gsi_remove (&si, true);
6309 /* Iteration space partitioning goes in ITER_PART_BB. */
6310 si = gsi_last_bb (iter_part_bb);
6312 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6313 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6314 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6315 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6316 false, GSI_CONTINUE_LINKING);
6318 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6319 t = fold_build2 (MIN_EXPR, itype, t, n);
6320 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6321 false, GSI_CONTINUE_LINKING);
6323 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6324 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6326 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6327 si = gsi_start_bb (seq_start_bb);
6329 tree startvar = fd->loop.v;
6330 tree endvar = NULL_TREE;
6332 if (gimple_omp_for_combined_p (fd->for_stmt))
6334 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6335 ? gimple_omp_parallel_clauses (inner_stmt)
6336 : gimple_omp_for_clauses (inner_stmt);
6337 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6338 gcc_assert (innerc);
6339 startvar = OMP_CLAUSE_DECL (innerc);
6340 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6341 OMP_CLAUSE__LOOPTEMP_);
6342 gcc_assert (innerc);
6343 endvar = OMP_CLAUSE_DECL (innerc);
6346 t = fold_convert (itype, s0);
6347 t = fold_build2 (MULT_EXPR, itype, t, step);
6348 if (POINTER_TYPE_P (type))
6349 t = fold_build_pointer_plus (n1, t);
6350 else
6351 t = fold_build2 (PLUS_EXPR, type, t, n1);
6352 t = fold_convert (TREE_TYPE (startvar), t);
6353 t = force_gimple_operand_gsi (&si, t,
6354 DECL_P (startvar)
6355 && TREE_ADDRESSABLE (startvar),
6356 NULL_TREE, false, GSI_CONTINUE_LINKING);
6357 stmt = gimple_build_assign (startvar, t);
6358 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6360 t = fold_convert (itype, e0);
6361 t = fold_build2 (MULT_EXPR, itype, t, step);
6362 if (POINTER_TYPE_P (type))
6363 t = fold_build_pointer_plus (n1, t);
6364 else
6365 t = fold_build2 (PLUS_EXPR, type, t, n1);
6366 t = fold_convert (TREE_TYPE (startvar), t);
6367 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6368 false, GSI_CONTINUE_LINKING);
6369 if (endvar)
6371 stmt = gimple_build_assign (endvar, e);
6372 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6374 if (fd->collapse > 1)
6375 expand_omp_for_init_vars (fd, &si, counts, inner_stmt, startvar);
6377 if (!broken_loop)
6379 /* The code controlling the sequential loop goes in CONT_BB,
6380 replacing the GIMPLE_OMP_CONTINUE. */
6381 si = gsi_last_bb (cont_bb);
6382 stmt = gsi_stmt (si);
6383 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6384 v_main = gimple_omp_continue_control_use (stmt);
6385 v_back = gimple_omp_continue_control_def (stmt);
6387 if (!gimple_omp_for_combined_p (fd->for_stmt))
6389 if (POINTER_TYPE_P (type))
6390 t = fold_build_pointer_plus (v_main, step);
6391 else
6392 t = fold_build2 (PLUS_EXPR, type, v_main, step);
6393 if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
6394 t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6395 true, GSI_SAME_STMT);
6396 stmt = gimple_build_assign (v_back, t);
6397 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6399 t = build2 (fd->loop.cond_code, boolean_type_node,
6400 DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
6401 ? t : v_back, e);
6402 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
6405 /* Remove GIMPLE_OMP_CONTINUE. */
6406 gsi_remove (&si, true);
6408 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6409 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6411 /* Trip update code goes into TRIP_UPDATE_BB. */
6412 si = gsi_start_bb (trip_update_bb);
6414 t = build_int_cst (itype, 1);
6415 t = build2 (PLUS_EXPR, itype, trip_main, t);
6416 stmt = gimple_build_assign (trip_back, t);
6417 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6420 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6421 si = gsi_last_bb (exit_bb);
6422 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
6424 t = gimple_omp_return_lhs (gsi_stmt (si));
6425 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
6427 gsi_remove (&si, true);
6429 /* Connect the new blocks. */
6430 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6431 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6433 if (!broken_loop)
6435 se = find_edge (cont_bb, body_bb);
6436 if (gimple_omp_for_combined_p (fd->for_stmt))
6438 remove_edge (se);
6439 se = NULL;
6441 else if (fd->collapse > 1)
6443 remove_edge (se);
6444 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6446 else
6447 se->flags = EDGE_TRUE_VALUE;
6448 find_edge (cont_bb, trip_update_bb)->flags
6449 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6451 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6454 if (gimple_in_ssa_p (cfun))
6456 gimple_stmt_iterator psi;
6457 gimple phi;
6458 edge re, ene;
6459 edge_var_map_vector *head;
6460 edge_var_map *vm;
6461 size_t i;
6463 gcc_assert (fd->collapse == 1 && !broken_loop);
6465 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6466 remove arguments of the phi nodes in fin_bb. We need to create
6467 appropriate phi nodes in iter_part_bb instead. */
6468 se = single_pred_edge (fin_bb);
6469 re = single_succ_edge (trip_update_bb);
6470 head = redirect_edge_var_map_vector (re);
6471 ene = single_succ_edge (entry_bb);
6473 psi = gsi_start_phis (fin_bb);
6474 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6475 gsi_next (&psi), ++i)
6477 gimple nphi;
6478 source_location locus;
6480 phi = gsi_stmt (psi);
6481 t = gimple_phi_result (phi);
6482 gcc_assert (t == redirect_edge_var_map_result (vm));
6483 nphi = create_phi_node (t, iter_part_bb);
6485 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6486 locus = gimple_phi_arg_location_from_edge (phi, se);
6488 /* A special case -- fd->loop.v is not yet computed in
6489 iter_part_bb, we need to use v_extra instead. */
6490 if (t == fd->loop.v)
6491 t = v_extra;
6492 add_phi_arg (nphi, t, ene, locus);
6493 locus = redirect_edge_var_map_location (vm);
6494 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6496 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6497 redirect_edge_var_map_clear (re);
6498 while (1)
6500 psi = gsi_start_phis (fin_bb);
6501 if (gsi_end_p (psi))
6502 break;
6503 remove_phi_node (&psi, false);
6506 /* Make phi node for trip. */
6507 phi = create_phi_node (trip_main, iter_part_bb);
6508 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6509 UNKNOWN_LOCATION);
6510 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6511 UNKNOWN_LOCATION);
6514 if (!broken_loop)
6515 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6516 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6517 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6518 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6519 recompute_dominator (CDI_DOMINATORS, fin_bb));
6520 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6521 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6522 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6523 recompute_dominator (CDI_DOMINATORS, body_bb));
6525 if (!broken_loop)
6527 struct loop *trip_loop = alloc_loop ();
6528 trip_loop->header = iter_part_bb;
6529 trip_loop->latch = trip_update_bb;
6530 add_loop (trip_loop, iter_part_bb->loop_father);
6532 if (!gimple_omp_for_combined_p (fd->for_stmt))
6534 struct loop *loop = alloc_loop ();
6535 loop->header = body_bb;
6536 if (collapse_bb == NULL)
6537 loop->latch = cont_bb;
6538 add_loop (loop, trip_loop);
6544 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6545 loop. Given parameters:
6547 for (V = N1; V cond N2; V += STEP) BODY;
6549 where COND is "<" or ">", we generate pseudocode
6551 V = N1;
6552 goto L1;
6554 BODY;
6555 V += STEP;
6557 if (V cond N2) goto L0; else goto L2;
6560 For collapsed loops, given parameters:
6561 collapse(3)
6562 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6563 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6564 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6565 BODY;
6567 we generate pseudocode
6569 if (cond3 is <)
6570 adj = STEP3 - 1;
6571 else
6572 adj = STEP3 + 1;
6573 count3 = (adj + N32 - N31) / STEP3;
6574 if (cond2 is <)
6575 adj = STEP2 - 1;
6576 else
6577 adj = STEP2 + 1;
6578 count2 = (adj + N22 - N21) / STEP2;
6579 if (cond1 is <)
6580 adj = STEP1 - 1;
6581 else
6582 adj = STEP1 + 1;
6583 count1 = (adj + N12 - N11) / STEP1;
6584 count = count1 * count2 * count3;
6585 V = 0;
6586 V1 = N11;
6587 V2 = N21;
6588 V3 = N31;
6589 goto L1;
6591 BODY;
6592 V += 1;
6593 V3 += STEP3;
6594 V2 += (V3 cond3 N32) ? 0 : STEP2;
6595 V3 = (V3 cond3 N32) ? V3 : N31;
6596 V1 += (V2 cond2 N22) ? 0 : STEP1;
6597 V2 = (V2 cond2 N22) ? V2 : N21;
6599 if (V < count) goto L0; else goto L2;
6604 static void
6605 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
6607 tree type, t;
6608 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
6609 gimple_stmt_iterator gsi;
6610 gimple stmt;
6611 bool broken_loop = region->cont == NULL;
6612 edge e, ne;
6613 tree *counts = NULL;
6614 int i;
6615 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6616 OMP_CLAUSE_SAFELEN);
6617 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6618 OMP_CLAUSE__SIMDUID_);
6619 tree n1, n2;
6621 type = TREE_TYPE (fd->loop.v);
6622 entry_bb = region->entry;
6623 cont_bb = region->cont;
6624 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6625 gcc_assert (broken_loop
6626 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6627 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6628 if (!broken_loop)
6630 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6631 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6632 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6633 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6635 else
6637 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6638 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6639 l2_bb = single_succ (l1_bb);
6641 exit_bb = region->exit;
6642 l2_dom_bb = NULL;
6644 gsi = gsi_last_bb (entry_bb);
6646 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6647 /* Not needed in SSA form right now. */
6648 gcc_assert (!gimple_in_ssa_p (cfun));
6649 if (fd->collapse > 1)
6651 int first_zero_iter = -1;
6652 basic_block zero_iter_bb = l2_bb;
6654 counts = XALLOCAVEC (tree, fd->collapse);
6655 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6656 zero_iter_bb, first_zero_iter,
6657 l2_dom_bb);
6659 if (l2_dom_bb == NULL)
6660 l2_dom_bb = l1_bb;
6662 n1 = fd->loop.n1;
6663 n2 = fd->loop.n2;
6664 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6666 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6667 OMP_CLAUSE__LOOPTEMP_);
6668 gcc_assert (innerc);
6669 n1 = OMP_CLAUSE_DECL (innerc);
6670 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6671 OMP_CLAUSE__LOOPTEMP_);
6672 gcc_assert (innerc);
6673 n2 = OMP_CLAUSE_DECL (innerc);
6674 expand_omp_build_assign (&gsi, fd->loop.v,
6675 fold_convert (type, n1));
6676 if (fd->collapse > 1)
6678 gsi_prev (&gsi);
6679 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
6680 gsi_next (&gsi);
6683 else
6685 expand_omp_build_assign (&gsi, fd->loop.v,
6686 fold_convert (type, fd->loop.n1));
6687 if (fd->collapse > 1)
6688 for (i = 0; i < fd->collapse; i++)
6690 tree itype = TREE_TYPE (fd->loops[i].v);
6691 if (POINTER_TYPE_P (itype))
6692 itype = signed_type_for (itype);
6693 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
6694 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6698 /* Remove the GIMPLE_OMP_FOR statement. */
6699 gsi_remove (&gsi, true);
6701 if (!broken_loop)
6703 /* Code to control the increment goes in the CONT_BB. */
6704 gsi = gsi_last_bb (cont_bb);
6705 stmt = gsi_stmt (gsi);
6706 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6708 if (POINTER_TYPE_P (type))
6709 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
6710 else
6711 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
6712 expand_omp_build_assign (&gsi, fd->loop.v, t);
6714 if (fd->collapse > 1)
6716 i = fd->collapse - 1;
6717 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
6719 t = fold_convert (sizetype, fd->loops[i].step);
6720 t = fold_build_pointer_plus (fd->loops[i].v, t);
6722 else
6724 t = fold_convert (TREE_TYPE (fd->loops[i].v),
6725 fd->loops[i].step);
6726 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
6727 fd->loops[i].v, t);
6729 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6731 for (i = fd->collapse - 1; i > 0; i--)
6733 tree itype = TREE_TYPE (fd->loops[i].v);
6734 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
6735 if (POINTER_TYPE_P (itype2))
6736 itype2 = signed_type_for (itype2);
6737 t = build3 (COND_EXPR, itype2,
6738 build2 (fd->loops[i].cond_code, boolean_type_node,
6739 fd->loops[i].v,
6740 fold_convert (itype, fd->loops[i].n2)),
6741 build_int_cst (itype2, 0),
6742 fold_convert (itype2, fd->loops[i - 1].step));
6743 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
6744 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
6745 else
6746 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
6747 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
6749 t = build3 (COND_EXPR, itype,
6750 build2 (fd->loops[i].cond_code, boolean_type_node,
6751 fd->loops[i].v,
6752 fold_convert (itype, fd->loops[i].n2)),
6753 fd->loops[i].v,
6754 fold_convert (itype, fd->loops[i].n1));
6755 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6759 /* Remove GIMPLE_OMP_CONTINUE. */
6760 gsi_remove (&gsi, true);
6763 /* Emit the condition in L1_BB. */
6764 gsi = gsi_start_bb (l1_bb);
6766 t = fold_convert (type, n2);
6767 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6768 false, GSI_CONTINUE_LINKING);
6769 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
6770 stmt = gimple_build_cond_empty (t);
6771 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6772 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
6773 NULL, NULL)
6774 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
6775 NULL, NULL))
6777 gsi = gsi_for_stmt (stmt);
6778 gimple_regimplify_operands (stmt, &gsi);
6781 /* Remove GIMPLE_OMP_RETURN. */
6782 gsi = gsi_last_bb (exit_bb);
6783 gsi_remove (&gsi, true);
6785 /* Connect the new blocks. */
6786 remove_edge (FALLTHRU_EDGE (entry_bb));
6788 if (!broken_loop)
6790 remove_edge (BRANCH_EDGE (entry_bb));
6791 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6793 e = BRANCH_EDGE (l1_bb);
6794 ne = FALLTHRU_EDGE (l1_bb);
6795 e->flags = EDGE_TRUE_VALUE;
6797 else
6799 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6801 ne = single_succ_edge (l1_bb);
6802 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6805 ne->flags = EDGE_FALSE_VALUE;
6806 e->probability = REG_BR_PROB_BASE * 7 / 8;
6807 ne->probability = REG_BR_PROB_BASE / 8;
6809 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6810 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6811 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6813 if (!broken_loop)
6815 struct loop *loop = alloc_loop ();
6816 loop->header = l1_bb;
6817 loop->latch = cont_bb;
6818 add_loop (loop, l1_bb->loop_father);
6819 if (safelen == NULL_TREE)
6820 loop->safelen = INT_MAX;
6821 else
6823 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
6824 if (!tree_fits_uhwi_p (safelen)
6825 || tree_to_uhwi (safelen) > INT_MAX)
6826 loop->safelen = INT_MAX;
6827 else
6828 loop->safelen = tree_to_uhwi (safelen);
6829 if (loop->safelen == 1)
6830 loop->safelen = 0;
6832 if (simduid)
6834 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
6835 cfun->has_simduid_loops = true;
6837 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
6838 the loop. */
6839 if ((flag_tree_loop_vectorize
6840 || (!global_options_set.x_flag_tree_loop_vectorize
6841 && !global_options_set.x_flag_tree_vectorize))
6842 && loop->safelen > 1)
6844 loop->force_vect = true;
6845 cfun->has_force_vect_loops = true;
6851 /* Expand the OpenMP loop defined by REGION. */
6853 static void
6854 expand_omp_for (struct omp_region *region, gimple inner_stmt)
6856 struct omp_for_data fd;
6857 struct omp_for_data_loop *loops;
6859 loops
6860 = (struct omp_for_data_loop *)
6861 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
6862 * sizeof (struct omp_for_data_loop));
6863 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
6864 region->sched_kind = fd.sched_kind;
6866 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
6867 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6868 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6869 if (region->cont)
6871 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
6872 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6873 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6875 else
6876 /* If there isn't a continue then this is a degerate case where
6877 the introduction of abnormal edges during lowering will prevent
6878 original loops from being detected. Fix that up. */
6879 loops_state_set (LOOPS_NEED_FIXUP);
6881 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_KIND_SIMD)
6882 expand_omp_simd (region, &fd);
6883 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
6884 && !fd.have_ordered)
6886 if (fd.chunk_size == NULL)
6887 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
6888 else
6889 expand_omp_for_static_chunk (region, &fd, inner_stmt);
6891 else
6893 int fn_index, start_ix, next_ix;
6895 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
6896 == GF_OMP_FOR_KIND_FOR);
6897 if (fd.chunk_size == NULL
6898 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
6899 fd.chunk_size = integer_zero_node;
6900 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6901 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
6902 ? 3 : fd.sched_kind;
6903 fn_index += fd.have_ordered * 4;
6904 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
6905 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
6906 if (fd.iter_type == long_long_unsigned_type_node)
6908 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
6909 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
6910 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
6911 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
6913 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
6914 (enum built_in_function) next_ix, inner_stmt);
6917 if (gimple_in_ssa_p (cfun))
6918 update_ssa (TODO_update_ssa_only_virtuals);
6922 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
6924 v = GOMP_sections_start (n);
6926 switch (v)
6928 case 0:
6929 goto L2;
6930 case 1:
6931 section 1;
6932 goto L1;
6933 case 2:
6935 case n:
6937 default:
6938 abort ();
6941 v = GOMP_sections_next ();
6942 goto L0;
6944 reduction;
6946 If this is a combined parallel sections, replace the call to
6947 GOMP_sections_start with call to GOMP_sections_next. */
6949 static void
6950 expand_omp_sections (struct omp_region *region)
6952 tree t, u, vin = NULL, vmain, vnext, l2;
6953 unsigned len;
6954 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
6955 gimple_stmt_iterator si, switch_si;
6956 gimple sections_stmt, stmt, cont;
6957 edge_iterator ei;
6958 edge e;
6959 struct omp_region *inner;
6960 unsigned i, casei;
6961 bool exit_reachable = region->cont != NULL;
6963 gcc_assert (region->exit != NULL);
6964 entry_bb = region->entry;
6965 l0_bb = single_succ (entry_bb);
6966 l1_bb = region->cont;
6967 l2_bb = region->exit;
6968 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
6969 l2 = gimple_block_label (l2_bb);
6970 else
6972 /* This can happen if there are reductions. */
6973 len = EDGE_COUNT (l0_bb->succs);
6974 gcc_assert (len > 0);
6975 e = EDGE_SUCC (l0_bb, len - 1);
6976 si = gsi_last_bb (e->dest);
6977 l2 = NULL_TREE;
6978 if (gsi_end_p (si)
6979 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
6980 l2 = gimple_block_label (e->dest);
6981 else
6982 FOR_EACH_EDGE (e, ei, l0_bb->succs)
6984 si = gsi_last_bb (e->dest);
6985 if (gsi_end_p (si)
6986 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
6988 l2 = gimple_block_label (e->dest);
6989 break;
6993 if (exit_reachable)
6994 default_bb = create_empty_bb (l1_bb->prev_bb);
6995 else
6996 default_bb = create_empty_bb (l0_bb);
6998 /* We will build a switch() with enough cases for all the
6999 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7000 and a default case to abort if something goes wrong. */
7001 len = EDGE_COUNT (l0_bb->succs);
7003 /* Use vec::quick_push on label_vec throughout, since we know the size
7004 in advance. */
7005 auto_vec<tree> label_vec (len);
7007 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7008 GIMPLE_OMP_SECTIONS statement. */
7009 si = gsi_last_bb (entry_bb);
7010 sections_stmt = gsi_stmt (si);
7011 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7012 vin = gimple_omp_sections_control (sections_stmt);
7013 if (!is_combined_parallel (region))
7015 /* If we are not inside a combined parallel+sections region,
7016 call GOMP_sections_start. */
7017 t = build_int_cst (unsigned_type_node, len - 1);
7018 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7019 stmt = gimple_build_call (u, 1, t);
7021 else
7023 /* Otherwise, call GOMP_sections_next. */
7024 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7025 stmt = gimple_build_call (u, 0);
7027 gimple_call_set_lhs (stmt, vin);
7028 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7029 gsi_remove (&si, true);
7031 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7032 L0_BB. */
7033 switch_si = gsi_last_bb (l0_bb);
7034 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7035 if (exit_reachable)
7037 cont = last_stmt (l1_bb);
7038 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7039 vmain = gimple_omp_continue_control_use (cont);
7040 vnext = gimple_omp_continue_control_def (cont);
7042 else
7044 vmain = vin;
7045 vnext = NULL_TREE;
7048 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7049 label_vec.quick_push (t);
7050 i = 1;
7052 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7053 for (inner = region->inner, casei = 1;
7054 inner;
7055 inner = inner->next, i++, casei++)
7057 basic_block s_entry_bb, s_exit_bb;
7059 /* Skip optional reduction region. */
7060 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7062 --i;
7063 --casei;
7064 continue;
7067 s_entry_bb = inner->entry;
7068 s_exit_bb = inner->exit;
7070 t = gimple_block_label (s_entry_bb);
7071 u = build_int_cst (unsigned_type_node, casei);
7072 u = build_case_label (u, NULL, t);
7073 label_vec.quick_push (u);
7075 si = gsi_last_bb (s_entry_bb);
7076 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7077 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7078 gsi_remove (&si, true);
7079 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7081 if (s_exit_bb == NULL)
7082 continue;
7084 si = gsi_last_bb (s_exit_bb);
7085 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7086 gsi_remove (&si, true);
7088 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7091 /* Error handling code goes in DEFAULT_BB. */
7092 t = gimple_block_label (default_bb);
7093 u = build_case_label (NULL, NULL, t);
7094 make_edge (l0_bb, default_bb, 0);
7095 if (current_loops)
7096 add_bb_to_loop (default_bb, current_loops->tree_root);
7098 stmt = gimple_build_switch (vmain, u, label_vec);
7099 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7100 gsi_remove (&switch_si, true);
7102 si = gsi_start_bb (default_bb);
7103 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7104 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7106 if (exit_reachable)
7108 tree bfn_decl;
7110 /* Code to get the next section goes in L1_BB. */
7111 si = gsi_last_bb (l1_bb);
7112 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7114 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7115 stmt = gimple_build_call (bfn_decl, 0);
7116 gimple_call_set_lhs (stmt, vnext);
7117 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7118 gsi_remove (&si, true);
7120 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7123 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7124 si = gsi_last_bb (l2_bb);
7125 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7126 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7127 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7128 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7129 else
7130 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7131 stmt = gimple_build_call (t, 0);
7132 if (gimple_omp_return_lhs (gsi_stmt (si)))
7133 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7134 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7135 gsi_remove (&si, true);
7137 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7141 /* Expand code for an OpenMP single directive. We've already expanded
7142 much of the code, here we simply place the GOMP_barrier call. */
7144 static void
7145 expand_omp_single (struct omp_region *region)
7147 basic_block entry_bb, exit_bb;
7148 gimple_stmt_iterator si;
7150 entry_bb = region->entry;
7151 exit_bb = region->exit;
7153 si = gsi_last_bb (entry_bb);
7154 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7155 gsi_remove (&si, true);
7156 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7158 si = gsi_last_bb (exit_bb);
7159 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7161 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7162 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7164 gsi_remove (&si, true);
7165 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7169 /* Generic expansion for OpenMP synchronization directives: master,
7170 ordered and critical. All we need to do here is remove the entry
7171 and exit markers for REGION. */
7173 static void
7174 expand_omp_synch (struct omp_region *region)
7176 basic_block entry_bb, exit_bb;
7177 gimple_stmt_iterator si;
7179 entry_bb = region->entry;
7180 exit_bb = region->exit;
7182 si = gsi_last_bb (entry_bb);
7183 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7184 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7185 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7186 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7187 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7188 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7189 gsi_remove (&si, true);
7190 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7192 if (exit_bb)
7194 si = gsi_last_bb (exit_bb);
7195 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7196 gsi_remove (&si, true);
7197 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7201 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7202 operation as a normal volatile load. */
7204 static bool
7205 expand_omp_atomic_load (basic_block load_bb, tree addr,
7206 tree loaded_val, int index)
7208 enum built_in_function tmpbase;
7209 gimple_stmt_iterator gsi;
7210 basic_block store_bb;
7211 location_t loc;
7212 gimple stmt;
7213 tree decl, call, type, itype;
7215 gsi = gsi_last_bb (load_bb);
7216 stmt = gsi_stmt (gsi);
7217 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7218 loc = gimple_location (stmt);
7220 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7221 is smaller than word size, then expand_atomic_load assumes that the load
7222 is atomic. We could avoid the builtin entirely in this case. */
7224 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7225 decl = builtin_decl_explicit (tmpbase);
7226 if (decl == NULL_TREE)
7227 return false;
7229 type = TREE_TYPE (loaded_val);
7230 itype = TREE_TYPE (TREE_TYPE (decl));
7232 call = build_call_expr_loc (loc, decl, 2, addr,
7233 build_int_cst (NULL,
7234 gimple_omp_atomic_seq_cst_p (stmt)
7235 ? MEMMODEL_SEQ_CST
7236 : MEMMODEL_RELAXED));
7237 if (!useless_type_conversion_p (type, itype))
7238 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7239 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7241 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7242 gsi_remove (&gsi, true);
7244 store_bb = single_succ (load_bb);
7245 gsi = gsi_last_bb (store_bb);
7246 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7247 gsi_remove (&gsi, true);
7249 if (gimple_in_ssa_p (cfun))
7250 update_ssa (TODO_update_ssa_no_phi);
7252 return true;
7255 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7256 operation as a normal volatile store. */
7258 static bool
7259 expand_omp_atomic_store (basic_block load_bb, tree addr,
7260 tree loaded_val, tree stored_val, int index)
7262 enum built_in_function tmpbase;
7263 gimple_stmt_iterator gsi;
7264 basic_block store_bb = single_succ (load_bb);
7265 location_t loc;
7266 gimple stmt;
7267 tree decl, call, type, itype;
7268 enum machine_mode imode;
7269 bool exchange;
7271 gsi = gsi_last_bb (load_bb);
7272 stmt = gsi_stmt (gsi);
7273 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7275 /* If the load value is needed, then this isn't a store but an exchange. */
7276 exchange = gimple_omp_atomic_need_value_p (stmt);
7278 gsi = gsi_last_bb (store_bb);
7279 stmt = gsi_stmt (gsi);
7280 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7281 loc = gimple_location (stmt);
7283 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7284 is smaller than word size, then expand_atomic_store assumes that the store
7285 is atomic. We could avoid the builtin entirely in this case. */
7287 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7288 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7289 decl = builtin_decl_explicit (tmpbase);
7290 if (decl == NULL_TREE)
7291 return false;
7293 type = TREE_TYPE (stored_val);
7295 /* Dig out the type of the function's second argument. */
7296 itype = TREE_TYPE (decl);
7297 itype = TYPE_ARG_TYPES (itype);
7298 itype = TREE_CHAIN (itype);
7299 itype = TREE_VALUE (itype);
7300 imode = TYPE_MODE (itype);
7302 if (exchange && !can_atomic_exchange_p (imode, true))
7303 return false;
7305 if (!useless_type_conversion_p (itype, type))
7306 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7307 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7308 build_int_cst (NULL,
7309 gimple_omp_atomic_seq_cst_p (stmt)
7310 ? MEMMODEL_SEQ_CST
7311 : MEMMODEL_RELAXED));
7312 if (exchange)
7314 if (!useless_type_conversion_p (type, itype))
7315 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7316 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7319 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7320 gsi_remove (&gsi, true);
7322 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7323 gsi = gsi_last_bb (load_bb);
7324 gsi_remove (&gsi, true);
7326 if (gimple_in_ssa_p (cfun))
7327 update_ssa (TODO_update_ssa_no_phi);
7329 return true;
7332 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7333 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7334 size of the data type, and thus usable to find the index of the builtin
7335 decl. Returns false if the expression is not of the proper form. */
7337 static bool
7338 expand_omp_atomic_fetch_op (basic_block load_bb,
7339 tree addr, tree loaded_val,
7340 tree stored_val, int index)
7342 enum built_in_function oldbase, newbase, tmpbase;
7343 tree decl, itype, call;
7344 tree lhs, rhs;
7345 basic_block store_bb = single_succ (load_bb);
7346 gimple_stmt_iterator gsi;
7347 gimple stmt;
7348 location_t loc;
7349 enum tree_code code;
7350 bool need_old, need_new;
7351 enum machine_mode imode;
7352 bool seq_cst;
7354 /* We expect to find the following sequences:
7356 load_bb:
7357 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7359 store_bb:
7360 val = tmp OP something; (or: something OP tmp)
7361 GIMPLE_OMP_STORE (val)
7363 ???FIXME: Allow a more flexible sequence.
7364 Perhaps use data flow to pick the statements.
7368 gsi = gsi_after_labels (store_bb);
7369 stmt = gsi_stmt (gsi);
7370 loc = gimple_location (stmt);
7371 if (!is_gimple_assign (stmt))
7372 return false;
7373 gsi_next (&gsi);
7374 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7375 return false;
7376 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7377 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7378 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7379 gcc_checking_assert (!need_old || !need_new);
7381 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7382 return false;
7384 /* Check for one of the supported fetch-op operations. */
7385 code = gimple_assign_rhs_code (stmt);
7386 switch (code)
7388 case PLUS_EXPR:
7389 case POINTER_PLUS_EXPR:
7390 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7391 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7392 break;
7393 case MINUS_EXPR:
7394 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7395 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7396 break;
7397 case BIT_AND_EXPR:
7398 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7399 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7400 break;
7401 case BIT_IOR_EXPR:
7402 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7403 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7404 break;
7405 case BIT_XOR_EXPR:
7406 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7407 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7408 break;
7409 default:
7410 return false;
7413 /* Make sure the expression is of the proper form. */
7414 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7415 rhs = gimple_assign_rhs2 (stmt);
7416 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7417 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7418 rhs = gimple_assign_rhs1 (stmt);
7419 else
7420 return false;
7422 tmpbase = ((enum built_in_function)
7423 ((need_new ? newbase : oldbase) + index + 1));
7424 decl = builtin_decl_explicit (tmpbase);
7425 if (decl == NULL_TREE)
7426 return false;
7427 itype = TREE_TYPE (TREE_TYPE (decl));
7428 imode = TYPE_MODE (itype);
7430 /* We could test all of the various optabs involved, but the fact of the
7431 matter is that (with the exception of i486 vs i586 and xadd) all targets
7432 that support any atomic operaton optab also implements compare-and-swap.
7433 Let optabs.c take care of expanding any compare-and-swap loop. */
7434 if (!can_compare_and_swap_p (imode, true))
7435 return false;
7437 gsi = gsi_last_bb (load_bb);
7438 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7440 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7441 It only requires that the operation happen atomically. Thus we can
7442 use the RELAXED memory model. */
7443 call = build_call_expr_loc (loc, decl, 3, addr,
7444 fold_convert_loc (loc, itype, rhs),
7445 build_int_cst (NULL,
7446 seq_cst ? MEMMODEL_SEQ_CST
7447 : MEMMODEL_RELAXED));
7449 if (need_old || need_new)
7451 lhs = need_old ? loaded_val : stored_val;
7452 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7453 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7455 else
7456 call = fold_convert_loc (loc, void_type_node, call);
7457 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7458 gsi_remove (&gsi, true);
7460 gsi = gsi_last_bb (store_bb);
7461 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7462 gsi_remove (&gsi, true);
7463 gsi = gsi_last_bb (store_bb);
7464 gsi_remove (&gsi, true);
7466 if (gimple_in_ssa_p (cfun))
7467 update_ssa (TODO_update_ssa_no_phi);
7469 return true;
7472 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7474 oldval = *addr;
7475 repeat:
7476 newval = rhs; // with oldval replacing *addr in rhs
7477 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7478 if (oldval != newval)
7479 goto repeat;
7481 INDEX is log2 of the size of the data type, and thus usable to find the
7482 index of the builtin decl. */
7484 static bool
7485 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7486 tree addr, tree loaded_val, tree stored_val,
7487 int index)
7489 tree loadedi, storedi, initial, new_storedi, old_vali;
7490 tree type, itype, cmpxchg, iaddr;
7491 gimple_stmt_iterator si;
7492 basic_block loop_header = single_succ (load_bb);
7493 gimple phi, stmt;
7494 edge e;
7495 enum built_in_function fncode;
7497 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7498 order to use the RELAXED memory model effectively. */
7499 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7500 + index + 1);
7501 cmpxchg = builtin_decl_explicit (fncode);
7502 if (cmpxchg == NULL_TREE)
7503 return false;
7504 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7505 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7507 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7508 return false;
7510 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7511 si = gsi_last_bb (load_bb);
7512 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7514 /* For floating-point values, we'll need to view-convert them to integers
7515 so that we can perform the atomic compare and swap. Simplify the
7516 following code by always setting up the "i"ntegral variables. */
7517 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7519 tree iaddr_val;
7521 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7522 true), NULL);
7523 iaddr_val
7524 = force_gimple_operand_gsi (&si,
7525 fold_convert (TREE_TYPE (iaddr), addr),
7526 false, NULL_TREE, true, GSI_SAME_STMT);
7527 stmt = gimple_build_assign (iaddr, iaddr_val);
7528 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7529 loadedi = create_tmp_var (itype, NULL);
7530 if (gimple_in_ssa_p (cfun))
7531 loadedi = make_ssa_name (loadedi, NULL);
7533 else
7535 iaddr = addr;
7536 loadedi = loaded_val;
7539 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7540 tree loaddecl = builtin_decl_explicit (fncode);
7541 if (loaddecl)
7542 initial
7543 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
7544 build_call_expr (loaddecl, 2, iaddr,
7545 build_int_cst (NULL_TREE,
7546 MEMMODEL_RELAXED)));
7547 else
7548 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
7549 build_int_cst (TREE_TYPE (iaddr), 0));
7551 initial
7552 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
7553 GSI_SAME_STMT);
7555 /* Move the value to the LOADEDI temporary. */
7556 if (gimple_in_ssa_p (cfun))
7558 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
7559 phi = create_phi_node (loadedi, loop_header);
7560 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
7561 initial);
7563 else
7564 gsi_insert_before (&si,
7565 gimple_build_assign (loadedi, initial),
7566 GSI_SAME_STMT);
7567 if (loadedi != loaded_val)
7569 gimple_stmt_iterator gsi2;
7570 tree x;
7572 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
7573 gsi2 = gsi_start_bb (loop_header);
7574 if (gimple_in_ssa_p (cfun))
7576 gimple stmt;
7577 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7578 true, GSI_SAME_STMT);
7579 stmt = gimple_build_assign (loaded_val, x);
7580 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
7582 else
7584 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
7585 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7586 true, GSI_SAME_STMT);
7589 gsi_remove (&si, true);
7591 si = gsi_last_bb (store_bb);
7592 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7594 if (iaddr == addr)
7595 storedi = stored_val;
7596 else
7597 storedi =
7598 force_gimple_operand_gsi (&si,
7599 build1 (VIEW_CONVERT_EXPR, itype,
7600 stored_val), true, NULL_TREE, true,
7601 GSI_SAME_STMT);
7603 /* Build the compare&swap statement. */
7604 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
7605 new_storedi = force_gimple_operand_gsi (&si,
7606 fold_convert (TREE_TYPE (loadedi),
7607 new_storedi),
7608 true, NULL_TREE,
7609 true, GSI_SAME_STMT);
7611 if (gimple_in_ssa_p (cfun))
7612 old_vali = loadedi;
7613 else
7615 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
7616 stmt = gimple_build_assign (old_vali, loadedi);
7617 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7619 stmt = gimple_build_assign (loadedi, new_storedi);
7620 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7623 /* Note that we always perform the comparison as an integer, even for
7624 floating point. This allows the atomic operation to properly
7625 succeed even with NaNs and -0.0. */
7626 stmt = gimple_build_cond_empty
7627 (build2 (NE_EXPR, boolean_type_node,
7628 new_storedi, old_vali));
7629 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7631 /* Update cfg. */
7632 e = single_succ_edge (store_bb);
7633 e->flags &= ~EDGE_FALLTHRU;
7634 e->flags |= EDGE_FALSE_VALUE;
7636 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
7638 /* Copy the new value to loadedi (we already did that before the condition
7639 if we are not in SSA). */
7640 if (gimple_in_ssa_p (cfun))
7642 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
7643 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
7646 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
7647 gsi_remove (&si, true);
7649 struct loop *loop = alloc_loop ();
7650 loop->header = loop_header;
7651 loop->latch = store_bb;
7652 add_loop (loop, loop_header->loop_father);
7654 if (gimple_in_ssa_p (cfun))
7655 update_ssa (TODO_update_ssa_no_phi);
7657 return true;
7660 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7662 GOMP_atomic_start ();
7663 *addr = rhs;
7664 GOMP_atomic_end ();
7666 The result is not globally atomic, but works so long as all parallel
7667 references are within #pragma omp atomic directives. According to
7668 responses received from omp@openmp.org, appears to be within spec.
7669 Which makes sense, since that's how several other compilers handle
7670 this situation as well.
7671 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
7672 expanding. STORED_VAL is the operand of the matching
7673 GIMPLE_OMP_ATOMIC_STORE.
7675 We replace
7676 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
7677 loaded_val = *addr;
7679 and replace
7680 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
7681 *addr = stored_val;
7684 static bool
7685 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
7686 tree addr, tree loaded_val, tree stored_val)
7688 gimple_stmt_iterator si;
7689 gimple stmt;
7690 tree t;
7692 si = gsi_last_bb (load_bb);
7693 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7695 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
7696 t = build_call_expr (t, 0);
7697 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7699 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
7700 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7701 gsi_remove (&si, true);
7703 si = gsi_last_bb (store_bb);
7704 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7706 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
7707 stored_val);
7708 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7710 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
7711 t = build_call_expr (t, 0);
7712 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7713 gsi_remove (&si, true);
7715 if (gimple_in_ssa_p (cfun))
7716 update_ssa (TODO_update_ssa_no_phi);
7717 return true;
7720 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
7721 using expand_omp_atomic_fetch_op. If it failed, we try to
7722 call expand_omp_atomic_pipeline, and if it fails too, the
7723 ultimate fallback is wrapping the operation in a mutex
7724 (expand_omp_atomic_mutex). REGION is the atomic region built
7725 by build_omp_regions_1(). */
7727 static void
7728 expand_omp_atomic (struct omp_region *region)
7730 basic_block load_bb = region->entry, store_bb = region->exit;
7731 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
7732 tree loaded_val = gimple_omp_atomic_load_lhs (load);
7733 tree addr = gimple_omp_atomic_load_rhs (load);
7734 tree stored_val = gimple_omp_atomic_store_val (store);
7735 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7736 HOST_WIDE_INT index;
7738 /* Make sure the type is one of the supported sizes. */
7739 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
7740 index = exact_log2 (index);
7741 if (index >= 0 && index <= 4)
7743 unsigned int align = TYPE_ALIGN_UNIT (type);
7745 /* __sync builtins require strict data alignment. */
7746 if (exact_log2 (align) >= index)
7748 /* Atomic load. */
7749 if (loaded_val == stored_val
7750 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7751 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7752 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7753 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
7754 return;
7756 /* Atomic store. */
7757 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7758 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7759 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7760 && store_bb == single_succ (load_bb)
7761 && first_stmt (store_bb) == store
7762 && expand_omp_atomic_store (load_bb, addr, loaded_val,
7763 stored_val, index))
7764 return;
7766 /* When possible, use specialized atomic update functions. */
7767 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
7768 && store_bb == single_succ (load_bb)
7769 && expand_omp_atomic_fetch_op (load_bb, addr,
7770 loaded_val, stored_val, index))
7771 return;
7773 /* If we don't have specialized __sync builtins, try and implement
7774 as a compare and swap loop. */
7775 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
7776 loaded_val, stored_val, index))
7777 return;
7781 /* The ultimate fallback is wrapping the operation in a mutex. */
7782 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
7786 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
7788 static void
7789 expand_omp_target (struct omp_region *region)
7791 basic_block entry_bb, exit_bb, new_bb;
7792 struct function *child_cfun = NULL;
7793 tree child_fn = NULL_TREE, block, t;
7794 gimple_stmt_iterator gsi;
7795 gimple entry_stmt, stmt;
7796 edge e;
7798 entry_stmt = last_stmt (region->entry);
7799 new_bb = region->entry;
7800 int kind = gimple_omp_target_kind (entry_stmt);
7801 if (kind == GF_OMP_TARGET_KIND_REGION)
7803 child_fn = gimple_omp_target_child_fn (entry_stmt);
7804 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7807 entry_bb = region->entry;
7808 exit_bb = region->exit;
7810 if (kind == GF_OMP_TARGET_KIND_REGION)
7812 unsigned srcidx, dstidx, num;
7814 /* If the target region needs data sent from the parent
7815 function, then the very first statement (except possible
7816 tree profile counter updates) of the parallel body
7817 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7818 &.OMP_DATA_O is passed as an argument to the child function,
7819 we need to replace it with the argument as seen by the child
7820 function.
7822 In most cases, this will end up being the identity assignment
7823 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7824 a function call that has been inlined, the original PARM_DECL
7825 .OMP_DATA_I may have been converted into a different local
7826 variable. In which case, we need to keep the assignment. */
7827 if (gimple_omp_target_data_arg (entry_stmt))
7829 basic_block entry_succ_bb = single_succ (entry_bb);
7830 gimple_stmt_iterator gsi;
7831 tree arg;
7832 gimple tgtcopy_stmt = NULL;
7833 tree sender
7834 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
7836 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7838 gcc_assert (!gsi_end_p (gsi));
7839 stmt = gsi_stmt (gsi);
7840 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7841 continue;
7843 if (gimple_num_ops (stmt) == 2)
7845 tree arg = gimple_assign_rhs1 (stmt);
7847 /* We're ignoring the subcode because we're
7848 effectively doing a STRIP_NOPS. */
7850 if (TREE_CODE (arg) == ADDR_EXPR
7851 && TREE_OPERAND (arg, 0) == sender)
7853 tgtcopy_stmt = stmt;
7854 break;
7859 gcc_assert (tgtcopy_stmt != NULL);
7860 arg = DECL_ARGUMENTS (child_fn);
7862 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
7863 gsi_remove (&gsi, true);
7866 /* Declare local variables needed in CHILD_CFUN. */
7867 block = DECL_INITIAL (child_fn);
7868 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7869 /* The gimplifier could record temporaries in target block
7870 rather than in containing function's local_decls chain,
7871 which would mean cgraph missed finalizing them. Do it now. */
7872 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7873 if (TREE_CODE (t) == VAR_DECL
7874 && TREE_STATIC (t)
7875 && !DECL_EXTERNAL (t))
7876 varpool_finalize_decl (t);
7877 DECL_SAVED_TREE (child_fn) = NULL;
7878 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7879 gimple_set_body (child_fn, NULL);
7880 TREE_USED (block) = 1;
7882 /* Reset DECL_CONTEXT on function arguments. */
7883 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7884 DECL_CONTEXT (t) = child_fn;
7886 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
7887 so that it can be moved to the child function. */
7888 gsi = gsi_last_bb (entry_bb);
7889 stmt = gsi_stmt (gsi);
7890 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
7891 && gimple_omp_target_kind (stmt)
7892 == GF_OMP_TARGET_KIND_REGION);
7893 gsi_remove (&gsi, true);
7894 e = split_block (entry_bb, stmt);
7895 entry_bb = e->dest;
7896 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7898 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
7899 if (exit_bb)
7901 gsi = gsi_last_bb (exit_bb);
7902 gcc_assert (!gsi_end_p (gsi)
7903 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7904 stmt = gimple_build_return (NULL);
7905 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7906 gsi_remove (&gsi, true);
7909 /* Move the target region into CHILD_CFUN. */
7911 block = gimple_block (entry_stmt);
7913 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7914 if (exit_bb)
7915 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7916 /* When the OMP expansion process cannot guarantee an up-to-date
7917 loop tree arrange for the child function to fixup loops. */
7918 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7919 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7921 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7922 num = vec_safe_length (child_cfun->local_decls);
7923 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7925 t = (*child_cfun->local_decls)[srcidx];
7926 if (DECL_CONTEXT (t) == cfun->decl)
7927 continue;
7928 if (srcidx != dstidx)
7929 (*child_cfun->local_decls)[dstidx] = t;
7930 dstidx++;
7932 if (dstidx != num)
7933 vec_safe_truncate (child_cfun->local_decls, dstidx);
7935 /* Inform the callgraph about the new function. */
7936 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
7937 cgraph_add_new_function (child_fn, true);
7939 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7940 fixed in a following pass. */
7941 push_cfun (child_cfun);
7942 rebuild_cgraph_edges ();
7944 /* Some EH regions might become dead, see PR34608. If
7945 pass_cleanup_cfg isn't the first pass to happen with the
7946 new child, these dead EH edges might cause problems.
7947 Clean them up now. */
7948 if (flag_exceptions)
7950 basic_block bb;
7951 bool changed = false;
7953 FOR_EACH_BB_FN (bb, cfun)
7954 changed |= gimple_purge_dead_eh_edges (bb);
7955 if (changed)
7956 cleanup_tree_cfg ();
7958 pop_cfun ();
7961 /* Emit a library call to launch the target region, or do data
7962 transfers. */
7963 tree t1, t2, t3, t4, device, cond, c, clauses;
7964 enum built_in_function start_ix;
7965 location_t clause_loc;
7967 clauses = gimple_omp_target_clauses (entry_stmt);
7969 if (kind == GF_OMP_TARGET_KIND_REGION)
7970 start_ix = BUILT_IN_GOMP_TARGET;
7971 else if (kind == GF_OMP_TARGET_KIND_DATA)
7972 start_ix = BUILT_IN_GOMP_TARGET_DATA;
7973 else
7974 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
7976 /* By default, the value of DEVICE is -1 (let runtime library choose)
7977 and there is no conditional. */
7978 cond = NULL_TREE;
7979 device = build_int_cst (integer_type_node, -1);
7981 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
7982 if (c)
7983 cond = OMP_CLAUSE_IF_EXPR (c);
7985 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
7986 if (c)
7988 device = OMP_CLAUSE_DEVICE_ID (c);
7989 clause_loc = OMP_CLAUSE_LOCATION (c);
7991 else
7992 clause_loc = gimple_location (entry_stmt);
7994 /* Ensure 'device' is of the correct type. */
7995 device = fold_convert_loc (clause_loc, integer_type_node, device);
7997 /* If we found the clause 'if (cond)', build
7998 (cond ? device : -2). */
7999 if (cond)
8001 cond = gimple_boolify (cond);
8003 basic_block cond_bb, then_bb, else_bb;
8004 edge e;
8005 tree tmp_var;
8007 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8008 if (kind != GF_OMP_TARGET_KIND_REGION)
8010 gsi = gsi_last_bb (new_bb);
8011 gsi_prev (&gsi);
8012 e = split_block (new_bb, gsi_stmt (gsi));
8014 else
8015 e = split_block (new_bb, NULL);
8016 cond_bb = e->src;
8017 new_bb = e->dest;
8018 remove_edge (e);
8020 then_bb = create_empty_bb (cond_bb);
8021 else_bb = create_empty_bb (then_bb);
8022 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8023 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8025 stmt = gimple_build_cond_empty (cond);
8026 gsi = gsi_last_bb (cond_bb);
8027 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8029 gsi = gsi_start_bb (then_bb);
8030 stmt = gimple_build_assign (tmp_var, device);
8031 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8033 gsi = gsi_start_bb (else_bb);
8034 stmt = gimple_build_assign (tmp_var,
8035 build_int_cst (integer_type_node, -2));
8036 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8038 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8039 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8040 if (current_loops)
8042 add_bb_to_loop (then_bb, cond_bb->loop_father);
8043 add_bb_to_loop (else_bb, cond_bb->loop_father);
8045 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8046 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8048 device = tmp_var;
8051 gsi = gsi_last_bb (new_bb);
8052 t = gimple_omp_target_data_arg (entry_stmt);
8053 if (t == NULL)
8055 t1 = size_zero_node;
8056 t2 = build_zero_cst (ptr_type_node);
8057 t3 = t2;
8058 t4 = t2;
8060 else
8062 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8063 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8064 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8065 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8066 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8069 gimple g;
8070 /* FIXME: This will be address of
8071 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8072 symbol, as soon as the linker plugin is able to create it for us. */
8073 tree openmp_target = build_zero_cst (ptr_type_node);
8074 if (kind == GF_OMP_TARGET_KIND_REGION)
8076 tree fnaddr = build_fold_addr_expr (child_fn);
8077 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8078 device, fnaddr, openmp_target, t1, t2, t3, t4);
8080 else
8081 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8082 device, openmp_target, t1, t2, t3, t4);
8083 gimple_set_location (g, gimple_location (entry_stmt));
8084 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8085 if (kind != GF_OMP_TARGET_KIND_REGION)
8087 g = gsi_stmt (gsi);
8088 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8089 gsi_remove (&gsi, true);
8091 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8093 gsi = gsi_last_bb (region->exit);
8094 g = gsi_stmt (gsi);
8095 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8096 gsi_remove (&gsi, true);
8101 /* Expand the parallel region tree rooted at REGION. Expansion
8102 proceeds in depth-first order. Innermost regions are expanded
8103 first. This way, parallel regions that require a new function to
8104 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8105 internal dependencies in their body. */
8107 static void
8108 expand_omp (struct omp_region *region)
8110 while (region)
8112 location_t saved_location;
8113 gimple inner_stmt = NULL;
8115 /* First, determine whether this is a combined parallel+workshare
8116 region. */
8117 if (region->type == GIMPLE_OMP_PARALLEL)
8118 determine_parallel_type (region);
8120 if (region->type == GIMPLE_OMP_FOR
8121 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8122 inner_stmt = last_stmt (region->inner->entry);
8124 if (region->inner)
8125 expand_omp (region->inner);
8127 saved_location = input_location;
8128 if (gimple_has_location (last_stmt (region->entry)))
8129 input_location = gimple_location (last_stmt (region->entry));
8131 switch (region->type)
8133 case GIMPLE_OMP_PARALLEL:
8134 case GIMPLE_OMP_TASK:
8135 expand_omp_taskreg (region);
8136 break;
8138 case GIMPLE_OMP_FOR:
8139 expand_omp_for (region, inner_stmt);
8140 break;
8142 case GIMPLE_OMP_SECTIONS:
8143 expand_omp_sections (region);
8144 break;
8146 case GIMPLE_OMP_SECTION:
8147 /* Individual omp sections are handled together with their
8148 parent GIMPLE_OMP_SECTIONS region. */
8149 break;
8151 case GIMPLE_OMP_SINGLE:
8152 expand_omp_single (region);
8153 break;
8155 case GIMPLE_OMP_MASTER:
8156 case GIMPLE_OMP_TASKGROUP:
8157 case GIMPLE_OMP_ORDERED:
8158 case GIMPLE_OMP_CRITICAL:
8159 case GIMPLE_OMP_TEAMS:
8160 expand_omp_synch (region);
8161 break;
8163 case GIMPLE_OMP_ATOMIC_LOAD:
8164 expand_omp_atomic (region);
8165 break;
8167 case GIMPLE_OMP_TARGET:
8168 expand_omp_target (region);
8169 break;
8171 default:
8172 gcc_unreachable ();
8175 input_location = saved_location;
8176 region = region->next;
8181 /* Helper for build_omp_regions. Scan the dominator tree starting at
8182 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8183 true, the function ends once a single tree is built (otherwise, whole
8184 forest of OMP constructs may be built). */
8186 static void
8187 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8188 bool single_tree)
8190 gimple_stmt_iterator gsi;
8191 gimple stmt;
8192 basic_block son;
8194 gsi = gsi_last_bb (bb);
8195 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8197 struct omp_region *region;
8198 enum gimple_code code;
8200 stmt = gsi_stmt (gsi);
8201 code = gimple_code (stmt);
8202 if (code == GIMPLE_OMP_RETURN)
8204 /* STMT is the return point out of region PARENT. Mark it
8205 as the exit point and make PARENT the immediately
8206 enclosing region. */
8207 gcc_assert (parent);
8208 region = parent;
8209 region->exit = bb;
8210 parent = parent->outer;
8212 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8214 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8215 GIMPLE_OMP_RETURN, but matches with
8216 GIMPLE_OMP_ATOMIC_LOAD. */
8217 gcc_assert (parent);
8218 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8219 region = parent;
8220 region->exit = bb;
8221 parent = parent->outer;
8224 else if (code == GIMPLE_OMP_CONTINUE)
8226 gcc_assert (parent);
8227 parent->cont = bb;
8229 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8231 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8232 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8235 else if (code == GIMPLE_OMP_TARGET
8236 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8237 new_omp_region (bb, code, parent);
8238 else
8240 /* Otherwise, this directive becomes the parent for a new
8241 region. */
8242 region = new_omp_region (bb, code, parent);
8243 parent = region;
8247 if (single_tree && !parent)
8248 return;
8250 for (son = first_dom_son (CDI_DOMINATORS, bb);
8251 son;
8252 son = next_dom_son (CDI_DOMINATORS, son))
8253 build_omp_regions_1 (son, parent, single_tree);
8256 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8257 root_omp_region. */
8259 static void
8260 build_omp_regions_root (basic_block root)
8262 gcc_assert (root_omp_region == NULL);
8263 build_omp_regions_1 (root, NULL, true);
8264 gcc_assert (root_omp_region != NULL);
8267 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8269 void
8270 omp_expand_local (basic_block head)
8272 build_omp_regions_root (head);
8273 if (dump_file && (dump_flags & TDF_DETAILS))
8275 fprintf (dump_file, "\nOMP region tree\n\n");
8276 dump_omp_region (dump_file, root_omp_region, 0);
8277 fprintf (dump_file, "\n");
8280 remove_exit_barriers (root_omp_region);
8281 expand_omp (root_omp_region);
8283 free_omp_regions ();
8286 /* Scan the CFG and build a tree of OMP regions. Return the root of
8287 the OMP region tree. */
8289 static void
8290 build_omp_regions (void)
8292 gcc_assert (root_omp_region == NULL);
8293 calculate_dominance_info (CDI_DOMINATORS);
8294 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8297 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8299 static unsigned int
8300 execute_expand_omp (void)
8302 build_omp_regions ();
8304 if (!root_omp_region)
8305 return 0;
8307 if (dump_file)
8309 fprintf (dump_file, "\nOMP region tree\n\n");
8310 dump_omp_region (dump_file, root_omp_region, 0);
8311 fprintf (dump_file, "\n");
8314 remove_exit_barriers (root_omp_region);
8316 expand_omp (root_omp_region);
8318 cleanup_tree_cfg ();
8320 free_omp_regions ();
8322 return 0;
8325 /* OMP expansion -- the default pass, run before creation of SSA form. */
8327 static bool
8328 gate_expand_omp (void)
8330 return ((flag_openmp != 0 || flag_openmp_simd != 0
8331 || flag_cilkplus != 0) && !seen_error ());
8334 namespace {
8336 const pass_data pass_data_expand_omp =
8338 GIMPLE_PASS, /* type */
8339 "ompexp", /* name */
8340 OPTGROUP_NONE, /* optinfo_flags */
8341 true, /* has_gate */
8342 true, /* has_execute */
8343 TV_NONE, /* tv_id */
8344 PROP_gimple_any, /* properties_required */
8345 0, /* properties_provided */
8346 0, /* properties_destroyed */
8347 0, /* todo_flags_start */
8348 0, /* todo_flags_finish */
8351 class pass_expand_omp : public gimple_opt_pass
8353 public:
8354 pass_expand_omp (gcc::context *ctxt)
8355 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8358 /* opt_pass methods: */
8359 bool gate () { return gate_expand_omp (); }
8360 unsigned int execute () { return execute_expand_omp (); }
8362 }; // class pass_expand_omp
8364 } // anon namespace
8366 gimple_opt_pass *
8367 make_pass_expand_omp (gcc::context *ctxt)
8369 return new pass_expand_omp (ctxt);
8372 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8374 /* If ctx is a worksharing context inside of a cancellable parallel
8375 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8376 and conditional branch to parallel's cancel_label to handle
8377 cancellation in the implicit barrier. */
8379 static void
8380 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8382 gimple omp_return = gimple_seq_last_stmt (*body);
8383 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8384 if (gimple_omp_return_nowait_p (omp_return))
8385 return;
8386 if (ctx->outer
8387 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8388 && ctx->outer->cancellable)
8390 tree lhs = create_tmp_var (boolean_type_node, NULL);
8391 gimple_omp_return_set_lhs (omp_return, lhs);
8392 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8393 gimple g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
8394 ctx->outer->cancel_label, fallthru_label);
8395 gimple_seq_add_stmt (body, g);
8396 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8400 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8401 CTX is the enclosing OMP context for the current statement. */
8403 static void
8404 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8406 tree block, control;
8407 gimple_stmt_iterator tgsi;
8408 gimple stmt, new_stmt, bind, t;
8409 gimple_seq ilist, dlist, olist, new_body;
8411 stmt = gsi_stmt (*gsi_p);
8413 push_gimplify_context ();
8415 dlist = NULL;
8416 ilist = NULL;
8417 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8418 &ilist, &dlist, ctx, NULL);
8420 new_body = gimple_omp_body (stmt);
8421 gimple_omp_set_body (stmt, NULL);
8422 tgsi = gsi_start (new_body);
8423 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8425 omp_context *sctx;
8426 gimple sec_start;
8428 sec_start = gsi_stmt (tgsi);
8429 sctx = maybe_lookup_ctx (sec_start);
8430 gcc_assert (sctx);
8432 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8433 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8434 GSI_CONTINUE_LINKING);
8435 gimple_omp_set_body (sec_start, NULL);
8437 if (gsi_one_before_end_p (tgsi))
8439 gimple_seq l = NULL;
8440 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8441 &l, ctx);
8442 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8443 gimple_omp_section_set_last (sec_start);
8446 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8447 GSI_CONTINUE_LINKING);
8450 block = make_node (BLOCK);
8451 bind = gimple_build_bind (NULL, new_body, block);
8453 olist = NULL;
8454 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8456 block = make_node (BLOCK);
8457 new_stmt = gimple_build_bind (NULL, NULL, block);
8458 gsi_replace (gsi_p, new_stmt, true);
8460 pop_gimplify_context (new_stmt);
8461 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8462 BLOCK_VARS (block) = gimple_bind_vars (bind);
8463 if (BLOCK_VARS (block))
8464 TREE_USED (block) = 1;
8466 new_body = NULL;
8467 gimple_seq_add_seq (&new_body, ilist);
8468 gimple_seq_add_stmt (&new_body, stmt);
8469 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8470 gimple_seq_add_stmt (&new_body, bind);
8472 control = create_tmp_var (unsigned_type_node, ".section");
8473 t = gimple_build_omp_continue (control, control);
8474 gimple_omp_sections_set_control (stmt, control);
8475 gimple_seq_add_stmt (&new_body, t);
8477 gimple_seq_add_seq (&new_body, olist);
8478 if (ctx->cancellable)
8479 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8480 gimple_seq_add_seq (&new_body, dlist);
8482 new_body = maybe_catch_exception (new_body);
8484 t = gimple_build_omp_return
8485 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8486 OMP_CLAUSE_NOWAIT));
8487 gimple_seq_add_stmt (&new_body, t);
8488 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8490 gimple_bind_set_body (new_stmt, new_body);
8494 /* A subroutine of lower_omp_single. Expand the simple form of
8495 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8497 if (GOMP_single_start ())
8498 BODY;
8499 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8501 FIXME. It may be better to delay expanding the logic of this until
8502 pass_expand_omp. The expanded logic may make the job more difficult
8503 to a synchronization analysis pass. */
8505 static void
8506 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8508 location_t loc = gimple_location (single_stmt);
8509 tree tlabel = create_artificial_label (loc);
8510 tree flabel = create_artificial_label (loc);
8511 gimple call, cond;
8512 tree lhs, decl;
8514 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8515 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8516 call = gimple_build_call (decl, 0);
8517 gimple_call_set_lhs (call, lhs);
8518 gimple_seq_add_stmt (pre_p, call);
8520 cond = gimple_build_cond (EQ_EXPR, lhs,
8521 fold_convert_loc (loc, TREE_TYPE (lhs),
8522 boolean_true_node),
8523 tlabel, flabel);
8524 gimple_seq_add_stmt (pre_p, cond);
8525 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8526 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8527 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8531 /* A subroutine of lower_omp_single. Expand the simple form of
8532 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8534 #pragma omp single copyprivate (a, b, c)
8536 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8539 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8541 BODY;
8542 copyout.a = a;
8543 copyout.b = b;
8544 copyout.c = c;
8545 GOMP_single_copy_end (&copyout);
8547 else
8549 a = copyout_p->a;
8550 b = copyout_p->b;
8551 c = copyout_p->c;
8553 GOMP_barrier ();
8556 FIXME. It may be better to delay expanding the logic of this until
8557 pass_expand_omp. The expanded logic may make the job more difficult
8558 to a synchronization analysis pass. */
8560 static void
8561 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
8563 tree ptr_type, t, l0, l1, l2, bfn_decl;
8564 gimple_seq copyin_seq;
8565 location_t loc = gimple_location (single_stmt);
8567 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8569 ptr_type = build_pointer_type (ctx->record_type);
8570 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8572 l0 = create_artificial_label (loc);
8573 l1 = create_artificial_label (loc);
8574 l2 = create_artificial_label (loc);
8576 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8577 t = build_call_expr_loc (loc, bfn_decl, 0);
8578 t = fold_convert_loc (loc, ptr_type, t);
8579 gimplify_assign (ctx->receiver_decl, t, pre_p);
8581 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8582 build_int_cst (ptr_type, 0));
8583 t = build3 (COND_EXPR, void_type_node, t,
8584 build_and_jump (&l0), build_and_jump (&l1));
8585 gimplify_and_add (t, pre_p);
8587 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8589 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8591 copyin_seq = NULL;
8592 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8593 &copyin_seq, ctx);
8595 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8596 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8597 t = build_call_expr_loc (loc, bfn_decl, 1, t);
8598 gimplify_and_add (t, pre_p);
8600 t = build_and_jump (&l2);
8601 gimplify_and_add (t, pre_p);
8603 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8605 gimple_seq_add_seq (pre_p, copyin_seq);
8607 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8611 /* Expand code for an OpenMP single directive. */
8613 static void
8614 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8616 tree block;
8617 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
8618 gimple_seq bind_body, bind_body_tail = NULL, dlist;
8620 push_gimplify_context ();
8622 block = make_node (BLOCK);
8623 bind = gimple_build_bind (NULL, NULL, block);
8624 gsi_replace (gsi_p, bind, true);
8625 bind_body = NULL;
8626 dlist = NULL;
8627 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8628 &bind_body, &dlist, ctx, NULL);
8629 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8631 gimple_seq_add_stmt (&bind_body, single_stmt);
8633 if (ctx->record_type)
8634 lower_omp_single_copy (single_stmt, &bind_body, ctx);
8635 else
8636 lower_omp_single_simple (single_stmt, &bind_body);
8638 gimple_omp_set_body (single_stmt, NULL);
8640 gimple_seq_add_seq (&bind_body, dlist);
8642 bind_body = maybe_catch_exception (bind_body);
8644 t = gimple_build_omp_return
8645 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
8646 OMP_CLAUSE_NOWAIT));
8647 gimple_seq_add_stmt (&bind_body_tail, t);
8648 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
8649 if (ctx->record_type)
8651 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8652 tree clobber = build_constructor (ctx->record_type, NULL);
8653 TREE_THIS_VOLATILE (clobber) = 1;
8654 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8655 clobber), GSI_SAME_STMT);
8657 gimple_seq_add_seq (&bind_body, bind_body_tail);
8658 gimple_bind_set_body (bind, bind_body);
8660 pop_gimplify_context (bind);
8662 gimple_bind_append_vars (bind, ctx->block_vars);
8663 BLOCK_VARS (block) = ctx->block_vars;
8664 if (BLOCK_VARS (block))
8665 TREE_USED (block) = 1;
8669 /* Expand code for an OpenMP master directive. */
8671 static void
8672 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8674 tree block, lab = NULL, x, bfn_decl;
8675 gimple stmt = gsi_stmt (*gsi_p), bind;
8676 location_t loc = gimple_location (stmt);
8677 gimple_seq tseq;
8679 push_gimplify_context ();
8681 block = make_node (BLOCK);
8682 bind = gimple_build_bind (NULL, NULL, block);
8683 gsi_replace (gsi_p, bind, true);
8684 gimple_bind_add_stmt (bind, stmt);
8686 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8687 x = build_call_expr_loc (loc, bfn_decl, 0);
8688 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
8689 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
8690 tseq = NULL;
8691 gimplify_and_add (x, &tseq);
8692 gimple_bind_add_seq (bind, tseq);
8694 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8695 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8696 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8697 gimple_omp_set_body (stmt, NULL);
8699 gimple_bind_add_stmt (bind, gimple_build_label (lab));
8701 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8703 pop_gimplify_context (bind);
8705 gimple_bind_append_vars (bind, ctx->block_vars);
8706 BLOCK_VARS (block) = ctx->block_vars;
8710 /* Expand code for an OpenMP taskgroup directive. */
8712 static void
8713 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8715 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8716 tree block = make_node (BLOCK);
8718 bind = gimple_build_bind (NULL, NULL, block);
8719 gsi_replace (gsi_p, bind, true);
8720 gimple_bind_add_stmt (bind, stmt);
8722 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
8724 gimple_bind_add_stmt (bind, x);
8726 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8727 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8728 gimple_omp_set_body (stmt, NULL);
8730 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8732 gimple_bind_append_vars (bind, ctx->block_vars);
8733 BLOCK_VARS (block) = ctx->block_vars;
8737 /* Expand code for an OpenMP ordered directive. */
8739 static void
8740 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8742 tree block;
8743 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8745 push_gimplify_context ();
8747 block = make_node (BLOCK);
8748 bind = gimple_build_bind (NULL, NULL, block);
8749 gsi_replace (gsi_p, bind, true);
8750 gimple_bind_add_stmt (bind, stmt);
8752 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
8754 gimple_bind_add_stmt (bind, x);
8756 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8757 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8758 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8759 gimple_omp_set_body (stmt, NULL);
8761 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
8762 gimple_bind_add_stmt (bind, x);
8764 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8766 pop_gimplify_context (bind);
8768 gimple_bind_append_vars (bind, ctx->block_vars);
8769 BLOCK_VARS (block) = gimple_bind_vars (bind);
8773 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
8774 substitution of a couple of function calls. But in the NAMED case,
8775 requires that languages coordinate a symbol name. It is therefore
8776 best put here in common code. */
8778 static GTY((param1_is (tree), param2_is (tree)))
8779 splay_tree critical_name_mutexes;
8781 static void
8782 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8784 tree block;
8785 tree name, lock, unlock;
8786 gimple stmt = gsi_stmt (*gsi_p), bind;
8787 location_t loc = gimple_location (stmt);
8788 gimple_seq tbody;
8790 name = gimple_omp_critical_name (stmt);
8791 if (name)
8793 tree decl;
8794 splay_tree_node n;
8796 if (!critical_name_mutexes)
8797 critical_name_mutexes
8798 = splay_tree_new_ggc (splay_tree_compare_pointers,
8799 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
8800 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
8802 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
8803 if (n == NULL)
8805 char *new_str;
8807 decl = create_tmp_var_raw (ptr_type_node, NULL);
8809 new_str = ACONCAT ((".gomp_critical_user_",
8810 IDENTIFIER_POINTER (name), NULL));
8811 DECL_NAME (decl) = get_identifier (new_str);
8812 TREE_PUBLIC (decl) = 1;
8813 TREE_STATIC (decl) = 1;
8814 DECL_COMMON (decl) = 1;
8815 DECL_ARTIFICIAL (decl) = 1;
8816 DECL_IGNORED_P (decl) = 1;
8817 varpool_finalize_decl (decl);
8819 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
8820 (splay_tree_value) decl);
8822 else
8823 decl = (tree) n->value;
8825 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
8826 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
8828 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
8829 unlock = build_call_expr_loc (loc, unlock, 1,
8830 build_fold_addr_expr_loc (loc, decl));
8832 else
8834 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
8835 lock = build_call_expr_loc (loc, lock, 0);
8837 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
8838 unlock = build_call_expr_loc (loc, unlock, 0);
8841 push_gimplify_context ();
8843 block = make_node (BLOCK);
8844 bind = gimple_build_bind (NULL, NULL, block);
8845 gsi_replace (gsi_p, bind, true);
8846 gimple_bind_add_stmt (bind, stmt);
8848 tbody = gimple_bind_body (bind);
8849 gimplify_and_add (lock, &tbody);
8850 gimple_bind_set_body (bind, tbody);
8852 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8853 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8854 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8855 gimple_omp_set_body (stmt, NULL);
8857 tbody = gimple_bind_body (bind);
8858 gimplify_and_add (unlock, &tbody);
8859 gimple_bind_set_body (bind, tbody);
8861 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8863 pop_gimplify_context (bind);
8864 gimple_bind_append_vars (bind, ctx->block_vars);
8865 BLOCK_VARS (block) = gimple_bind_vars (bind);
8869 /* A subroutine of lower_omp_for. Generate code to emit the predicate
8870 for a lastprivate clause. Given a loop control predicate of (V
8871 cond N2), we gate the clause on (!(V cond N2)). The lowered form
8872 is appended to *DLIST, iterator initialization is appended to
8873 *BODY_P. */
8875 static void
8876 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
8877 gimple_seq *dlist, struct omp_context *ctx)
8879 tree clauses, cond, vinit;
8880 enum tree_code cond_code;
8881 gimple_seq stmts;
8883 cond_code = fd->loop.cond_code;
8884 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
8886 /* When possible, use a strict equality expression. This can let VRP
8887 type optimizations deduce the value and remove a copy. */
8888 if (tree_fits_shwi_p (fd->loop.step))
8890 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
8891 if (step == 1 || step == -1)
8892 cond_code = EQ_EXPR;
8895 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
8897 clauses = gimple_omp_for_clauses (fd->for_stmt);
8898 stmts = NULL;
8899 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
8900 if (!gimple_seq_empty_p (stmts))
8902 gimple_seq_add_seq (&stmts, *dlist);
8903 *dlist = stmts;
8905 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
8906 vinit = fd->loop.n1;
8907 if (cond_code == EQ_EXPR
8908 && tree_fits_shwi_p (fd->loop.n2)
8909 && ! integer_zerop (fd->loop.n2))
8910 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
8911 else
8912 vinit = unshare_expr (vinit);
8914 /* Initialize the iterator variable, so that threads that don't execute
8915 any iterations don't execute the lastprivate clauses by accident. */
8916 gimplify_assign (fd->loop.v, vinit, body_p);
8921 /* Lower code for an OpenMP loop directive. */
8923 static void
8924 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8926 tree *rhs_p, block;
8927 struct omp_for_data fd, *fdp = NULL;
8928 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
8929 gimple_seq omp_for_body, body, dlist;
8930 size_t i;
8932 push_gimplify_context ();
8934 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
8936 block = make_node (BLOCK);
8937 new_stmt = gimple_build_bind (NULL, NULL, block);
8938 /* Replace at gsi right away, so that 'stmt' is no member
8939 of a sequence anymore as we're going to add to to a different
8940 one below. */
8941 gsi_replace (gsi_p, new_stmt, true);
8943 /* Move declaration of temporaries in the loop body before we make
8944 it go away. */
8945 omp_for_body = gimple_omp_body (stmt);
8946 if (!gimple_seq_empty_p (omp_for_body)
8947 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
8949 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
8950 tree vars = gimple_bind_vars (inner_bind);
8951 gimple_bind_append_vars (new_stmt, vars);
8952 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
8953 keep them on the inner_bind and it's block. */
8954 gimple_bind_set_vars (inner_bind, NULL_TREE);
8955 if (gimple_bind_block (inner_bind))
8956 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
8959 if (gimple_omp_for_combined_into_p (stmt))
8961 extract_omp_for_data (stmt, &fd, NULL);
8962 fdp = &fd;
8964 /* We need two temporaries with fd.loop.v type (istart/iend)
8965 and then (fd.collapse - 1) temporaries with the same
8966 type for count2 ... countN-1 vars if not constant. */
8967 size_t count = 2;
8968 tree type = fd.iter_type;
8969 if (fd.collapse > 1
8970 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
8971 count += fd.collapse - 1;
8972 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
8973 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
8974 tree clauses = *pc;
8975 if (parallel_for)
8976 outerc
8977 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
8978 OMP_CLAUSE__LOOPTEMP_);
8979 for (i = 0; i < count; i++)
8981 tree temp;
8982 if (parallel_for)
8984 gcc_assert (outerc);
8985 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
8986 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
8987 OMP_CLAUSE__LOOPTEMP_);
8989 else
8990 temp = create_tmp_var (type, NULL);
8991 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
8992 OMP_CLAUSE_DECL (*pc) = temp;
8993 pc = &OMP_CLAUSE_CHAIN (*pc);
8995 *pc = clauses;
8998 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
8999 dlist = NULL;
9000 body = NULL;
9001 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9002 fdp);
9003 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9005 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9007 /* Lower the header expressions. At this point, we can assume that
9008 the header is of the form:
9010 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9012 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9013 using the .omp_data_s mapping, if needed. */
9014 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9016 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9017 if (!is_gimple_min_invariant (*rhs_p))
9018 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9020 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9021 if (!is_gimple_min_invariant (*rhs_p))
9022 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9024 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9025 if (!is_gimple_min_invariant (*rhs_p))
9026 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9029 /* Once lowered, extract the bounds and clauses. */
9030 extract_omp_for_data (stmt, &fd, NULL);
9032 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9034 gimple_seq_add_stmt (&body, stmt);
9035 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9037 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9038 fd.loop.v));
9040 /* After the loop, add exit clauses. */
9041 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9043 if (ctx->cancellable)
9044 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9046 gimple_seq_add_seq (&body, dlist);
9048 body = maybe_catch_exception (body);
9050 /* Region exit marker goes at the end of the loop body. */
9051 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9052 maybe_add_implicit_barrier_cancel (ctx, &body);
9053 pop_gimplify_context (new_stmt);
9055 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9056 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9057 if (BLOCK_VARS (block))
9058 TREE_USED (block) = 1;
9060 gimple_bind_set_body (new_stmt, body);
9061 gimple_omp_set_body (stmt, NULL);
9062 gimple_omp_for_set_pre_body (stmt, NULL);
9065 /* Callback for walk_stmts. Check if the current statement only contains
9066 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9068 static tree
9069 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9070 bool *handled_ops_p,
9071 struct walk_stmt_info *wi)
9073 int *info = (int *) wi->info;
9074 gimple stmt = gsi_stmt (*gsi_p);
9076 *handled_ops_p = true;
9077 switch (gimple_code (stmt))
9079 WALK_SUBSTMTS;
9081 case GIMPLE_OMP_FOR:
9082 case GIMPLE_OMP_SECTIONS:
9083 *info = *info == 0 ? 1 : -1;
9084 break;
9085 default:
9086 *info = -1;
9087 break;
9089 return NULL;
9092 struct omp_taskcopy_context
9094 /* This field must be at the beginning, as we do "inheritance": Some
9095 callback functions for tree-inline.c (e.g., omp_copy_decl)
9096 receive a copy_body_data pointer that is up-casted to an
9097 omp_context pointer. */
9098 copy_body_data cb;
9099 omp_context *ctx;
9102 static tree
9103 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9105 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9107 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9108 return create_tmp_var (TREE_TYPE (var), NULL);
9110 return var;
9113 static tree
9114 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9116 tree name, new_fields = NULL, type, f;
9118 type = lang_hooks.types.make_type (RECORD_TYPE);
9119 name = DECL_NAME (TYPE_NAME (orig_type));
9120 name = build_decl (gimple_location (tcctx->ctx->stmt),
9121 TYPE_DECL, name, type);
9122 TYPE_NAME (type) = name;
9124 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9126 tree new_f = copy_node (f);
9127 DECL_CONTEXT (new_f) = type;
9128 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9129 TREE_CHAIN (new_f) = new_fields;
9130 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9131 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9132 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9133 &tcctx->cb, NULL);
9134 new_fields = new_f;
9135 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
9137 TYPE_FIELDS (type) = nreverse (new_fields);
9138 layout_type (type);
9139 return type;
9142 /* Create task copyfn. */
9144 static void
9145 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9147 struct function *child_cfun;
9148 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9149 tree record_type, srecord_type, bind, list;
9150 bool record_needs_remap = false, srecord_needs_remap = false;
9151 splay_tree_node n;
9152 struct omp_taskcopy_context tcctx;
9153 location_t loc = gimple_location (task_stmt);
9155 child_fn = gimple_omp_task_copy_fn (task_stmt);
9156 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9157 gcc_assert (child_cfun->cfg == NULL);
9158 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9160 /* Reset DECL_CONTEXT on function arguments. */
9161 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9162 DECL_CONTEXT (t) = child_fn;
9164 /* Populate the function. */
9165 push_gimplify_context ();
9166 push_cfun (child_cfun);
9168 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9169 TREE_SIDE_EFFECTS (bind) = 1;
9170 list = NULL;
9171 DECL_SAVED_TREE (child_fn) = bind;
9172 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9174 /* Remap src and dst argument types if needed. */
9175 record_type = ctx->record_type;
9176 srecord_type = ctx->srecord_type;
9177 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9178 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9180 record_needs_remap = true;
9181 break;
9183 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9184 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9186 srecord_needs_remap = true;
9187 break;
9190 if (record_needs_remap || srecord_needs_remap)
9192 memset (&tcctx, '\0', sizeof (tcctx));
9193 tcctx.cb.src_fn = ctx->cb.src_fn;
9194 tcctx.cb.dst_fn = child_fn;
9195 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
9196 gcc_checking_assert (tcctx.cb.src_node);
9197 tcctx.cb.dst_node = tcctx.cb.src_node;
9198 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9199 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9200 tcctx.cb.eh_lp_nr = 0;
9201 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9202 tcctx.cb.decl_map = pointer_map_create ();
9203 tcctx.ctx = ctx;
9205 if (record_needs_remap)
9206 record_type = task_copyfn_remap_type (&tcctx, record_type);
9207 if (srecord_needs_remap)
9208 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9210 else
9211 tcctx.cb.decl_map = NULL;
9213 arg = DECL_ARGUMENTS (child_fn);
9214 TREE_TYPE (arg) = build_pointer_type (record_type);
9215 sarg = DECL_CHAIN (arg);
9216 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9218 /* First pass: initialize temporaries used in record_type and srecord_type
9219 sizes and field offsets. */
9220 if (tcctx.cb.decl_map)
9221 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9222 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9224 tree *p;
9226 decl = OMP_CLAUSE_DECL (c);
9227 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
9228 if (p == NULL)
9229 continue;
9230 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9231 sf = (tree) n->value;
9232 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9233 src = build_simple_mem_ref_loc (loc, sarg);
9234 src = omp_build_component_ref (src, sf);
9235 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9236 append_to_statement_list (t, &list);
9239 /* Second pass: copy shared var pointers and copy construct non-VLA
9240 firstprivate vars. */
9241 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9242 switch (OMP_CLAUSE_CODE (c))
9244 case OMP_CLAUSE_SHARED:
9245 decl = OMP_CLAUSE_DECL (c);
9246 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9247 if (n == NULL)
9248 break;
9249 f = (tree) n->value;
9250 if (tcctx.cb.decl_map)
9251 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9252 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9253 sf = (tree) n->value;
9254 if (tcctx.cb.decl_map)
9255 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9256 src = build_simple_mem_ref_loc (loc, sarg);
9257 src = omp_build_component_ref (src, sf);
9258 dst = build_simple_mem_ref_loc (loc, arg);
9259 dst = omp_build_component_ref (dst, f);
9260 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9261 append_to_statement_list (t, &list);
9262 break;
9263 case OMP_CLAUSE_FIRSTPRIVATE:
9264 decl = OMP_CLAUSE_DECL (c);
9265 if (is_variable_sized (decl))
9266 break;
9267 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9268 if (n == NULL)
9269 break;
9270 f = (tree) n->value;
9271 if (tcctx.cb.decl_map)
9272 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9273 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9274 if (n != NULL)
9276 sf = (tree) n->value;
9277 if (tcctx.cb.decl_map)
9278 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9279 src = build_simple_mem_ref_loc (loc, sarg);
9280 src = omp_build_component_ref (src, sf);
9281 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9282 src = build_simple_mem_ref_loc (loc, src);
9284 else
9285 src = decl;
9286 dst = build_simple_mem_ref_loc (loc, arg);
9287 dst = omp_build_component_ref (dst, f);
9288 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9289 append_to_statement_list (t, &list);
9290 break;
9291 case OMP_CLAUSE_PRIVATE:
9292 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9293 break;
9294 decl = OMP_CLAUSE_DECL (c);
9295 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9296 f = (tree) n->value;
9297 if (tcctx.cb.decl_map)
9298 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9299 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9300 if (n != NULL)
9302 sf = (tree) n->value;
9303 if (tcctx.cb.decl_map)
9304 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9305 src = build_simple_mem_ref_loc (loc, sarg);
9306 src = omp_build_component_ref (src, sf);
9307 if (use_pointer_for_field (decl, NULL))
9308 src = build_simple_mem_ref_loc (loc, src);
9310 else
9311 src = decl;
9312 dst = build_simple_mem_ref_loc (loc, arg);
9313 dst = omp_build_component_ref (dst, f);
9314 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9315 append_to_statement_list (t, &list);
9316 break;
9317 default:
9318 break;
9321 /* Last pass: handle VLA firstprivates. */
9322 if (tcctx.cb.decl_map)
9323 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9324 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9326 tree ind, ptr, df;
9328 decl = OMP_CLAUSE_DECL (c);
9329 if (!is_variable_sized (decl))
9330 continue;
9331 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9332 if (n == NULL)
9333 continue;
9334 f = (tree) n->value;
9335 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9336 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9337 ind = DECL_VALUE_EXPR (decl);
9338 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9339 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9340 n = splay_tree_lookup (ctx->sfield_map,
9341 (splay_tree_key) TREE_OPERAND (ind, 0));
9342 sf = (tree) n->value;
9343 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9344 src = build_simple_mem_ref_loc (loc, sarg);
9345 src = omp_build_component_ref (src, sf);
9346 src = build_simple_mem_ref_loc (loc, src);
9347 dst = build_simple_mem_ref_loc (loc, arg);
9348 dst = omp_build_component_ref (dst, f);
9349 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9350 append_to_statement_list (t, &list);
9351 n = splay_tree_lookup (ctx->field_map,
9352 (splay_tree_key) TREE_OPERAND (ind, 0));
9353 df = (tree) n->value;
9354 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
9355 ptr = build_simple_mem_ref_loc (loc, arg);
9356 ptr = omp_build_component_ref (ptr, df);
9357 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9358 build_fold_addr_expr_loc (loc, dst));
9359 append_to_statement_list (t, &list);
9362 t = build1 (RETURN_EXPR, void_type_node, NULL);
9363 append_to_statement_list (t, &list);
9365 if (tcctx.cb.decl_map)
9366 pointer_map_destroy (tcctx.cb.decl_map);
9367 pop_gimplify_context (NULL);
9368 BIND_EXPR_BODY (bind) = list;
9369 pop_cfun ();
9372 static void
9373 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9375 tree c, clauses;
9376 gimple g;
9377 size_t n_in = 0, n_out = 0, idx = 2, i;
9379 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9380 OMP_CLAUSE_DEPEND);
9381 gcc_assert (clauses);
9382 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9383 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9384 switch (OMP_CLAUSE_DEPEND_KIND (c))
9386 case OMP_CLAUSE_DEPEND_IN:
9387 n_in++;
9388 break;
9389 case OMP_CLAUSE_DEPEND_OUT:
9390 case OMP_CLAUSE_DEPEND_INOUT:
9391 n_out++;
9392 break;
9393 default:
9394 gcc_unreachable ();
9396 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9397 tree array = create_tmp_var (type, NULL);
9398 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9399 NULL_TREE);
9400 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9401 gimple_seq_add_stmt (iseq, g);
9402 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9403 NULL_TREE);
9404 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9405 gimple_seq_add_stmt (iseq, g);
9406 for (i = 0; i < 2; i++)
9408 if ((i ? n_in : n_out) == 0)
9409 continue;
9410 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9411 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9412 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9414 tree t = OMP_CLAUSE_DECL (c);
9415 t = fold_convert (ptr_type_node, t);
9416 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9417 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9418 NULL_TREE, NULL_TREE);
9419 g = gimple_build_assign (r, t);
9420 gimple_seq_add_stmt (iseq, g);
9423 tree *p = gimple_omp_task_clauses_ptr (stmt);
9424 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9425 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9426 OMP_CLAUSE_CHAIN (c) = *p;
9427 *p = c;
9428 tree clobber = build_constructor (type, NULL);
9429 TREE_THIS_VOLATILE (clobber) = 1;
9430 g = gimple_build_assign (array, clobber);
9431 gimple_seq_add_stmt (oseq, g);
9434 /* Lower the OpenMP parallel or task directive in the current statement
9435 in GSI_P. CTX holds context information for the directive. */
9437 static void
9438 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9440 tree clauses;
9441 tree child_fn, t;
9442 gimple stmt = gsi_stmt (*gsi_p);
9443 gimple par_bind, bind, dep_bind = NULL;
9444 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9445 location_t loc = gimple_location (stmt);
9447 clauses = gimple_omp_taskreg_clauses (stmt);
9448 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9449 par_body = gimple_bind_body (par_bind);
9450 child_fn = ctx->cb.dst_fn;
9451 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9452 && !gimple_omp_parallel_combined_p (stmt))
9454 struct walk_stmt_info wi;
9455 int ws_num = 0;
9457 memset (&wi, 0, sizeof (wi));
9458 wi.info = &ws_num;
9459 wi.val_only = true;
9460 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9461 if (ws_num == 1)
9462 gimple_omp_parallel_set_combined_p (stmt, true);
9464 gimple_seq dep_ilist = NULL;
9465 gimple_seq dep_olist = NULL;
9466 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9467 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9469 push_gimplify_context ();
9470 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9471 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9474 if (ctx->srecord_type)
9475 create_task_copyfn (stmt, ctx);
9477 push_gimplify_context ();
9479 par_olist = NULL;
9480 par_ilist = NULL;
9481 par_rlist = NULL;
9482 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9483 lower_omp (&par_body, ctx);
9484 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9485 lower_reduction_clauses (clauses, &par_rlist, ctx);
9487 /* Declare all the variables created by mapping and the variables
9488 declared in the scope of the parallel body. */
9489 record_vars_into (ctx->block_vars, child_fn);
9490 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9492 if (ctx->record_type)
9494 ctx->sender_decl
9495 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9496 : ctx->record_type, ".omp_data_o");
9497 DECL_NAMELESS (ctx->sender_decl) = 1;
9498 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9499 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9502 olist = NULL;
9503 ilist = NULL;
9504 lower_send_clauses (clauses, &ilist, &olist, ctx);
9505 lower_send_shared_vars (&ilist, &olist, ctx);
9507 if (ctx->record_type)
9509 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9510 TREE_THIS_VOLATILE (clobber) = 1;
9511 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9512 clobber));
9515 /* Once all the expansions are done, sequence all the different
9516 fragments inside gimple_omp_body. */
9518 new_body = NULL;
9520 if (ctx->record_type)
9522 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9523 /* fixup_child_record_type might have changed receiver_decl's type. */
9524 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9525 gimple_seq_add_stmt (&new_body,
9526 gimple_build_assign (ctx->receiver_decl, t));
9529 gimple_seq_add_seq (&new_body, par_ilist);
9530 gimple_seq_add_seq (&new_body, par_body);
9531 gimple_seq_add_seq (&new_body, par_rlist);
9532 if (ctx->cancellable)
9533 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9534 gimple_seq_add_seq (&new_body, par_olist);
9535 new_body = maybe_catch_exception (new_body);
9536 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9537 gimple_omp_set_body (stmt, new_body);
9539 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9540 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
9541 gimple_bind_add_seq (bind, ilist);
9542 gimple_bind_add_stmt (bind, stmt);
9543 gimple_bind_add_seq (bind, olist);
9545 pop_gimplify_context (NULL);
9547 if (dep_bind)
9549 gimple_bind_add_seq (dep_bind, dep_ilist);
9550 gimple_bind_add_stmt (dep_bind, bind);
9551 gimple_bind_add_seq (dep_bind, dep_olist);
9552 pop_gimplify_context (dep_bind);
9556 /* Lower the OpenMP target directive in the current statement
9557 in GSI_P. CTX holds context information for the directive. */
9559 static void
9560 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9562 tree clauses;
9563 tree child_fn, t, c;
9564 gimple stmt = gsi_stmt (*gsi_p);
9565 gimple tgt_bind = NULL, bind;
9566 gimple_seq tgt_body = NULL, olist, ilist, new_body;
9567 location_t loc = gimple_location (stmt);
9568 int kind = gimple_omp_target_kind (stmt);
9569 unsigned int map_cnt = 0;
9571 clauses = gimple_omp_target_clauses (stmt);
9572 if (kind == GF_OMP_TARGET_KIND_REGION)
9574 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9575 tgt_body = gimple_bind_body (tgt_bind);
9577 else if (kind == GF_OMP_TARGET_KIND_DATA)
9578 tgt_body = gimple_omp_body (stmt);
9579 child_fn = ctx->cb.dst_fn;
9581 push_gimplify_context ();
9583 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9584 switch (OMP_CLAUSE_CODE (c))
9586 tree var, x;
9588 default:
9589 break;
9590 case OMP_CLAUSE_MAP:
9591 case OMP_CLAUSE_TO:
9592 case OMP_CLAUSE_FROM:
9593 var = OMP_CLAUSE_DECL (c);
9594 if (!DECL_P (var))
9596 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
9597 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9598 map_cnt++;
9599 continue;
9602 if (DECL_SIZE (var)
9603 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
9605 tree var2 = DECL_VALUE_EXPR (var);
9606 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
9607 var2 = TREE_OPERAND (var2, 0);
9608 gcc_assert (DECL_P (var2));
9609 var = var2;
9612 if (!maybe_lookup_field (var, ctx))
9613 continue;
9615 if (kind == GF_OMP_TARGET_KIND_REGION)
9617 x = build_receiver_ref (var, true, ctx);
9618 tree new_var = lookup_decl (var, ctx);
9619 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9620 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9621 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9622 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
9623 x = build_simple_mem_ref (x);
9624 SET_DECL_VALUE_EXPR (new_var, x);
9625 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
9627 map_cnt++;
9630 if (kind == GF_OMP_TARGET_KIND_REGION)
9632 target_nesting_level++;
9633 lower_omp (&tgt_body, ctx);
9634 target_nesting_level--;
9636 else if (kind == GF_OMP_TARGET_KIND_DATA)
9637 lower_omp (&tgt_body, ctx);
9639 if (kind == GF_OMP_TARGET_KIND_REGION)
9641 /* Declare all the variables created by mapping and the variables
9642 declared in the scope of the target body. */
9643 record_vars_into (ctx->block_vars, child_fn);
9644 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
9647 olist = NULL;
9648 ilist = NULL;
9649 if (ctx->record_type)
9651 ctx->sender_decl
9652 = create_tmp_var (ctx->record_type, ".omp_data_arr");
9653 DECL_NAMELESS (ctx->sender_decl) = 1;
9654 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9655 t = make_tree_vec (3);
9656 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
9657 TREE_VEC_ELT (t, 1)
9658 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
9659 ".omp_data_sizes");
9660 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
9661 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
9662 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
9663 TREE_VEC_ELT (t, 2)
9664 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
9665 map_cnt),
9666 ".omp_data_kinds");
9667 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
9668 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
9669 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
9670 gimple_omp_target_set_data_arg (stmt, t);
9672 vec<constructor_elt, va_gc> *vsize;
9673 vec<constructor_elt, va_gc> *vkind;
9674 vec_alloc (vsize, map_cnt);
9675 vec_alloc (vkind, map_cnt);
9676 unsigned int map_idx = 0;
9678 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9679 switch (OMP_CLAUSE_CODE (c))
9681 tree ovar, nc;
9683 default:
9684 break;
9685 case OMP_CLAUSE_MAP:
9686 case OMP_CLAUSE_TO:
9687 case OMP_CLAUSE_FROM:
9688 nc = c;
9689 ovar = OMP_CLAUSE_DECL (c);
9690 if (!DECL_P (ovar))
9692 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9693 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9695 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
9696 == get_base_address (ovar));
9697 nc = OMP_CLAUSE_CHAIN (c);
9698 ovar = OMP_CLAUSE_DECL (nc);
9700 else
9702 tree x = build_sender_ref (ovar, ctx);
9703 tree v
9704 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
9705 gimplify_assign (x, v, &ilist);
9706 nc = NULL_TREE;
9709 else
9711 if (DECL_SIZE (ovar)
9712 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
9714 tree ovar2 = DECL_VALUE_EXPR (ovar);
9715 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
9716 ovar2 = TREE_OPERAND (ovar2, 0);
9717 gcc_assert (DECL_P (ovar2));
9718 ovar = ovar2;
9720 if (!maybe_lookup_field (ovar, ctx))
9721 continue;
9724 if (nc)
9726 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
9727 tree x = build_sender_ref (ovar, ctx);
9728 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9729 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9730 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9731 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
9733 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9734 tree avar
9735 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
9736 mark_addressable (avar);
9737 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
9738 avar = build_fold_addr_expr (avar);
9739 gimplify_assign (x, avar, &ilist);
9741 else if (is_gimple_reg (var))
9743 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9744 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
9745 mark_addressable (avar);
9746 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
9747 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
9748 gimplify_assign (avar, var, &ilist);
9749 avar = build_fold_addr_expr (avar);
9750 gimplify_assign (x, avar, &ilist);
9751 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
9752 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
9753 && !TYPE_READONLY (TREE_TYPE (var)))
9755 x = build_sender_ref (ovar, ctx);
9756 x = build_simple_mem_ref (x);
9757 gimplify_assign (var, x, &olist);
9760 else
9762 var = build_fold_addr_expr (var);
9763 gimplify_assign (x, var, &ilist);
9766 tree s = OMP_CLAUSE_SIZE (c);
9767 if (s == NULL_TREE)
9768 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
9769 s = fold_convert (size_type_node, s);
9770 tree purpose = size_int (map_idx++);
9771 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
9772 if (TREE_CODE (s) != INTEGER_CST)
9773 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
9775 unsigned char tkind = 0;
9776 switch (OMP_CLAUSE_CODE (c))
9778 case OMP_CLAUSE_MAP:
9779 tkind = OMP_CLAUSE_MAP_KIND (c);
9780 break;
9781 case OMP_CLAUSE_TO:
9782 tkind = OMP_CLAUSE_MAP_TO;
9783 break;
9784 case OMP_CLAUSE_FROM:
9785 tkind = OMP_CLAUSE_MAP_FROM;
9786 break;
9787 default:
9788 gcc_unreachable ();
9790 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
9791 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
9792 talign = DECL_ALIGN_UNIT (ovar);
9793 talign = ceil_log2 (talign);
9794 tkind |= talign << 3;
9795 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
9796 build_int_cst (unsigned_char_type_node,
9797 tkind));
9798 if (nc && nc != c)
9799 c = nc;
9802 gcc_assert (map_idx == map_cnt);
9804 DECL_INITIAL (TREE_VEC_ELT (t, 1))
9805 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
9806 DECL_INITIAL (TREE_VEC_ELT (t, 2))
9807 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
9808 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
9810 gimple_seq initlist = NULL;
9811 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
9812 TREE_VEC_ELT (t, 1)),
9813 &initlist, true, NULL_TREE);
9814 gimple_seq_add_seq (&ilist, initlist);
9816 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
9817 NULL);
9818 TREE_THIS_VOLATILE (clobber) = 1;
9819 gimple_seq_add_stmt (&olist,
9820 gimple_build_assign (TREE_VEC_ELT (t, 1),
9821 clobber));
9824 tree clobber = build_constructor (ctx->record_type, NULL);
9825 TREE_THIS_VOLATILE (clobber) = 1;
9826 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9827 clobber));
9830 /* Once all the expansions are done, sequence all the different
9831 fragments inside gimple_omp_body. */
9833 new_body = NULL;
9835 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
9837 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9838 /* fixup_child_record_type might have changed receiver_decl's type. */
9839 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9840 gimple_seq_add_stmt (&new_body,
9841 gimple_build_assign (ctx->receiver_decl, t));
9844 if (kind == GF_OMP_TARGET_KIND_REGION)
9846 gimple_seq_add_seq (&new_body, tgt_body);
9847 new_body = maybe_catch_exception (new_body);
9849 else if (kind == GF_OMP_TARGET_KIND_DATA)
9850 new_body = tgt_body;
9851 if (kind != GF_OMP_TARGET_KIND_UPDATE)
9853 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9854 gimple_omp_set_body (stmt, new_body);
9857 bind = gimple_build_bind (NULL, NULL,
9858 tgt_bind ? gimple_bind_block (tgt_bind)
9859 : NULL_TREE);
9860 gsi_replace (gsi_p, bind, true);
9861 gimple_bind_add_seq (bind, ilist);
9862 gimple_bind_add_stmt (bind, stmt);
9863 gimple_bind_add_seq (bind, olist);
9865 pop_gimplify_context (NULL);
9868 /* Expand code for an OpenMP teams directive. */
9870 static void
9871 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9873 gimple teams_stmt = gsi_stmt (*gsi_p);
9874 push_gimplify_context ();
9876 tree block = make_node (BLOCK);
9877 gimple bind = gimple_build_bind (NULL, NULL, block);
9878 gsi_replace (gsi_p, bind, true);
9879 gimple_seq bind_body = NULL;
9880 gimple_seq dlist = NULL;
9881 gimple_seq olist = NULL;
9883 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9884 OMP_CLAUSE_NUM_TEAMS);
9885 if (num_teams == NULL_TREE)
9886 num_teams = build_int_cst (unsigned_type_node, 0);
9887 else
9889 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
9890 num_teams = fold_convert (unsigned_type_node, num_teams);
9891 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
9893 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9894 OMP_CLAUSE_THREAD_LIMIT);
9895 if (thread_limit == NULL_TREE)
9896 thread_limit = build_int_cst (unsigned_type_node, 0);
9897 else
9899 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
9900 thread_limit = fold_convert (unsigned_type_node, thread_limit);
9901 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
9902 fb_rvalue);
9905 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
9906 &bind_body, &dlist, ctx, NULL);
9907 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
9908 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
9909 gimple_seq_add_stmt (&bind_body, teams_stmt);
9911 location_t loc = gimple_location (teams_stmt);
9912 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
9913 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
9914 gimple_set_location (call, loc);
9915 gimple_seq_add_stmt (&bind_body, call);
9917 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
9918 gimple_omp_set_body (teams_stmt, NULL);
9919 gimple_seq_add_seq (&bind_body, olist);
9920 gimple_seq_add_seq (&bind_body, dlist);
9921 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
9922 gimple_bind_set_body (bind, bind_body);
9924 pop_gimplify_context (bind);
9926 gimple_bind_append_vars (bind, ctx->block_vars);
9927 BLOCK_VARS (block) = ctx->block_vars;
9928 if (BLOCK_VARS (block))
9929 TREE_USED (block) = 1;
9933 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
9934 regimplified. If DATA is non-NULL, lower_omp_1 is outside
9935 of OpenMP context, but with task_shared_vars set. */
9937 static tree
9938 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
9939 void *data)
9941 tree t = *tp;
9943 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
9944 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9945 return t;
9947 if (task_shared_vars
9948 && DECL_P (t)
9949 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
9950 return t;
9952 /* If a global variable has been privatized, TREE_CONSTANT on
9953 ADDR_EXPR might be wrong. */
9954 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
9955 recompute_tree_invariant_for_addr_expr (t);
9957 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
9958 return NULL_TREE;
9961 static void
9962 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9964 gimple stmt = gsi_stmt (*gsi_p);
9965 struct walk_stmt_info wi;
9967 if (gimple_has_location (stmt))
9968 input_location = gimple_location (stmt);
9970 if (task_shared_vars)
9971 memset (&wi, '\0', sizeof (wi));
9973 /* If we have issued syntax errors, avoid doing any heavy lifting.
9974 Just replace the OpenMP directives with a NOP to avoid
9975 confusing RTL expansion. */
9976 if (seen_error () && is_gimple_omp (stmt))
9978 gsi_replace (gsi_p, gimple_build_nop (), true);
9979 return;
9982 switch (gimple_code (stmt))
9984 case GIMPLE_COND:
9985 if ((ctx || task_shared_vars)
9986 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
9987 ctx ? NULL : &wi, NULL)
9988 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
9989 ctx ? NULL : &wi, NULL)))
9990 gimple_regimplify_operands (stmt, gsi_p);
9991 break;
9992 case GIMPLE_CATCH:
9993 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
9994 break;
9995 case GIMPLE_EH_FILTER:
9996 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
9997 break;
9998 case GIMPLE_TRY:
9999 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10000 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10001 break;
10002 case GIMPLE_TRANSACTION:
10003 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
10004 break;
10005 case GIMPLE_BIND:
10006 lower_omp (gimple_bind_body_ptr (stmt), ctx);
10007 break;
10008 case GIMPLE_OMP_PARALLEL:
10009 case GIMPLE_OMP_TASK:
10010 ctx = maybe_lookup_ctx (stmt);
10011 gcc_assert (ctx);
10012 if (ctx->cancellable)
10013 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10014 lower_omp_taskreg (gsi_p, ctx);
10015 break;
10016 case GIMPLE_OMP_FOR:
10017 ctx = maybe_lookup_ctx (stmt);
10018 gcc_assert (ctx);
10019 if (ctx->cancellable)
10020 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10021 lower_omp_for (gsi_p, ctx);
10022 break;
10023 case GIMPLE_OMP_SECTIONS:
10024 ctx = maybe_lookup_ctx (stmt);
10025 gcc_assert (ctx);
10026 if (ctx->cancellable)
10027 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10028 lower_omp_sections (gsi_p, ctx);
10029 break;
10030 case GIMPLE_OMP_SINGLE:
10031 ctx = maybe_lookup_ctx (stmt);
10032 gcc_assert (ctx);
10033 lower_omp_single (gsi_p, ctx);
10034 break;
10035 case GIMPLE_OMP_MASTER:
10036 ctx = maybe_lookup_ctx (stmt);
10037 gcc_assert (ctx);
10038 lower_omp_master (gsi_p, ctx);
10039 break;
10040 case GIMPLE_OMP_TASKGROUP:
10041 ctx = maybe_lookup_ctx (stmt);
10042 gcc_assert (ctx);
10043 lower_omp_taskgroup (gsi_p, ctx);
10044 break;
10045 case GIMPLE_OMP_ORDERED:
10046 ctx = maybe_lookup_ctx (stmt);
10047 gcc_assert (ctx);
10048 lower_omp_ordered (gsi_p, ctx);
10049 break;
10050 case GIMPLE_OMP_CRITICAL:
10051 ctx = maybe_lookup_ctx (stmt);
10052 gcc_assert (ctx);
10053 lower_omp_critical (gsi_p, ctx);
10054 break;
10055 case GIMPLE_OMP_ATOMIC_LOAD:
10056 if ((ctx || task_shared_vars)
10057 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
10058 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10059 gimple_regimplify_operands (stmt, gsi_p);
10060 break;
10061 case GIMPLE_OMP_TARGET:
10062 ctx = maybe_lookup_ctx (stmt);
10063 gcc_assert (ctx);
10064 lower_omp_target (gsi_p, ctx);
10065 break;
10066 case GIMPLE_OMP_TEAMS:
10067 ctx = maybe_lookup_ctx (stmt);
10068 gcc_assert (ctx);
10069 lower_omp_teams (gsi_p, ctx);
10070 break;
10071 case GIMPLE_CALL:
10072 tree fndecl;
10073 fndecl = gimple_call_fndecl (stmt);
10074 if (fndecl
10075 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10076 switch (DECL_FUNCTION_CODE (fndecl))
10078 case BUILT_IN_GOMP_BARRIER:
10079 if (ctx == NULL)
10080 break;
10081 /* FALLTHRU */
10082 case BUILT_IN_GOMP_CANCEL:
10083 case BUILT_IN_GOMP_CANCELLATION_POINT:
10084 omp_context *cctx;
10085 cctx = ctx;
10086 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10087 cctx = cctx->outer;
10088 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10089 if (!cctx->cancellable)
10091 if (DECL_FUNCTION_CODE (fndecl)
10092 == BUILT_IN_GOMP_CANCELLATION_POINT)
10094 stmt = gimple_build_nop ();
10095 gsi_replace (gsi_p, stmt, false);
10097 break;
10099 tree lhs;
10100 lhs = create_tmp_var (boolean_type_node, NULL);
10101 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10103 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10104 gimple_call_set_fndecl (stmt, fndecl);
10105 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10107 gimple_call_set_lhs (stmt, lhs);
10108 tree fallthru_label;
10109 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10110 gimple g;
10111 g = gimple_build_label (fallthru_label);
10112 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10113 g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
10114 cctx->cancel_label, fallthru_label);
10115 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10116 break;
10117 default:
10118 break;
10120 /* FALLTHRU */
10121 default:
10122 if ((ctx || task_shared_vars)
10123 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10124 ctx ? NULL : &wi))
10125 gimple_regimplify_operands (stmt, gsi_p);
10126 break;
10130 static void
10131 lower_omp (gimple_seq *body, omp_context *ctx)
10133 location_t saved_location = input_location;
10134 gimple_stmt_iterator gsi;
10135 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10136 lower_omp_1 (&gsi, ctx);
10137 /* During gimplification, we have not always invoked fold_stmt
10138 (gimplify.c:maybe_fold_stmt); call it now. */
10139 if (target_nesting_level)
10140 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10141 fold_stmt (&gsi);
10142 input_location = saved_location;
10145 /* Main entry point. */
10147 static unsigned int
10148 execute_lower_omp (void)
10150 gimple_seq body;
10152 /* This pass always runs, to provide PROP_gimple_lomp.
10153 But there is nothing to do unless -fopenmp is given. */
10154 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10155 return 0;
10157 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10158 delete_omp_context);
10160 body = gimple_body (current_function_decl);
10161 scan_omp (&body, NULL);
10162 gcc_assert (taskreg_nesting_level == 0);
10164 if (all_contexts->root)
10166 if (task_shared_vars)
10167 push_gimplify_context ();
10168 lower_omp (&body, NULL);
10169 if (task_shared_vars)
10170 pop_gimplify_context (NULL);
10173 if (all_contexts)
10175 splay_tree_delete (all_contexts);
10176 all_contexts = NULL;
10178 BITMAP_FREE (task_shared_vars);
10179 return 0;
10182 namespace {
10184 const pass_data pass_data_lower_omp =
10186 GIMPLE_PASS, /* type */
10187 "omplower", /* name */
10188 OPTGROUP_NONE, /* optinfo_flags */
10189 false, /* has_gate */
10190 true, /* has_execute */
10191 TV_NONE, /* tv_id */
10192 PROP_gimple_any, /* properties_required */
10193 PROP_gimple_lomp, /* properties_provided */
10194 0, /* properties_destroyed */
10195 0, /* todo_flags_start */
10196 0, /* todo_flags_finish */
10199 class pass_lower_omp : public gimple_opt_pass
10201 public:
10202 pass_lower_omp (gcc::context *ctxt)
10203 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10206 /* opt_pass methods: */
10207 unsigned int execute () { return execute_lower_omp (); }
10209 }; // class pass_lower_omp
10211 } // anon namespace
10213 gimple_opt_pass *
10214 make_pass_lower_omp (gcc::context *ctxt)
10216 return new pass_lower_omp (ctxt);
10219 /* The following is a utility to diagnose OpenMP structured block violations.
10220 It is not part of the "omplower" pass, as that's invoked too late. It
10221 should be invoked by the respective front ends after gimplification. */
10223 static splay_tree all_labels;
10225 /* Check for mismatched contexts and generate an error if needed. Return
10226 true if an error is detected. */
10228 static bool
10229 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10230 gimple branch_ctx, gimple label_ctx)
10232 if (label_ctx == branch_ctx)
10233 return false;
10237 Previously we kept track of the label's entire context in diagnose_sb_[12]
10238 so we could traverse it and issue a correct "exit" or "enter" error
10239 message upon a structured block violation.
10241 We built the context by building a list with tree_cons'ing, but there is
10242 no easy counterpart in gimple tuples. It seems like far too much work
10243 for issuing exit/enter error messages. If someone really misses the
10244 distinct error message... patches welcome.
10247 #if 0
10248 /* Try to avoid confusing the user by producing and error message
10249 with correct "exit" or "enter" verbiage. We prefer "exit"
10250 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10251 if (branch_ctx == NULL)
10252 exit_p = false;
10253 else
10255 while (label_ctx)
10257 if (TREE_VALUE (label_ctx) == branch_ctx)
10259 exit_p = false;
10260 break;
10262 label_ctx = TREE_CHAIN (label_ctx);
10266 if (exit_p)
10267 error ("invalid exit from OpenMP structured block");
10268 else
10269 error ("invalid entry to OpenMP structured block");
10270 #endif
10272 bool cilkplus_block = false;
10273 if (flag_cilkplus)
10275 if ((branch_ctx
10276 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10277 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10278 || (label_ctx
10279 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10280 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10281 cilkplus_block = true;
10284 /* If it's obvious we have an invalid entry, be specific about the error. */
10285 if (branch_ctx == NULL)
10287 if (cilkplus_block)
10288 error ("invalid entry to Cilk Plus structured block");
10289 else
10290 error ("invalid entry to OpenMP structured block");
10292 else
10294 /* Otherwise, be vague and lazy, but efficient. */
10295 if (cilkplus_block)
10296 error ("invalid branch to/from a Cilk Plus structured block");
10297 else
10298 error ("invalid branch to/from an OpenMP structured block");
10301 gsi_replace (gsi_p, gimple_build_nop (), false);
10302 return true;
10305 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10306 where each label is found. */
10308 static tree
10309 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10310 struct walk_stmt_info *wi)
10312 gimple context = (gimple) wi->info;
10313 gimple inner_context;
10314 gimple stmt = gsi_stmt (*gsi_p);
10316 *handled_ops_p = true;
10318 switch (gimple_code (stmt))
10320 WALK_SUBSTMTS;
10322 case GIMPLE_OMP_PARALLEL:
10323 case GIMPLE_OMP_TASK:
10324 case GIMPLE_OMP_SECTIONS:
10325 case GIMPLE_OMP_SINGLE:
10326 case GIMPLE_OMP_SECTION:
10327 case GIMPLE_OMP_MASTER:
10328 case GIMPLE_OMP_ORDERED:
10329 case GIMPLE_OMP_CRITICAL:
10330 case GIMPLE_OMP_TARGET:
10331 case GIMPLE_OMP_TEAMS:
10332 case GIMPLE_OMP_TASKGROUP:
10333 /* The minimal context here is just the current OMP construct. */
10334 inner_context = stmt;
10335 wi->info = inner_context;
10336 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10337 wi->info = context;
10338 break;
10340 case GIMPLE_OMP_FOR:
10341 inner_context = stmt;
10342 wi->info = inner_context;
10343 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10344 walk them. */
10345 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10346 diagnose_sb_1, NULL, wi);
10347 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10348 wi->info = context;
10349 break;
10351 case GIMPLE_LABEL:
10352 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10353 (splay_tree_value) context);
10354 break;
10356 default:
10357 break;
10360 return NULL_TREE;
10363 /* Pass 2: Check each branch and see if its context differs from that of
10364 the destination label's context. */
10366 static tree
10367 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10368 struct walk_stmt_info *wi)
10370 gimple context = (gimple) wi->info;
10371 splay_tree_node n;
10372 gimple stmt = gsi_stmt (*gsi_p);
10374 *handled_ops_p = true;
10376 switch (gimple_code (stmt))
10378 WALK_SUBSTMTS;
10380 case GIMPLE_OMP_PARALLEL:
10381 case GIMPLE_OMP_TASK:
10382 case GIMPLE_OMP_SECTIONS:
10383 case GIMPLE_OMP_SINGLE:
10384 case GIMPLE_OMP_SECTION:
10385 case GIMPLE_OMP_MASTER:
10386 case GIMPLE_OMP_ORDERED:
10387 case GIMPLE_OMP_CRITICAL:
10388 case GIMPLE_OMP_TARGET:
10389 case GIMPLE_OMP_TEAMS:
10390 case GIMPLE_OMP_TASKGROUP:
10391 wi->info = stmt;
10392 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10393 wi->info = context;
10394 break;
10396 case GIMPLE_OMP_FOR:
10397 wi->info = stmt;
10398 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10399 walk them. */
10400 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10401 diagnose_sb_2, NULL, wi);
10402 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10403 wi->info = context;
10404 break;
10406 case GIMPLE_COND:
10408 tree lab = gimple_cond_true_label (stmt);
10409 if (lab)
10411 n = splay_tree_lookup (all_labels,
10412 (splay_tree_key) lab);
10413 diagnose_sb_0 (gsi_p, context,
10414 n ? (gimple) n->value : NULL);
10416 lab = gimple_cond_false_label (stmt);
10417 if (lab)
10419 n = splay_tree_lookup (all_labels,
10420 (splay_tree_key) lab);
10421 diagnose_sb_0 (gsi_p, context,
10422 n ? (gimple) n->value : NULL);
10425 break;
10427 case GIMPLE_GOTO:
10429 tree lab = gimple_goto_dest (stmt);
10430 if (TREE_CODE (lab) != LABEL_DECL)
10431 break;
10433 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10434 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10436 break;
10438 case GIMPLE_SWITCH:
10440 unsigned int i;
10441 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10443 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10444 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10445 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10446 break;
10449 break;
10451 case GIMPLE_RETURN:
10452 diagnose_sb_0 (gsi_p, context, NULL);
10453 break;
10455 default:
10456 break;
10459 return NULL_TREE;
10462 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10463 codes. */
10464 bool
10465 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
10466 int *region_idx)
10468 gimple last = last_stmt (bb);
10469 enum gimple_code code = gimple_code (last);
10470 struct omp_region *cur_region = *region;
10471 bool fallthru = false;
10473 switch (code)
10475 case GIMPLE_OMP_PARALLEL:
10476 case GIMPLE_OMP_TASK:
10477 case GIMPLE_OMP_FOR:
10478 case GIMPLE_OMP_SINGLE:
10479 case GIMPLE_OMP_TEAMS:
10480 case GIMPLE_OMP_MASTER:
10481 case GIMPLE_OMP_TASKGROUP:
10482 case GIMPLE_OMP_ORDERED:
10483 case GIMPLE_OMP_CRITICAL:
10484 case GIMPLE_OMP_SECTION:
10485 cur_region = new_omp_region (bb, code, cur_region);
10486 fallthru = true;
10487 break;
10489 case GIMPLE_OMP_TARGET:
10490 cur_region = new_omp_region (bb, code, cur_region);
10491 fallthru = true;
10492 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10493 cur_region = cur_region->outer;
10494 break;
10496 case GIMPLE_OMP_SECTIONS:
10497 cur_region = new_omp_region (bb, code, cur_region);
10498 fallthru = true;
10499 break;
10501 case GIMPLE_OMP_SECTIONS_SWITCH:
10502 fallthru = false;
10503 break;
10505 case GIMPLE_OMP_ATOMIC_LOAD:
10506 case GIMPLE_OMP_ATOMIC_STORE:
10507 fallthru = true;
10508 break;
10510 case GIMPLE_OMP_RETURN:
10511 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10512 somewhere other than the next block. This will be
10513 created later. */
10514 cur_region->exit = bb;
10515 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
10516 cur_region = cur_region->outer;
10517 break;
10519 case GIMPLE_OMP_CONTINUE:
10520 cur_region->cont = bb;
10521 switch (cur_region->type)
10523 case GIMPLE_OMP_FOR:
10524 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
10525 succs edges as abnormal to prevent splitting
10526 them. */
10527 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
10528 /* Make the loopback edge. */
10529 make_edge (bb, single_succ (cur_region->entry),
10530 EDGE_ABNORMAL);
10532 /* Create an edge from GIMPLE_OMP_FOR to exit, which
10533 corresponds to the case that the body of the loop
10534 is not executed at all. */
10535 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
10536 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
10537 fallthru = false;
10538 break;
10540 case GIMPLE_OMP_SECTIONS:
10541 /* Wire up the edges into and out of the nested sections. */
10543 basic_block switch_bb = single_succ (cur_region->entry);
10545 struct omp_region *i;
10546 for (i = cur_region->inner; i ; i = i->next)
10548 gcc_assert (i->type == GIMPLE_OMP_SECTION);
10549 make_edge (switch_bb, i->entry, 0);
10550 make_edge (i->exit, bb, EDGE_FALLTHRU);
10553 /* Make the loopback edge to the block with
10554 GIMPLE_OMP_SECTIONS_SWITCH. */
10555 make_edge (bb, switch_bb, 0);
10557 /* Make the edge from the switch to exit. */
10558 make_edge (switch_bb, bb->next_bb, 0);
10559 fallthru = false;
10561 break;
10563 default:
10564 gcc_unreachable ();
10566 break;
10568 default:
10569 gcc_unreachable ();
10572 if (*region != cur_region)
10574 *region = cur_region;
10575 if (cur_region)
10576 *region_idx = cur_region->entry->index;
10577 else
10578 *region_idx = 0;
10581 return fallthru;
10584 static unsigned int
10585 diagnose_omp_structured_block_errors (void)
10587 struct walk_stmt_info wi;
10588 gimple_seq body = gimple_body (current_function_decl);
10590 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
10592 memset (&wi, 0, sizeof (wi));
10593 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
10595 memset (&wi, 0, sizeof (wi));
10596 wi.want_locations = true;
10597 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
10599 gimple_set_body (current_function_decl, body);
10601 splay_tree_delete (all_labels);
10602 all_labels = NULL;
10604 return 0;
10607 static bool
10608 gate_diagnose_omp_blocks (void)
10610 return flag_openmp || flag_cilkplus;
10613 namespace {
10615 const pass_data pass_data_diagnose_omp_blocks =
10617 GIMPLE_PASS, /* type */
10618 "*diagnose_omp_blocks", /* name */
10619 OPTGROUP_NONE, /* optinfo_flags */
10620 true, /* has_gate */
10621 true, /* has_execute */
10622 TV_NONE, /* tv_id */
10623 PROP_gimple_any, /* properties_required */
10624 0, /* properties_provided */
10625 0, /* properties_destroyed */
10626 0, /* todo_flags_start */
10627 0, /* todo_flags_finish */
10630 class pass_diagnose_omp_blocks : public gimple_opt_pass
10632 public:
10633 pass_diagnose_omp_blocks (gcc::context *ctxt)
10634 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
10637 /* opt_pass methods: */
10638 bool gate () { return gate_diagnose_omp_blocks (); }
10639 unsigned int execute () {
10640 return diagnose_omp_structured_block_errors ();
10643 }; // class pass_diagnose_omp_blocks
10645 } // anon namespace
10647 gimple_opt_pass *
10648 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
10650 return new pass_diagnose_omp_blocks (ctxt);
10653 /* SIMD clone supporting code. */
10655 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
10656 of arguments to reserve space for. */
10658 static struct cgraph_simd_clone *
10659 simd_clone_struct_alloc (int nargs)
10661 struct cgraph_simd_clone *clone_info;
10662 size_t len = (sizeof (struct cgraph_simd_clone)
10663 + nargs * sizeof (struct cgraph_simd_clone_arg));
10664 clone_info = (struct cgraph_simd_clone *)
10665 ggc_internal_cleared_alloc (len);
10666 return clone_info;
10669 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
10671 static inline void
10672 simd_clone_struct_copy (struct cgraph_simd_clone *to,
10673 struct cgraph_simd_clone *from)
10675 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
10676 + ((from->nargs - from->inbranch)
10677 * sizeof (struct cgraph_simd_clone_arg))));
10680 /* Return vector of parameter types of function FNDECL. This uses
10681 TYPE_ARG_TYPES if available, otherwise falls back to types of
10682 DECL_ARGUMENTS types. */
10684 vec<tree>
10685 simd_clone_vector_of_formal_parm_types (tree fndecl)
10687 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
10688 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
10689 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
10690 unsigned int i;
10691 tree arg;
10692 FOR_EACH_VEC_ELT (args, i, arg)
10693 args[i] = TREE_TYPE (args[i]);
10694 return args;
10697 /* Given a simd function in NODE, extract the simd specific
10698 information from the OMP clauses passed in CLAUSES, and return
10699 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
10700 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
10701 otherwise set to FALSE. */
10703 static struct cgraph_simd_clone *
10704 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
10705 bool *inbranch_specified)
10707 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
10708 tree t;
10709 int n;
10710 *inbranch_specified = false;
10712 n = args.length ();
10713 if (n > 0 && args.last () == void_type_node)
10714 n--;
10716 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
10717 be cloned have a distinctive artificial label in addition to "omp
10718 declare simd". */
10719 bool cilk_clone
10720 = (flag_cilkplus
10721 && lookup_attribute ("cilk simd function",
10722 DECL_ATTRIBUTES (node->decl)));
10724 /* Allocate one more than needed just in case this is an in-branch
10725 clone which will require a mask argument. */
10726 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
10727 clone_info->nargs = n;
10728 clone_info->cilk_elemental = cilk_clone;
10730 if (!clauses)
10732 args.release ();
10733 return clone_info;
10735 clauses = TREE_VALUE (clauses);
10736 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
10737 return clone_info;
10739 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
10741 switch (OMP_CLAUSE_CODE (t))
10743 case OMP_CLAUSE_INBRANCH:
10744 clone_info->inbranch = 1;
10745 *inbranch_specified = true;
10746 break;
10747 case OMP_CLAUSE_NOTINBRANCH:
10748 clone_info->inbranch = 0;
10749 *inbranch_specified = true;
10750 break;
10751 case OMP_CLAUSE_SIMDLEN:
10752 clone_info->simdlen
10753 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
10754 break;
10755 case OMP_CLAUSE_LINEAR:
10757 tree decl = OMP_CLAUSE_DECL (t);
10758 tree step = OMP_CLAUSE_LINEAR_STEP (t);
10759 int argno = TREE_INT_CST_LOW (decl);
10760 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
10762 clone_info->args[argno].arg_type
10763 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
10764 clone_info->args[argno].linear_step = tree_to_shwi (step);
10765 gcc_assert (clone_info->args[argno].linear_step >= 0
10766 && clone_info->args[argno].linear_step < n);
10768 else
10770 if (POINTER_TYPE_P (args[argno]))
10771 step = fold_convert (ssizetype, step);
10772 if (!tree_fits_shwi_p (step))
10774 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10775 "ignoring large linear step");
10776 args.release ();
10777 return NULL;
10779 else if (integer_zerop (step))
10781 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10782 "ignoring zero linear step");
10783 args.release ();
10784 return NULL;
10786 else
10788 clone_info->args[argno].arg_type
10789 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
10790 clone_info->args[argno].linear_step = tree_to_shwi (step);
10793 break;
10795 case OMP_CLAUSE_UNIFORM:
10797 tree decl = OMP_CLAUSE_DECL (t);
10798 int argno = tree_to_uhwi (decl);
10799 clone_info->args[argno].arg_type
10800 = SIMD_CLONE_ARG_TYPE_UNIFORM;
10801 break;
10803 case OMP_CLAUSE_ALIGNED:
10805 tree decl = OMP_CLAUSE_DECL (t);
10806 int argno = tree_to_uhwi (decl);
10807 clone_info->args[argno].alignment
10808 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
10809 break;
10811 default:
10812 break;
10815 args.release ();
10816 return clone_info;
10819 /* Given a SIMD clone in NODE, calculate the characteristic data
10820 type and return the coresponding type. The characteristic data
10821 type is computed as described in the Intel Vector ABI. */
10823 static tree
10824 simd_clone_compute_base_data_type (struct cgraph_node *node,
10825 struct cgraph_simd_clone *clone_info)
10827 tree type = integer_type_node;
10828 tree fndecl = node->decl;
10830 /* a) For non-void function, the characteristic data type is the
10831 return type. */
10832 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
10833 type = TREE_TYPE (TREE_TYPE (fndecl));
10835 /* b) If the function has any non-uniform, non-linear parameters,
10836 then the characteristic data type is the type of the first
10837 such parameter. */
10838 else
10840 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
10841 for (unsigned int i = 0; i < clone_info->nargs; ++i)
10842 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
10844 type = map[i];
10845 break;
10847 map.release ();
10850 /* c) If the characteristic data type determined by a) or b) above
10851 is struct, union, or class type which is pass-by-value (except
10852 for the type that maps to the built-in complex data type), the
10853 characteristic data type is int. */
10854 if (RECORD_OR_UNION_TYPE_P (type)
10855 && !aggregate_value_p (type, NULL)
10856 && TREE_CODE (type) != COMPLEX_TYPE)
10857 return integer_type_node;
10859 /* d) If none of the above three classes is applicable, the
10860 characteristic data type is int. */
10862 return type;
10864 /* e) For Intel Xeon Phi native and offload compilation, if the
10865 resulting characteristic data type is 8-bit or 16-bit integer
10866 data type, the characteristic data type is int. */
10867 /* Well, we don't handle Xeon Phi yet. */
10870 static tree
10871 simd_clone_mangle (struct cgraph_node *node,
10872 struct cgraph_simd_clone *clone_info)
10874 char vecsize_mangle = clone_info->vecsize_mangle;
10875 char mask = clone_info->inbranch ? 'M' : 'N';
10876 unsigned int simdlen = clone_info->simdlen;
10877 unsigned int n;
10878 pretty_printer pp;
10880 gcc_assert (vecsize_mangle && simdlen);
10882 pp_string (&pp, "_ZGV");
10883 pp_character (&pp, vecsize_mangle);
10884 pp_character (&pp, mask);
10885 pp_decimal_int (&pp, simdlen);
10887 for (n = 0; n < clone_info->nargs; ++n)
10889 struct cgraph_simd_clone_arg arg = clone_info->args[n];
10891 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
10892 pp_character (&pp, 'u');
10893 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
10895 gcc_assert (arg.linear_step != 0);
10896 pp_character (&pp, 'l');
10897 if (arg.linear_step > 1)
10898 pp_unsigned_wide_integer (&pp, arg.linear_step);
10899 else if (arg.linear_step < 0)
10901 pp_character (&pp, 'n');
10902 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
10903 arg.linear_step));
10906 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
10908 pp_character (&pp, 's');
10909 pp_unsigned_wide_integer (&pp, arg.linear_step);
10911 else
10912 pp_character (&pp, 'v');
10913 if (arg.alignment)
10915 pp_character (&pp, 'a');
10916 pp_decimal_int (&pp, arg.alignment);
10920 pp_underscore (&pp);
10921 pp_string (&pp,
10922 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
10923 const char *str = pp_formatted_text (&pp);
10925 /* If there already is a SIMD clone with the same mangled name, don't
10926 add another one. This can happen e.g. for
10927 #pragma omp declare simd
10928 #pragma omp declare simd simdlen(8)
10929 int foo (int, int);
10930 if the simdlen is assumed to be 8 for the first one, etc. */
10931 for (struct cgraph_node *clone = node->simd_clones; clone;
10932 clone = clone->simdclone->next_clone)
10933 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
10934 str) == 0)
10935 return NULL_TREE;
10937 return get_identifier (str);
10940 /* Create a simd clone of OLD_NODE and return it. */
10942 static struct cgraph_node *
10943 simd_clone_create (struct cgraph_node *old_node)
10945 struct cgraph_node *new_node;
10946 if (old_node->definition)
10948 if (!cgraph_function_with_gimple_body_p (old_node))
10949 return NULL;
10950 cgraph_get_body (old_node);
10951 new_node = cgraph_function_versioning (old_node, vNULL, NULL, NULL,
10952 false, NULL, NULL, "simdclone");
10954 else
10956 tree old_decl = old_node->decl;
10957 tree new_decl = copy_node (old_node->decl);
10958 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
10959 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
10960 SET_DECL_RTL (new_decl, NULL);
10961 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
10962 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
10963 new_node
10964 = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL);
10965 cgraph_call_function_insertion_hooks (new_node);
10967 if (new_node == NULL)
10968 return new_node;
10970 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
10972 /* The function cgraph_function_versioning () will force the new
10973 symbol local. Undo this, and inherit external visability from
10974 the old node. */
10975 new_node->local.local = old_node->local.local;
10976 new_node->externally_visible = old_node->externally_visible;
10978 return new_node;
10981 /* Adjust the return type of the given function to its appropriate
10982 vector counterpart. Returns a simd array to be used throughout the
10983 function as a return value. */
10985 static tree
10986 simd_clone_adjust_return_type (struct cgraph_node *node)
10988 tree fndecl = node->decl;
10989 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
10990 unsigned int veclen;
10991 tree t;
10993 /* Adjust the function return type. */
10994 if (orig_rettype == void_type_node)
10995 return NULL_TREE;
10996 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
10997 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
10998 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
10999 veclen = node->simdclone->vecsize_int;
11000 else
11001 veclen = node->simdclone->vecsize_float;
11002 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11003 if (veclen > node->simdclone->simdlen)
11004 veclen = node->simdclone->simdlen;
11005 if (veclen == node->simdclone->simdlen)
11006 TREE_TYPE (TREE_TYPE (fndecl))
11007 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11008 node->simdclone->simdlen);
11009 else
11011 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11012 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11013 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11015 if (!node->definition)
11016 return NULL_TREE;
11018 t = DECL_RESULT (fndecl);
11019 /* Adjust the DECL_RESULT. */
11020 gcc_assert (TREE_TYPE (t) != void_type_node);
11021 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11022 relayout_decl (t);
11024 tree atype = build_array_type_nelts (orig_rettype,
11025 node->simdclone->simdlen);
11026 if (veclen != node->simdclone->simdlen)
11027 return build1 (VIEW_CONVERT_EXPR, atype, t);
11029 /* Set up a SIMD array to use as the return value. */
11030 tree retval = create_tmp_var_raw (atype, "retval");
11031 gimple_add_tmp_var (retval);
11032 return retval;
11035 /* Each vector argument has a corresponding array to be used locally
11036 as part of the eventual loop. Create such temporary array and
11037 return it.
11039 PREFIX is the prefix to be used for the temporary.
11041 TYPE is the inner element type.
11043 SIMDLEN is the number of elements. */
11045 static tree
11046 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11048 tree atype = build_array_type_nelts (type, simdlen);
11049 tree avar = create_tmp_var_raw (atype, prefix);
11050 gimple_add_tmp_var (avar);
11051 return avar;
11054 /* Modify the function argument types to their corresponding vector
11055 counterparts if appropriate. Also, create one array for each simd
11056 argument to be used locally when using the function arguments as
11057 part of the loop.
11059 NODE is the function whose arguments are to be adjusted.
11061 Returns an adjustment vector that will be filled describing how the
11062 argument types will be adjusted. */
11064 static ipa_parm_adjustment_vec
11065 simd_clone_adjust_argument_types (struct cgraph_node *node)
11067 vec<tree> args;
11068 ipa_parm_adjustment_vec adjustments;
11070 if (node->definition)
11071 args = ipa_get_vector_of_formal_parms (node->decl);
11072 else
11073 args = simd_clone_vector_of_formal_parm_types (node->decl);
11074 adjustments.create (args.length ());
11075 unsigned i, j, veclen;
11076 struct ipa_parm_adjustment adj;
11077 for (i = 0; i < node->simdclone->nargs; ++i)
11079 memset (&adj, 0, sizeof (adj));
11080 tree parm = args[i];
11081 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11082 adj.base_index = i;
11083 adj.base = parm;
11085 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11086 node->simdclone->args[i].orig_type = parm_type;
11088 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11090 /* No adjustment necessary for scalar arguments. */
11091 adj.op = IPA_PARM_OP_COPY;
11093 else
11095 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11096 veclen = node->simdclone->vecsize_int;
11097 else
11098 veclen = node->simdclone->vecsize_float;
11099 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11100 if (veclen > node->simdclone->simdlen)
11101 veclen = node->simdclone->simdlen;
11102 adj.arg_prefix = "simd";
11103 adj.type = build_vector_type (parm_type, veclen);
11104 node->simdclone->args[i].vector_type = adj.type;
11105 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11107 adjustments.safe_push (adj);
11108 if (j == veclen)
11110 memset (&adj, 0, sizeof (adj));
11111 adj.op = IPA_PARM_OP_NEW;
11112 adj.arg_prefix = "simd";
11113 adj.base_index = i;
11114 adj.type = node->simdclone->args[i].vector_type;
11118 if (node->definition)
11119 node->simdclone->args[i].simd_array
11120 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11121 parm_type, node->simdclone->simdlen);
11123 adjustments.safe_push (adj);
11126 if (node->simdclone->inbranch)
11128 tree base_type
11129 = simd_clone_compute_base_data_type (node->simdclone->origin,
11130 node->simdclone);
11132 memset (&adj, 0, sizeof (adj));
11133 adj.op = IPA_PARM_OP_NEW;
11134 adj.arg_prefix = "mask";
11136 adj.base_index = i;
11137 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11138 veclen = node->simdclone->vecsize_int;
11139 else
11140 veclen = node->simdclone->vecsize_float;
11141 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11142 if (veclen > node->simdclone->simdlen)
11143 veclen = node->simdclone->simdlen;
11144 adj.type = build_vector_type (base_type, veclen);
11145 adjustments.safe_push (adj);
11147 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11148 adjustments.safe_push (adj);
11150 /* We have previously allocated one extra entry for the mask. Use
11151 it and fill it. */
11152 struct cgraph_simd_clone *sc = node->simdclone;
11153 sc->nargs++;
11154 if (node->definition)
11156 sc->args[i].orig_arg
11157 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11158 sc->args[i].simd_array
11159 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11161 sc->args[i].orig_type = base_type;
11162 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11165 if (node->definition)
11166 ipa_modify_formal_parameters (node->decl, adjustments);
11167 else
11169 tree new_arg_types = NULL_TREE, new_reversed;
11170 bool last_parm_void = false;
11171 if (args.length () > 0 && args.last () == void_type_node)
11172 last_parm_void = true;
11174 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11175 j = adjustments.length ();
11176 for (i = 0; i < j; i++)
11178 struct ipa_parm_adjustment *adj = &adjustments[i];
11179 tree ptype;
11180 if (adj->op == IPA_PARM_OP_COPY)
11181 ptype = args[adj->base_index];
11182 else
11183 ptype = adj->type;
11184 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11186 new_reversed = nreverse (new_arg_types);
11187 if (last_parm_void)
11189 if (new_reversed)
11190 TREE_CHAIN (new_arg_types) = void_list_node;
11191 else
11192 new_reversed = void_list_node;
11195 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11196 TYPE_ARG_TYPES (new_type) = new_reversed;
11197 TREE_TYPE (node->decl) = new_type;
11199 adjustments.release ();
11201 args.release ();
11202 return adjustments;
11205 /* Initialize and copy the function arguments in NODE to their
11206 corresponding local simd arrays. Returns a fresh gimple_seq with
11207 the instruction sequence generated. */
11209 static gimple_seq
11210 simd_clone_init_simd_arrays (struct cgraph_node *node,
11211 ipa_parm_adjustment_vec adjustments)
11213 gimple_seq seq = NULL;
11214 unsigned i = 0, j = 0, k;
11216 for (tree arg = DECL_ARGUMENTS (node->decl);
11217 arg;
11218 arg = DECL_CHAIN (arg), i++, j++)
11220 if (adjustments[j].op == IPA_PARM_OP_COPY)
11221 continue;
11223 node->simdclone->args[i].vector_arg = arg;
11225 tree array = node->simdclone->args[i].simd_array;
11226 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11228 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11229 tree ptr = build_fold_addr_expr (array);
11230 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11231 build_int_cst (ptype, 0));
11232 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11233 gimplify_and_add (t, &seq);
11235 else
11237 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11238 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11239 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11241 tree ptr = build_fold_addr_expr (array);
11242 int elemsize;
11243 if (k)
11245 arg = DECL_CHAIN (arg);
11246 j++;
11248 elemsize
11249 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11250 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11251 build_int_cst (ptype, k * elemsize));
11252 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11253 gimplify_and_add (t, &seq);
11257 return seq;
11260 /* Callback info for ipa_simd_modify_stmt_ops below. */
11262 struct modify_stmt_info {
11263 ipa_parm_adjustment_vec adjustments;
11264 gimple stmt;
11265 /* True if the parent statement was modified by
11266 ipa_simd_modify_stmt_ops. */
11267 bool modified;
11270 /* Callback for walk_gimple_op.
11272 Adjust operands from a given statement as specified in the
11273 adjustments vector in the callback data. */
11275 static tree
11276 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11278 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11279 if (!SSA_VAR_P (*tp))
11281 /* Make sure we treat subtrees as a RHS. This makes sure that
11282 when examining the `*foo' in *foo=x, the `foo' get treated as
11283 a use properly. */
11284 wi->is_lhs = false;
11285 wi->val_only = true;
11286 if (TYPE_P (*tp))
11287 *walk_subtrees = 0;
11288 return NULL_TREE;
11290 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11291 struct ipa_parm_adjustment *cand
11292 = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11293 if (!cand)
11294 return NULL_TREE;
11296 tree t = *tp;
11297 tree repl = make_ssa_name (TREE_TYPE (t), NULL);
11299 gimple stmt;
11300 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11301 if (wi->is_lhs)
11303 stmt = gimple_build_assign (unshare_expr (cand->new_decl), repl);
11304 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
11305 SSA_NAME_DEF_STMT (repl) = info->stmt;
11307 else
11309 /* You'd think we could skip the extra SSA variable when
11310 wi->val_only=true, but we may have `*var' which will get
11311 replaced into `*var_array[iter]' and will likely be something
11312 not gimple. */
11313 stmt = gimple_build_assign (repl, unshare_expr (cand->new_decl));
11314 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11317 if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11319 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11320 *tp = vce;
11322 else
11323 *tp = repl;
11325 info->modified = true;
11326 wi->is_lhs = false;
11327 wi->val_only = true;
11328 return NULL_TREE;
11331 /* Traverse the function body and perform all modifications as
11332 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11333 modified such that the replacement/reduction value will now be an
11334 offset into the corresponding simd_array.
11336 This function will replace all function argument uses with their
11337 corresponding simd array elements, and ajust the return values
11338 accordingly. */
11340 static void
11341 ipa_simd_modify_function_body (struct cgraph_node *node,
11342 ipa_parm_adjustment_vec adjustments,
11343 tree retval_array, tree iter)
11345 basic_block bb;
11346 unsigned int i, j;
11348 /* Re-use the adjustments array, but this time use it to replace
11349 every function argument use to an offset into the corresponding
11350 simd_array. */
11351 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11353 if (!node->simdclone->args[i].vector_arg)
11354 continue;
11356 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11357 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11358 adjustments[j].new_decl
11359 = build4 (ARRAY_REF,
11360 basetype,
11361 node->simdclone->args[i].simd_array,
11362 iter,
11363 NULL_TREE, NULL_TREE);
11364 if (adjustments[j].op == IPA_PARM_OP_NONE
11365 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11366 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11369 struct modify_stmt_info info;
11370 info.adjustments = adjustments;
11372 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
11374 gimple_stmt_iterator gsi;
11376 gsi = gsi_start_bb (bb);
11377 while (!gsi_end_p (gsi))
11379 gimple stmt = gsi_stmt (gsi);
11380 info.stmt = stmt;
11381 struct walk_stmt_info wi;
11383 memset (&wi, 0, sizeof (wi));
11384 info.modified = false;
11385 wi.info = &info;
11386 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
11388 if (gimple_code (stmt) == GIMPLE_RETURN)
11390 tree retval = gimple_return_retval (stmt);
11391 if (!retval)
11393 gsi_remove (&gsi, true);
11394 continue;
11397 /* Replace `return foo' with `retval_array[iter] = foo'. */
11398 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
11399 retval_array, iter, NULL, NULL);
11400 stmt = gimple_build_assign (ref, retval);
11401 gsi_replace (&gsi, stmt, true);
11402 info.modified = true;
11405 if (info.modified)
11407 update_stmt (stmt);
11408 if (maybe_clean_eh_stmt (stmt))
11409 gimple_purge_dead_eh_edges (gimple_bb (stmt));
11411 gsi_next (&gsi);
11416 /* Adjust the argument types in NODE to their appropriate vector
11417 counterparts. */
11419 static void
11420 simd_clone_adjust (struct cgraph_node *node)
11422 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
11424 targetm.simd_clone.adjust (node);
11426 tree retval = simd_clone_adjust_return_type (node);
11427 ipa_parm_adjustment_vec adjustments
11428 = simd_clone_adjust_argument_types (node);
11430 push_gimplify_context ();
11432 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
11434 /* Adjust all uses of vector arguments accordingly. Adjust all
11435 return values accordingly. */
11436 tree iter = create_tmp_var (unsigned_type_node, "iter");
11437 tree iter1 = make_ssa_name (iter, NULL);
11438 tree iter2 = make_ssa_name (iter, NULL);
11439 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
11441 /* Initialize the iteration variable. */
11442 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11443 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
11444 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
11445 /* Insert the SIMD array and iv initialization at function
11446 entry. */
11447 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
11449 pop_gimplify_context (NULL);
11451 /* Create a new BB right before the original exit BB, to hold the
11452 iteration increment and the condition/branch. */
11453 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
11454 basic_block incr_bb = create_empty_bb (orig_exit);
11455 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11456 flag. Set it now to be a FALLTHRU_EDGE. */
11457 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
11458 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
11459 for (unsigned i = 0;
11460 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
11462 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
11463 redirect_edge_succ (e, incr_bb);
11465 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
11466 e->probability = REG_BR_PROB_BASE;
11467 gsi = gsi_last_bb (incr_bb);
11468 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
11469 build_int_cst (unsigned_type_node,
11470 1));
11471 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11473 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
11474 struct loop *loop = alloc_loop ();
11475 cfun->has_force_vect_loops = true;
11476 loop->safelen = node->simdclone->simdlen;
11477 loop->force_vect = true;
11478 loop->header = body_bb;
11479 add_bb_to_loop (incr_bb, loop);
11481 /* Branch around the body if the mask applies. */
11482 if (node->simdclone->inbranch)
11484 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
11485 tree mask_array
11486 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
11487 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
11488 tree aref = build4 (ARRAY_REF,
11489 TREE_TYPE (TREE_TYPE (mask_array)),
11490 mask_array, iter1,
11491 NULL, NULL);
11492 g = gimple_build_assign (mask, aref);
11493 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11494 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
11495 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
11497 aref = build1 (VIEW_CONVERT_EXPR,
11498 build_nonstandard_integer_type (bitsize, 0), mask);
11499 mask = make_ssa_name (TREE_TYPE (aref), NULL);
11500 g = gimple_build_assign (mask, aref);
11501 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11504 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
11505 NULL, NULL);
11506 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11507 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
11508 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
11511 /* Generate the condition. */
11512 g = gimple_build_cond (LT_EXPR,
11513 iter2,
11514 build_int_cst (unsigned_type_node,
11515 node->simdclone->simdlen),
11516 NULL, NULL);
11517 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11518 e = split_block (incr_bb, gsi_stmt (gsi));
11519 basic_block latch_bb = e->dest;
11520 basic_block new_exit_bb = e->dest;
11521 new_exit_bb = split_block (latch_bb, NULL)->dest;
11522 loop->latch = latch_bb;
11524 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
11526 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
11527 /* The successor of incr_bb is already pointing to latch_bb; just
11528 change the flags.
11529 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
11530 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
11532 gimple phi = create_phi_node (iter1, body_bb);
11533 edge preheader_edge = find_edge (entry_bb, body_bb);
11534 edge latch_edge = single_succ_edge (latch_bb);
11535 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
11536 UNKNOWN_LOCATION);
11537 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11539 /* Generate the new return. */
11540 gsi = gsi_last_bb (new_exit_bb);
11541 if (retval
11542 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
11543 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
11544 retval = TREE_OPERAND (retval, 0);
11545 else if (retval)
11547 retval = build1 (VIEW_CONVERT_EXPR,
11548 TREE_TYPE (TREE_TYPE (node->decl)),
11549 retval);
11550 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
11551 false, GSI_CONTINUE_LINKING);
11553 g = gimple_build_return (retval);
11554 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11556 /* Handle aligned clauses by replacing default defs of the aligned
11557 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
11558 lhs. Handle linear by adding PHIs. */
11559 for (unsigned i = 0; i < node->simdclone->nargs; i++)
11560 if (node->simdclone->args[i].alignment
11561 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
11562 && (node->simdclone->args[i].alignment
11563 & (node->simdclone->args[i].alignment - 1)) == 0
11564 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
11565 == POINTER_TYPE)
11567 unsigned int alignment = node->simdclone->args[i].alignment;
11568 tree orig_arg = node->simdclone->args[i].orig_arg;
11569 tree def = ssa_default_def (cfun, orig_arg);
11570 if (def && !has_zero_uses (def))
11572 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
11573 gimple_seq seq = NULL;
11574 bool need_cvt = false;
11575 gimple call
11576 = gimple_build_call (fn, 2, def, size_int (alignment));
11577 g = call;
11578 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
11579 ptr_type_node))
11580 need_cvt = true;
11581 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
11582 gimple_call_set_lhs (g, t);
11583 gimple_seq_add_stmt_without_update (&seq, g);
11584 if (need_cvt)
11586 t = make_ssa_name (orig_arg, NULL);
11587 g = gimple_build_assign_with_ops (NOP_EXPR, t,
11588 gimple_call_lhs (g),
11589 NULL_TREE);
11590 gimple_seq_add_stmt_without_update (&seq, g);
11592 gsi_insert_seq_on_edge_immediate
11593 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
11595 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11596 int freq = compute_call_stmt_bb_frequency (current_function_decl,
11597 entry_bb);
11598 cgraph_create_edge (node, cgraph_get_create_node (fn),
11599 call, entry_bb->count, freq);
11601 imm_use_iterator iter;
11602 use_operand_p use_p;
11603 gimple use_stmt;
11604 tree repl = gimple_get_lhs (g);
11605 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11606 if (is_gimple_debug (use_stmt) || use_stmt == call)
11607 continue;
11608 else
11609 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11610 SET_USE (use_p, repl);
11613 else if (node->simdclone->args[i].arg_type
11614 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11616 tree orig_arg = node->simdclone->args[i].orig_arg;
11617 tree def = ssa_default_def (cfun, orig_arg);
11618 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11619 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
11620 if (def && !has_zero_uses (def))
11622 iter1 = make_ssa_name (orig_arg, NULL);
11623 iter2 = make_ssa_name (orig_arg, NULL);
11624 phi = create_phi_node (iter1, body_bb);
11625 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
11626 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11627 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11628 ? PLUS_EXPR : POINTER_PLUS_EXPR;
11629 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11630 ? TREE_TYPE (orig_arg) : sizetype;
11631 tree addcst
11632 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
11633 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
11634 gsi = gsi_last_bb (incr_bb);
11635 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
11637 imm_use_iterator iter;
11638 use_operand_p use_p;
11639 gimple use_stmt;
11640 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11641 if (use_stmt == phi)
11642 continue;
11643 else
11644 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11645 SET_USE (use_p, iter1);
11649 calculate_dominance_info (CDI_DOMINATORS);
11650 add_loop (loop, loop->header->loop_father);
11651 update_ssa (TODO_update_ssa);
11653 pop_cfun ();
11656 /* If the function in NODE is tagged as an elemental SIMD function,
11657 create the appropriate SIMD clones. */
11659 static void
11660 expand_simd_clones (struct cgraph_node *node)
11662 tree attr = lookup_attribute ("omp declare simd",
11663 DECL_ATTRIBUTES (node->decl));
11664 if (attr == NULL_TREE
11665 || node->global.inlined_to
11666 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
11667 return;
11669 /* Ignore
11670 #pragma omp declare simd
11671 extern int foo ();
11672 in C, there we don't know the argument types at all. */
11673 if (!node->definition
11674 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
11675 return;
11679 /* Start with parsing the "omp declare simd" attribute(s). */
11680 bool inbranch_clause_specified;
11681 struct cgraph_simd_clone *clone_info
11682 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
11683 &inbranch_clause_specified);
11684 if (clone_info == NULL)
11685 continue;
11687 int orig_simdlen = clone_info->simdlen;
11688 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
11689 /* The target can return 0 (no simd clones should be created),
11690 1 (just one ISA of simd clones should be created) or higher
11691 count of ISA variants. In that case, clone_info is initialized
11692 for the first ISA variant. */
11693 int count
11694 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
11695 base_type, 0);
11696 if (count == 0)
11697 continue;
11699 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
11700 also create one inbranch and one !inbranch clone of it. */
11701 for (int i = 0; i < count * 2; i++)
11703 struct cgraph_simd_clone *clone = clone_info;
11704 if (inbranch_clause_specified && (i & 1) != 0)
11705 continue;
11707 if (i != 0)
11709 clone = simd_clone_struct_alloc (clone_info->nargs
11710 + ((i & 1) != 0));
11711 simd_clone_struct_copy (clone, clone_info);
11712 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
11713 and simd_clone_adjust_argument_types did to the first
11714 clone's info. */
11715 clone->nargs -= clone_info->inbranch;
11716 clone->simdlen = orig_simdlen;
11717 /* And call the target hook again to get the right ISA. */
11718 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
11719 base_type,
11720 i / 2);
11721 if ((i & 1) != 0)
11722 clone->inbranch = 1;
11725 /* simd_clone_mangle might fail if such a clone has been created
11726 already. */
11727 tree id = simd_clone_mangle (node, clone);
11728 if (id == NULL_TREE)
11729 continue;
11731 /* Only when we are sure we want to create the clone actually
11732 clone the function (or definitions) or create another
11733 extern FUNCTION_DECL (for prototypes without definitions). */
11734 struct cgraph_node *n = simd_clone_create (node);
11735 if (n == NULL)
11736 continue;
11738 n->simdclone = clone;
11739 clone->origin = node;
11740 clone->next_clone = NULL;
11741 if (node->simd_clones == NULL)
11743 clone->prev_clone = n;
11744 node->simd_clones = n;
11746 else
11748 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
11749 clone->prev_clone->simdclone->next_clone = n;
11750 node->simd_clones->simdclone->prev_clone = n;
11752 change_decl_assembler_name (n->decl, id);
11753 /* And finally adjust the return type, parameters and for
11754 definitions also function body. */
11755 if (node->definition)
11756 simd_clone_adjust (n);
11757 else
11759 simd_clone_adjust_return_type (n);
11760 simd_clone_adjust_argument_types (n);
11764 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
11767 /* Entry point for IPA simd clone creation pass. */
11769 static unsigned int
11770 ipa_omp_simd_clone (void)
11772 struct cgraph_node *node;
11773 FOR_EACH_FUNCTION (node)
11774 expand_simd_clones (node);
11775 return 0;
11778 namespace {
11780 const pass_data pass_data_omp_simd_clone =
11782 SIMPLE_IPA_PASS, /* type */
11783 "simdclone", /* name */
11784 OPTGROUP_NONE, /* optinfo_flags */
11785 true, /* has_gate */
11786 true, /* has_execute */
11787 TV_NONE, /* tv_id */
11788 ( PROP_ssa | PROP_cfg ), /* properties_required */
11789 0, /* properties_provided */
11790 0, /* properties_destroyed */
11791 0, /* todo_flags_start */
11792 0, /* todo_flags_finish */
11795 class pass_omp_simd_clone : public simple_ipa_opt_pass
11797 public:
11798 pass_omp_simd_clone(gcc::context *ctxt)
11799 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
11802 /* opt_pass methods: */
11803 bool gate () { return ((flag_openmp || flag_openmp_simd
11804 || flag_cilkplus || (in_lto_p && !flag_wpa))
11805 && (targetm.simd_clone.compute_vecsize_and_simdlen
11806 != NULL)); }
11807 unsigned int execute () { return ipa_omp_simd_clone (); }
11810 } // anon namespace
11812 simple_ipa_opt_pass *
11813 make_pass_omp_simd_clone (gcc::context *ctxt)
11815 return new pass_omp_simd_clone (ctxt);
11818 #include "gt-omp-low.h"