* builtins.c (expand_builtin_memcpy_with_bounds): Use target hook
[official-gcc.git] / gcc / omp-low.c
blob915d55f7f93843f57cc95bbe2a2404e925e76666
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005-2014 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "stringpool.h"
30 #include "stor-layout.h"
31 #include "rtl.h"
32 #include "predict.h"
33 #include "vec.h"
34 #include "hashtab.h"
35 #include "hash-set.h"
36 #include "machmode.h"
37 #include "hard-reg-set.h"
38 #include "input.h"
39 #include "function.h"
40 #include "dominance.h"
41 #include "cfg.h"
42 #include "cfganal.h"
43 #include "basic-block.h"
44 #include "tree-ssa-alias.h"
45 #include "internal-fn.h"
46 #include "gimple-fold.h"
47 #include "gimple-expr.h"
48 #include "is-a.h"
49 #include "gimple.h"
50 #include "gimplify.h"
51 #include "gimple-iterator.h"
52 #include "gimplify-me.h"
53 #include "gimple-walk.h"
54 #include "tree-iterator.h"
55 #include "tree-inline.h"
56 #include "langhooks.h"
57 #include "diagnostic-core.h"
58 #include "gimple-ssa.h"
59 #include "hash-map.h"
60 #include "plugin-api.h"
61 #include "ipa-ref.h"
62 #include "cgraph.h"
63 #include "tree-cfg.h"
64 #include "tree-phinodes.h"
65 #include "ssa-iterators.h"
66 #include "tree-ssanames.h"
67 #include "tree-into-ssa.h"
68 #include "expr.h"
69 #include "tree-dfa.h"
70 #include "tree-ssa.h"
71 #include "flags.h"
72 #include "expr.h"
73 #include "tree-pass.h"
74 #include "except.h"
75 #include "splay-tree.h"
76 #include "insn-codes.h"
77 #include "optabs.h"
78 #include "cfgloop.h"
79 #include "target.h"
80 #include "common/common-target.h"
81 #include "omp-low.h"
82 #include "gimple-low.h"
83 #include "tree-cfgcleanup.h"
84 #include "pretty-print.h"
85 #include "alloc-pool.h"
86 #include "ipa-prop.h"
87 #include "tree-nested.h"
88 #include "tree-eh.h"
89 #include "cilk.h"
90 #include "context.h"
91 #include "lto-section-names.h"
94 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
95 phases. The first phase scans the function looking for OMP statements
96 and then for variables that must be replaced to satisfy data sharing
97 clauses. The second phase expands code for the constructs, as well as
98 re-gimplifying things when variables have been replaced with complex
99 expressions.
101 Final code generation is done by pass_expand_omp. The flowgraph is
102 scanned for parallel regions which are then moved to a new
103 function, to be invoked by the thread library. */
105 /* Parallel region information. Every parallel and workshare
106 directive is enclosed between two markers, the OMP_* directive
107 and a corresponding OMP_RETURN statement. */
109 struct omp_region
111 /* The enclosing region. */
112 struct omp_region *outer;
114 /* First child region. */
115 struct omp_region *inner;
117 /* Next peer region. */
118 struct omp_region *next;
120 /* Block containing the omp directive as its last stmt. */
121 basic_block entry;
123 /* Block containing the OMP_RETURN as its last stmt. */
124 basic_block exit;
126 /* Block containing the OMP_CONTINUE as its last stmt. */
127 basic_block cont;
129 /* If this is a combined parallel+workshare region, this is a list
130 of additional arguments needed by the combined parallel+workshare
131 library call. */
132 vec<tree, va_gc> *ws_args;
134 /* The code for the omp directive of this region. */
135 enum gimple_code type;
137 /* Schedule kind, only used for OMP_FOR type regions. */
138 enum omp_clause_schedule_kind sched_kind;
140 /* True if this is a combined parallel+workshare region. */
141 bool is_combined_parallel;
144 /* Context structure. Used to store information about each parallel
145 directive in the code. */
147 typedef struct omp_context
149 /* This field must be at the beginning, as we do "inheritance": Some
150 callback functions for tree-inline.c (e.g., omp_copy_decl)
151 receive a copy_body_data pointer that is up-casted to an
152 omp_context pointer. */
153 copy_body_data cb;
155 /* The tree of contexts corresponding to the encountered constructs. */
156 struct omp_context *outer;
157 gimple stmt;
159 /* Map variables to fields in a structure that allows communication
160 between sending and receiving threads. */
161 splay_tree field_map;
162 tree record_type;
163 tree sender_decl;
164 tree receiver_decl;
166 /* These are used just by task contexts, if task firstprivate fn is
167 needed. srecord_type is used to communicate from the thread
168 that encountered the task construct to task firstprivate fn,
169 record_type is allocated by GOMP_task, initialized by task firstprivate
170 fn and passed to the task body fn. */
171 splay_tree sfield_map;
172 tree srecord_type;
174 /* A chain of variables to add to the top-level block surrounding the
175 construct. In the case of a parallel, this is in the child function. */
176 tree block_vars;
178 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
179 barriers should jump to during omplower pass. */
180 tree cancel_label;
182 /* What to do with variables with implicitly determined sharing
183 attributes. */
184 enum omp_clause_default_kind default_kind;
186 /* Nesting depth of this context. Used to beautify error messages re
187 invalid gotos. The outermost ctx is depth 1, with depth 0 being
188 reserved for the main body of the function. */
189 int depth;
191 /* True if this parallel directive is nested within another. */
192 bool is_nested;
194 /* True if this construct can be cancelled. */
195 bool cancellable;
196 } omp_context;
199 struct omp_for_data_loop
201 tree v, n1, n2, step;
202 enum tree_code cond_code;
205 /* A structure describing the main elements of a parallel loop. */
207 struct omp_for_data
209 struct omp_for_data_loop loop;
210 tree chunk_size;
211 gimple for_stmt;
212 tree pre, iter_type;
213 int collapse;
214 bool have_nowait, have_ordered;
215 enum omp_clause_schedule_kind sched_kind;
216 struct omp_for_data_loop *loops;
220 static splay_tree all_contexts;
221 static int taskreg_nesting_level;
222 static int target_nesting_level;
223 static struct omp_region *root_omp_region;
224 static bitmap task_shared_vars;
225 static vec<omp_context *> taskreg_contexts;
227 static void scan_omp (gimple_seq *, omp_context *);
228 static tree scan_omp_1_op (tree *, int *, void *);
230 #define WALK_SUBSTMTS \
231 case GIMPLE_BIND: \
232 case GIMPLE_TRY: \
233 case GIMPLE_CATCH: \
234 case GIMPLE_EH_FILTER: \
235 case GIMPLE_TRANSACTION: \
236 /* The sub-statements for these should be walked. */ \
237 *handled_ops_p = false; \
238 break;
240 /* Holds offload tables with decls. */
241 vec<tree, va_gc> *offload_funcs, *offload_vars;
243 /* Convenience function for calling scan_omp_1_op on tree operands. */
245 static inline tree
246 scan_omp_op (tree *tp, omp_context *ctx)
248 struct walk_stmt_info wi;
250 memset (&wi, 0, sizeof (wi));
251 wi.info = ctx;
252 wi.want_locations = true;
254 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
257 static void lower_omp (gimple_seq *, omp_context *);
258 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
259 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
261 /* Find an OpenMP clause of type KIND within CLAUSES. */
263 tree
264 find_omp_clause (tree clauses, enum omp_clause_code kind)
266 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
267 if (OMP_CLAUSE_CODE (clauses) == kind)
268 return clauses;
270 return NULL_TREE;
273 /* Return true if CTX is for an omp parallel. */
275 static inline bool
276 is_parallel_ctx (omp_context *ctx)
278 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
282 /* Return true if CTX is for an omp target region. */
284 static inline bool
285 is_targetreg_ctx (omp_context *ctx)
287 return gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
288 && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION;
292 /* Return true if CTX is for an omp task. */
294 static inline bool
295 is_task_ctx (omp_context *ctx)
297 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
301 /* Return true if CTX is for an omp parallel or omp task. */
303 static inline bool
304 is_taskreg_ctx (omp_context *ctx)
306 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
307 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
311 /* Return true if REGION is a combined parallel+workshare region. */
313 static inline bool
314 is_combined_parallel (struct omp_region *region)
316 return region->is_combined_parallel;
320 /* Extract the header elements of parallel loop FOR_STMT and store
321 them into *FD. */
323 static void
324 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
325 struct omp_for_data_loop *loops)
327 tree t, var, *collapse_iter, *collapse_count;
328 tree count = NULL_TREE, iter_type = long_integer_type_node;
329 struct omp_for_data_loop *loop;
330 int i;
331 struct omp_for_data_loop dummy_loop;
332 location_t loc = gimple_location (for_stmt);
333 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
334 bool distribute = gimple_omp_for_kind (for_stmt)
335 == GF_OMP_FOR_KIND_DISTRIBUTE;
337 fd->for_stmt = for_stmt;
338 fd->pre = NULL;
339 fd->collapse = gimple_omp_for_collapse (for_stmt);
340 if (fd->collapse > 1)
341 fd->loops = loops;
342 else
343 fd->loops = &fd->loop;
345 fd->have_nowait = distribute || simd;
346 fd->have_ordered = false;
347 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
348 fd->chunk_size = NULL_TREE;
349 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
350 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
351 collapse_iter = NULL;
352 collapse_count = NULL;
354 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
355 switch (OMP_CLAUSE_CODE (t))
357 case OMP_CLAUSE_NOWAIT:
358 fd->have_nowait = true;
359 break;
360 case OMP_CLAUSE_ORDERED:
361 fd->have_ordered = true;
362 break;
363 case OMP_CLAUSE_SCHEDULE:
364 gcc_assert (!distribute);
365 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
366 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
367 break;
368 case OMP_CLAUSE_DIST_SCHEDULE:
369 gcc_assert (distribute);
370 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
371 break;
372 case OMP_CLAUSE_COLLAPSE:
373 if (fd->collapse > 1)
375 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
376 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
378 break;
379 default:
380 break;
383 /* FIXME: for now map schedule(auto) to schedule(static).
384 There should be analysis to determine whether all iterations
385 are approximately the same amount of work (then schedule(static)
386 is best) or if it varies (then schedule(dynamic,N) is better). */
387 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
389 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
390 gcc_assert (fd->chunk_size == NULL);
392 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
393 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
394 gcc_assert (fd->chunk_size == NULL);
395 else if (fd->chunk_size == NULL)
397 /* We only need to compute a default chunk size for ordered
398 static loops and dynamic loops. */
399 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
400 || fd->have_ordered)
401 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
402 ? integer_zero_node : integer_one_node;
405 for (i = 0; i < fd->collapse; i++)
407 if (fd->collapse == 1)
408 loop = &fd->loop;
409 else if (loops != NULL)
410 loop = loops + i;
411 else
412 loop = &dummy_loop;
414 loop->v = gimple_omp_for_index (for_stmt, i);
415 gcc_assert (SSA_VAR_P (loop->v));
416 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
417 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
418 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
419 loop->n1 = gimple_omp_for_initial (for_stmt, i);
421 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
422 loop->n2 = gimple_omp_for_final (for_stmt, i);
423 switch (loop->cond_code)
425 case LT_EXPR:
426 case GT_EXPR:
427 break;
428 case NE_EXPR:
429 gcc_assert (gimple_omp_for_kind (for_stmt)
430 == GF_OMP_FOR_KIND_CILKSIMD
431 || (gimple_omp_for_kind (for_stmt)
432 == GF_OMP_FOR_KIND_CILKFOR));
433 break;
434 case LE_EXPR:
435 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
436 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
437 else
438 loop->n2 = fold_build2_loc (loc,
439 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
440 build_int_cst (TREE_TYPE (loop->n2), 1));
441 loop->cond_code = LT_EXPR;
442 break;
443 case GE_EXPR:
444 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
445 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
446 else
447 loop->n2 = fold_build2_loc (loc,
448 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
449 build_int_cst (TREE_TYPE (loop->n2), 1));
450 loop->cond_code = GT_EXPR;
451 break;
452 default:
453 gcc_unreachable ();
456 t = gimple_omp_for_incr (for_stmt, i);
457 gcc_assert (TREE_OPERAND (t, 0) == var);
458 switch (TREE_CODE (t))
460 case PLUS_EXPR:
461 loop->step = TREE_OPERAND (t, 1);
462 break;
463 case POINTER_PLUS_EXPR:
464 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
465 break;
466 case MINUS_EXPR:
467 loop->step = TREE_OPERAND (t, 1);
468 loop->step = fold_build1_loc (loc,
469 NEGATE_EXPR, TREE_TYPE (loop->step),
470 loop->step);
471 break;
472 default:
473 gcc_unreachable ();
476 if (simd
477 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
478 && !fd->have_ordered))
480 if (fd->collapse == 1)
481 iter_type = TREE_TYPE (loop->v);
482 else if (i == 0
483 || TYPE_PRECISION (iter_type)
484 < TYPE_PRECISION (TREE_TYPE (loop->v)))
485 iter_type
486 = build_nonstandard_integer_type
487 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
489 else if (iter_type != long_long_unsigned_type_node)
491 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
492 iter_type = long_long_unsigned_type_node;
493 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
494 && TYPE_PRECISION (TREE_TYPE (loop->v))
495 >= TYPE_PRECISION (iter_type))
497 tree n;
499 if (loop->cond_code == LT_EXPR)
500 n = fold_build2_loc (loc,
501 PLUS_EXPR, TREE_TYPE (loop->v),
502 loop->n2, loop->step);
503 else
504 n = loop->n1;
505 if (TREE_CODE (n) != INTEGER_CST
506 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
507 iter_type = long_long_unsigned_type_node;
509 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
510 > TYPE_PRECISION (iter_type))
512 tree n1, n2;
514 if (loop->cond_code == LT_EXPR)
516 n1 = loop->n1;
517 n2 = fold_build2_loc (loc,
518 PLUS_EXPR, TREE_TYPE (loop->v),
519 loop->n2, loop->step);
521 else
523 n1 = fold_build2_loc (loc,
524 MINUS_EXPR, TREE_TYPE (loop->v),
525 loop->n2, loop->step);
526 n2 = loop->n1;
528 if (TREE_CODE (n1) != INTEGER_CST
529 || TREE_CODE (n2) != INTEGER_CST
530 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
531 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
532 iter_type = long_long_unsigned_type_node;
536 if (collapse_count && *collapse_count == NULL)
538 t = fold_binary (loop->cond_code, boolean_type_node,
539 fold_convert (TREE_TYPE (loop->v), loop->n1),
540 fold_convert (TREE_TYPE (loop->v), loop->n2));
541 if (t && integer_zerop (t))
542 count = build_zero_cst (long_long_unsigned_type_node);
543 else if ((i == 0 || count != NULL_TREE)
544 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
545 && TREE_CONSTANT (loop->n1)
546 && TREE_CONSTANT (loop->n2)
547 && TREE_CODE (loop->step) == INTEGER_CST)
549 tree itype = TREE_TYPE (loop->v);
551 if (POINTER_TYPE_P (itype))
552 itype = signed_type_for (itype);
553 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
554 t = fold_build2_loc (loc,
555 PLUS_EXPR, itype,
556 fold_convert_loc (loc, itype, loop->step), t);
557 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
558 fold_convert_loc (loc, itype, loop->n2));
559 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
560 fold_convert_loc (loc, itype, loop->n1));
561 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
562 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
563 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
564 fold_build1_loc (loc, NEGATE_EXPR, itype,
565 fold_convert_loc (loc, itype,
566 loop->step)));
567 else
568 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
569 fold_convert_loc (loc, itype, loop->step));
570 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
571 if (count != NULL_TREE)
572 count = fold_build2_loc (loc,
573 MULT_EXPR, long_long_unsigned_type_node,
574 count, t);
575 else
576 count = t;
577 if (TREE_CODE (count) != INTEGER_CST)
578 count = NULL_TREE;
580 else if (count && !integer_zerop (count))
581 count = NULL_TREE;
585 if (count
586 && !simd
587 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
588 || fd->have_ordered))
590 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
591 iter_type = long_long_unsigned_type_node;
592 else
593 iter_type = long_integer_type_node;
595 else if (collapse_iter && *collapse_iter != NULL)
596 iter_type = TREE_TYPE (*collapse_iter);
597 fd->iter_type = iter_type;
598 if (collapse_iter && *collapse_iter == NULL)
599 *collapse_iter = create_tmp_var (iter_type, ".iter");
600 if (collapse_count && *collapse_count == NULL)
602 if (count)
603 *collapse_count = fold_convert_loc (loc, iter_type, count);
604 else
605 *collapse_count = create_tmp_var (iter_type, ".count");
608 if (fd->collapse > 1)
610 fd->loop.v = *collapse_iter;
611 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
612 fd->loop.n2 = *collapse_count;
613 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
614 fd->loop.cond_code = LT_EXPR;
619 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
620 is the immediate dominator of PAR_ENTRY_BB, return true if there
621 are no data dependencies that would prevent expanding the parallel
622 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
624 When expanding a combined parallel+workshare region, the call to
625 the child function may need additional arguments in the case of
626 GIMPLE_OMP_FOR regions. In some cases, these arguments are
627 computed out of variables passed in from the parent to the child
628 via 'struct .omp_data_s'. For instance:
630 #pragma omp parallel for schedule (guided, i * 4)
631 for (j ...)
633 Is lowered into:
635 # BLOCK 2 (PAR_ENTRY_BB)
636 .omp_data_o.i = i;
637 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
639 # BLOCK 3 (WS_ENTRY_BB)
640 .omp_data_i = &.omp_data_o;
641 D.1667 = .omp_data_i->i;
642 D.1598 = D.1667 * 4;
643 #pragma omp for schedule (guided, D.1598)
645 When we outline the parallel region, the call to the child function
646 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
647 that value is computed *after* the call site. So, in principle we
648 cannot do the transformation.
650 To see whether the code in WS_ENTRY_BB blocks the combined
651 parallel+workshare call, we collect all the variables used in the
652 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
653 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
654 call.
656 FIXME. If we had the SSA form built at this point, we could merely
657 hoist the code in block 3 into block 2 and be done with it. But at
658 this point we don't have dataflow information and though we could
659 hack something up here, it is really not worth the aggravation. */
661 static bool
662 workshare_safe_to_combine_p (basic_block ws_entry_bb)
664 struct omp_for_data fd;
665 gimple ws_stmt = last_stmt (ws_entry_bb);
667 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
668 return true;
670 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
672 extract_omp_for_data (ws_stmt, &fd, NULL);
674 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
675 return false;
676 if (fd.iter_type != long_integer_type_node)
677 return false;
679 /* FIXME. We give up too easily here. If any of these arguments
680 are not constants, they will likely involve variables that have
681 been mapped into fields of .omp_data_s for sharing with the child
682 function. With appropriate data flow, it would be possible to
683 see through this. */
684 if (!is_gimple_min_invariant (fd.loop.n1)
685 || !is_gimple_min_invariant (fd.loop.n2)
686 || !is_gimple_min_invariant (fd.loop.step)
687 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
688 return false;
690 return true;
694 /* Collect additional arguments needed to emit a combined
695 parallel+workshare call. WS_STMT is the workshare directive being
696 expanded. */
698 static vec<tree, va_gc> *
699 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
701 tree t;
702 location_t loc = gimple_location (ws_stmt);
703 vec<tree, va_gc> *ws_args;
705 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
707 struct omp_for_data fd;
708 tree n1, n2;
710 extract_omp_for_data (ws_stmt, &fd, NULL);
711 n1 = fd.loop.n1;
712 n2 = fd.loop.n2;
714 if (gimple_omp_for_combined_into_p (ws_stmt))
716 tree innerc
717 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
718 OMP_CLAUSE__LOOPTEMP_);
719 gcc_assert (innerc);
720 n1 = OMP_CLAUSE_DECL (innerc);
721 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
722 OMP_CLAUSE__LOOPTEMP_);
723 gcc_assert (innerc);
724 n2 = OMP_CLAUSE_DECL (innerc);
727 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
729 t = fold_convert_loc (loc, long_integer_type_node, n1);
730 ws_args->quick_push (t);
732 t = fold_convert_loc (loc, long_integer_type_node, n2);
733 ws_args->quick_push (t);
735 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
736 ws_args->quick_push (t);
738 if (fd.chunk_size)
740 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
741 ws_args->quick_push (t);
744 return ws_args;
746 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
748 /* Number of sections is equal to the number of edges from the
749 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
750 the exit of the sections region. */
751 basic_block bb = single_succ (gimple_bb (ws_stmt));
752 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
753 vec_alloc (ws_args, 1);
754 ws_args->quick_push (t);
755 return ws_args;
758 gcc_unreachable ();
762 /* Discover whether REGION is a combined parallel+workshare region. */
764 static void
765 determine_parallel_type (struct omp_region *region)
767 basic_block par_entry_bb, par_exit_bb;
768 basic_block ws_entry_bb, ws_exit_bb;
770 if (region == NULL || region->inner == NULL
771 || region->exit == NULL || region->inner->exit == NULL
772 || region->inner->cont == NULL)
773 return;
775 /* We only support parallel+for and parallel+sections. */
776 if (region->type != GIMPLE_OMP_PARALLEL
777 || (region->inner->type != GIMPLE_OMP_FOR
778 && region->inner->type != GIMPLE_OMP_SECTIONS))
779 return;
781 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
782 WS_EXIT_BB -> PAR_EXIT_BB. */
783 par_entry_bb = region->entry;
784 par_exit_bb = region->exit;
785 ws_entry_bb = region->inner->entry;
786 ws_exit_bb = region->inner->exit;
788 if (single_succ (par_entry_bb) == ws_entry_bb
789 && single_succ (ws_exit_bb) == par_exit_bb
790 && workshare_safe_to_combine_p (ws_entry_bb)
791 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
792 || (last_and_only_stmt (ws_entry_bb)
793 && last_and_only_stmt (par_exit_bb))))
795 gimple par_stmt = last_stmt (par_entry_bb);
796 gimple ws_stmt = last_stmt (ws_entry_bb);
798 if (region->inner->type == GIMPLE_OMP_FOR)
800 /* If this is a combined parallel loop, we need to determine
801 whether or not to use the combined library calls. There
802 are two cases where we do not apply the transformation:
803 static loops and any kind of ordered loop. In the first
804 case, we already open code the loop so there is no need
805 to do anything else. In the latter case, the combined
806 parallel loop call would still need extra synchronization
807 to implement ordered semantics, so there would not be any
808 gain in using the combined call. */
809 tree clauses = gimple_omp_for_clauses (ws_stmt);
810 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
811 if (c == NULL
812 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
813 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
815 region->is_combined_parallel = false;
816 region->inner->is_combined_parallel = false;
817 return;
821 region->is_combined_parallel = true;
822 region->inner->is_combined_parallel = true;
823 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
828 /* Return true if EXPR is variable sized. */
830 static inline bool
831 is_variable_sized (const_tree expr)
833 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
836 /* Return true if DECL is a reference type. */
838 static inline bool
839 is_reference (tree decl)
841 return lang_hooks.decls.omp_privatize_by_reference (decl);
844 /* Lookup variables in the decl or field splay trees. The "maybe" form
845 allows for the variable form to not have been entered, otherwise we
846 assert that the variable must have been entered. */
848 static inline tree
849 lookup_decl (tree var, omp_context *ctx)
851 tree *n = ctx->cb.decl_map->get (var);
852 return *n;
855 static inline tree
856 maybe_lookup_decl (const_tree var, omp_context *ctx)
858 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
859 return n ? *n : NULL_TREE;
862 static inline tree
863 lookup_field (tree var, omp_context *ctx)
865 splay_tree_node n;
866 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
867 return (tree) n->value;
870 static inline tree
871 lookup_sfield (tree var, omp_context *ctx)
873 splay_tree_node n;
874 n = splay_tree_lookup (ctx->sfield_map
875 ? ctx->sfield_map : ctx->field_map,
876 (splay_tree_key) var);
877 return (tree) n->value;
880 static inline tree
881 maybe_lookup_field (tree var, omp_context *ctx)
883 splay_tree_node n;
884 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
885 return n ? (tree) n->value : NULL_TREE;
888 /* Return true if DECL should be copied by pointer. SHARED_CTX is
889 the parallel context if DECL is to be shared. */
891 static bool
892 use_pointer_for_field (tree decl, omp_context *shared_ctx)
894 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
895 return true;
897 /* We can only use copy-in/copy-out semantics for shared variables
898 when we know the value is not accessible from an outer scope. */
899 if (shared_ctx)
901 /* ??? Trivially accessible from anywhere. But why would we even
902 be passing an address in this case? Should we simply assert
903 this to be false, or should we have a cleanup pass that removes
904 these from the list of mappings? */
905 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
906 return true;
908 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
909 without analyzing the expression whether or not its location
910 is accessible to anyone else. In the case of nested parallel
911 regions it certainly may be. */
912 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
913 return true;
915 /* Do not use copy-in/copy-out for variables that have their
916 address taken. */
917 if (TREE_ADDRESSABLE (decl))
918 return true;
920 /* lower_send_shared_vars only uses copy-in, but not copy-out
921 for these. */
922 if (TREE_READONLY (decl)
923 || ((TREE_CODE (decl) == RESULT_DECL
924 || TREE_CODE (decl) == PARM_DECL)
925 && DECL_BY_REFERENCE (decl)))
926 return false;
928 /* Disallow copy-in/out in nested parallel if
929 decl is shared in outer parallel, otherwise
930 each thread could store the shared variable
931 in its own copy-in location, making the
932 variable no longer really shared. */
933 if (shared_ctx->is_nested)
935 omp_context *up;
937 for (up = shared_ctx->outer; up; up = up->outer)
938 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
939 break;
941 if (up)
943 tree c;
945 for (c = gimple_omp_taskreg_clauses (up->stmt);
946 c; c = OMP_CLAUSE_CHAIN (c))
947 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
948 && OMP_CLAUSE_DECL (c) == decl)
949 break;
951 if (c)
952 goto maybe_mark_addressable_and_ret;
956 /* For tasks avoid using copy-in/out. As tasks can be
957 deferred or executed in different thread, when GOMP_task
958 returns, the task hasn't necessarily terminated. */
959 if (is_task_ctx (shared_ctx))
961 tree outer;
962 maybe_mark_addressable_and_ret:
963 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
964 if (is_gimple_reg (outer))
966 /* Taking address of OUTER in lower_send_shared_vars
967 might need regimplification of everything that uses the
968 variable. */
969 if (!task_shared_vars)
970 task_shared_vars = BITMAP_ALLOC (NULL);
971 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
972 TREE_ADDRESSABLE (outer) = 1;
974 return true;
978 return false;
981 /* Construct a new automatic decl similar to VAR. */
983 static tree
984 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
986 tree copy = copy_var_decl (var, name, type);
988 DECL_CONTEXT (copy) = current_function_decl;
989 DECL_CHAIN (copy) = ctx->block_vars;
990 ctx->block_vars = copy;
992 return copy;
995 static tree
996 omp_copy_decl_1 (tree var, omp_context *ctx)
998 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1001 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1002 as appropriate. */
1003 static tree
1004 omp_build_component_ref (tree obj, tree field)
1006 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1007 if (TREE_THIS_VOLATILE (field))
1008 TREE_THIS_VOLATILE (ret) |= 1;
1009 if (TREE_READONLY (field))
1010 TREE_READONLY (ret) |= 1;
1011 return ret;
1014 /* Build tree nodes to access the field for VAR on the receiver side. */
1016 static tree
1017 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1019 tree x, field = lookup_field (var, ctx);
1021 /* If the receiver record type was remapped in the child function,
1022 remap the field into the new record type. */
1023 x = maybe_lookup_field (field, ctx);
1024 if (x != NULL)
1025 field = x;
1027 x = build_simple_mem_ref (ctx->receiver_decl);
1028 x = omp_build_component_ref (x, field);
1029 if (by_ref)
1030 x = build_simple_mem_ref (x);
1032 return x;
1035 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1036 of a parallel, this is a component reference; for workshare constructs
1037 this is some variable. */
1039 static tree
1040 build_outer_var_ref (tree var, omp_context *ctx)
1042 tree x;
1044 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1045 x = var;
1046 else if (is_variable_sized (var))
1048 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1049 x = build_outer_var_ref (x, ctx);
1050 x = build_simple_mem_ref (x);
1052 else if (is_taskreg_ctx (ctx))
1054 bool by_ref = use_pointer_for_field (var, NULL);
1055 x = build_receiver_ref (var, by_ref, ctx);
1057 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1058 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1060 /* #pragma omp simd isn't a worksharing construct, and can reference even
1061 private vars in its linear etc. clauses. */
1062 x = NULL_TREE;
1063 if (ctx->outer && is_taskreg_ctx (ctx))
1064 x = lookup_decl (var, ctx->outer);
1065 else if (ctx->outer)
1066 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1067 if (x == NULL_TREE)
1068 x = var;
1070 else if (ctx->outer)
1071 x = lookup_decl (var, ctx->outer);
1072 else if (is_reference (var))
1073 /* This can happen with orphaned constructs. If var is reference, it is
1074 possible it is shared and as such valid. */
1075 x = var;
1076 else
1077 gcc_unreachable ();
1079 if (is_reference (var))
1080 x = build_simple_mem_ref (x);
1082 return x;
1085 /* Build tree nodes to access the field for VAR on the sender side. */
1087 static tree
1088 build_sender_ref (tree var, omp_context *ctx)
1090 tree field = lookup_sfield (var, ctx);
1091 return omp_build_component_ref (ctx->sender_decl, field);
1094 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1096 static void
1097 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1099 tree field, type, sfield = NULL_TREE;
1101 gcc_assert ((mask & 1) == 0
1102 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1103 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1104 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1106 type = TREE_TYPE (var);
1107 if (mask & 4)
1109 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1110 type = build_pointer_type (build_pointer_type (type));
1112 else if (by_ref)
1113 type = build_pointer_type (type);
1114 else if ((mask & 3) == 1 && is_reference (var))
1115 type = TREE_TYPE (type);
1117 field = build_decl (DECL_SOURCE_LOCATION (var),
1118 FIELD_DECL, DECL_NAME (var), type);
1120 /* Remember what variable this field was created for. This does have a
1121 side effect of making dwarf2out ignore this member, so for helpful
1122 debugging we clear it later in delete_omp_context. */
1123 DECL_ABSTRACT_ORIGIN (field) = var;
1124 if (type == TREE_TYPE (var))
1126 DECL_ALIGN (field) = DECL_ALIGN (var);
1127 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1128 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1130 else
1131 DECL_ALIGN (field) = TYPE_ALIGN (type);
1133 if ((mask & 3) == 3)
1135 insert_field_into_struct (ctx->record_type, field);
1136 if (ctx->srecord_type)
1138 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1139 FIELD_DECL, DECL_NAME (var), type);
1140 DECL_ABSTRACT_ORIGIN (sfield) = var;
1141 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1142 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1143 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1144 insert_field_into_struct (ctx->srecord_type, sfield);
1147 else
1149 if (ctx->srecord_type == NULL_TREE)
1151 tree t;
1153 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1154 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1155 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1157 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1158 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1159 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1160 insert_field_into_struct (ctx->srecord_type, sfield);
1161 splay_tree_insert (ctx->sfield_map,
1162 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1163 (splay_tree_value) sfield);
1166 sfield = field;
1167 insert_field_into_struct ((mask & 1) ? ctx->record_type
1168 : ctx->srecord_type, field);
1171 if (mask & 1)
1172 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1173 (splay_tree_value) field);
1174 if ((mask & 2) && ctx->sfield_map)
1175 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1176 (splay_tree_value) sfield);
1179 static tree
1180 install_var_local (tree var, omp_context *ctx)
1182 tree new_var = omp_copy_decl_1 (var, ctx);
1183 insert_decl_map (&ctx->cb, var, new_var);
1184 return new_var;
1187 /* Adjust the replacement for DECL in CTX for the new context. This means
1188 copying the DECL_VALUE_EXPR, and fixing up the type. */
1190 static void
1191 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1193 tree new_decl, size;
1195 new_decl = lookup_decl (decl, ctx);
1197 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1199 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1200 && DECL_HAS_VALUE_EXPR_P (decl))
1202 tree ve = DECL_VALUE_EXPR (decl);
1203 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1204 SET_DECL_VALUE_EXPR (new_decl, ve);
1205 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1208 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1210 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1211 if (size == error_mark_node)
1212 size = TYPE_SIZE (TREE_TYPE (new_decl));
1213 DECL_SIZE (new_decl) = size;
1215 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1216 if (size == error_mark_node)
1217 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1218 DECL_SIZE_UNIT (new_decl) = size;
1222 /* The callback for remap_decl. Search all containing contexts for a
1223 mapping of the variable; this avoids having to duplicate the splay
1224 tree ahead of time. We know a mapping doesn't already exist in the
1225 given context. Create new mappings to implement default semantics. */
1227 static tree
1228 omp_copy_decl (tree var, copy_body_data *cb)
1230 omp_context *ctx = (omp_context *) cb;
1231 tree new_var;
1233 if (TREE_CODE (var) == LABEL_DECL)
1235 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1236 DECL_CONTEXT (new_var) = current_function_decl;
1237 insert_decl_map (&ctx->cb, var, new_var);
1238 return new_var;
1241 while (!is_taskreg_ctx (ctx))
1243 ctx = ctx->outer;
1244 if (ctx == NULL)
1245 return var;
1246 new_var = maybe_lookup_decl (var, ctx);
1247 if (new_var)
1248 return new_var;
1251 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1252 return var;
1254 return error_mark_node;
1258 /* Debugging dumps for parallel regions. */
1259 void dump_omp_region (FILE *, struct omp_region *, int);
1260 void debug_omp_region (struct omp_region *);
1261 void debug_all_omp_regions (void);
1263 /* Dump the parallel region tree rooted at REGION. */
1265 void
1266 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1268 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1269 gimple_code_name[region->type]);
1271 if (region->inner)
1272 dump_omp_region (file, region->inner, indent + 4);
1274 if (region->cont)
1276 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1277 region->cont->index);
1280 if (region->exit)
1281 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1282 region->exit->index);
1283 else
1284 fprintf (file, "%*s[no exit marker]\n", indent, "");
1286 if (region->next)
1287 dump_omp_region (file, region->next, indent);
1290 DEBUG_FUNCTION void
1291 debug_omp_region (struct omp_region *region)
1293 dump_omp_region (stderr, region, 0);
1296 DEBUG_FUNCTION void
1297 debug_all_omp_regions (void)
1299 dump_omp_region (stderr, root_omp_region, 0);
1303 /* Create a new parallel region starting at STMT inside region PARENT. */
1305 static struct omp_region *
1306 new_omp_region (basic_block bb, enum gimple_code type,
1307 struct omp_region *parent)
1309 struct omp_region *region = XCNEW (struct omp_region);
1311 region->outer = parent;
1312 region->entry = bb;
1313 region->type = type;
1315 if (parent)
1317 /* This is a nested region. Add it to the list of inner
1318 regions in PARENT. */
1319 region->next = parent->inner;
1320 parent->inner = region;
1322 else
1324 /* This is a toplevel region. Add it to the list of toplevel
1325 regions in ROOT_OMP_REGION. */
1326 region->next = root_omp_region;
1327 root_omp_region = region;
1330 return region;
1333 /* Release the memory associated with the region tree rooted at REGION. */
1335 static void
1336 free_omp_region_1 (struct omp_region *region)
1338 struct omp_region *i, *n;
1340 for (i = region->inner; i ; i = n)
1342 n = i->next;
1343 free_omp_region_1 (i);
1346 free (region);
1349 /* Release the memory for the entire omp region tree. */
1351 void
1352 free_omp_regions (void)
1354 struct omp_region *r, *n;
1355 for (r = root_omp_region; r ; r = n)
1357 n = r->next;
1358 free_omp_region_1 (r);
1360 root_omp_region = NULL;
1364 /* Create a new context, with OUTER_CTX being the surrounding context. */
1366 static omp_context *
1367 new_omp_context (gimple stmt, omp_context *outer_ctx)
1369 omp_context *ctx = XCNEW (omp_context);
1371 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1372 (splay_tree_value) ctx);
1373 ctx->stmt = stmt;
1375 if (outer_ctx)
1377 ctx->outer = outer_ctx;
1378 ctx->cb = outer_ctx->cb;
1379 ctx->cb.block = NULL;
1380 ctx->depth = outer_ctx->depth + 1;
1382 else
1384 ctx->cb.src_fn = current_function_decl;
1385 ctx->cb.dst_fn = current_function_decl;
1386 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1387 gcc_checking_assert (ctx->cb.src_node);
1388 ctx->cb.dst_node = ctx->cb.src_node;
1389 ctx->cb.src_cfun = cfun;
1390 ctx->cb.copy_decl = omp_copy_decl;
1391 ctx->cb.eh_lp_nr = 0;
1392 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1393 ctx->depth = 1;
1396 ctx->cb.decl_map = new hash_map<tree, tree>;
1398 return ctx;
1401 static gimple_seq maybe_catch_exception (gimple_seq);
1403 /* Finalize task copyfn. */
1405 static void
1406 finalize_task_copyfn (gimple task_stmt)
1408 struct function *child_cfun;
1409 tree child_fn;
1410 gimple_seq seq = NULL, new_seq;
1411 gimple bind;
1413 child_fn = gimple_omp_task_copy_fn (task_stmt);
1414 if (child_fn == NULL_TREE)
1415 return;
1417 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1418 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1420 push_cfun (child_cfun);
1421 bind = gimplify_body (child_fn, false);
1422 gimple_seq_add_stmt (&seq, bind);
1423 new_seq = maybe_catch_exception (seq);
1424 if (new_seq != seq)
1426 bind = gimple_build_bind (NULL, new_seq, NULL);
1427 seq = NULL;
1428 gimple_seq_add_stmt (&seq, bind);
1430 gimple_set_body (child_fn, seq);
1431 pop_cfun ();
1433 /* Inform the callgraph about the new function. */
1434 cgraph_node::add_new_function (child_fn, false);
1437 /* Destroy a omp_context data structures. Called through the splay tree
1438 value delete callback. */
1440 static void
1441 delete_omp_context (splay_tree_value value)
1443 omp_context *ctx = (omp_context *) value;
1445 delete ctx->cb.decl_map;
1447 if (ctx->field_map)
1448 splay_tree_delete (ctx->field_map);
1449 if (ctx->sfield_map)
1450 splay_tree_delete (ctx->sfield_map);
1452 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1453 it produces corrupt debug information. */
1454 if (ctx->record_type)
1456 tree t;
1457 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1458 DECL_ABSTRACT_ORIGIN (t) = NULL;
1460 if (ctx->srecord_type)
1462 tree t;
1463 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1464 DECL_ABSTRACT_ORIGIN (t) = NULL;
1467 if (is_task_ctx (ctx))
1468 finalize_task_copyfn (ctx->stmt);
1470 XDELETE (ctx);
1473 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1474 context. */
1476 static void
1477 fixup_child_record_type (omp_context *ctx)
1479 tree f, type = ctx->record_type;
1481 /* ??? It isn't sufficient to just call remap_type here, because
1482 variably_modified_type_p doesn't work the way we expect for
1483 record types. Testing each field for whether it needs remapping
1484 and creating a new record by hand works, however. */
1485 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1486 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1487 break;
1488 if (f)
1490 tree name, new_fields = NULL;
1492 type = lang_hooks.types.make_type (RECORD_TYPE);
1493 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1494 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1495 TYPE_DECL, name, type);
1496 TYPE_NAME (type) = name;
1498 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1500 tree new_f = copy_node (f);
1501 DECL_CONTEXT (new_f) = type;
1502 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1503 DECL_CHAIN (new_f) = new_fields;
1504 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1505 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1506 &ctx->cb, NULL);
1507 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1508 &ctx->cb, NULL);
1509 new_fields = new_f;
1511 /* Arrange to be able to look up the receiver field
1512 given the sender field. */
1513 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1514 (splay_tree_value) new_f);
1516 TYPE_FIELDS (type) = nreverse (new_fields);
1517 layout_type (type);
1520 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1523 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1524 specified by CLAUSES. */
1526 static void
1527 scan_sharing_clauses (tree clauses, omp_context *ctx)
1529 tree c, decl;
1530 bool scan_array_reductions = false;
1532 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1534 bool by_ref;
1536 switch (OMP_CLAUSE_CODE (c))
1538 case OMP_CLAUSE_PRIVATE:
1539 decl = OMP_CLAUSE_DECL (c);
1540 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1541 goto do_private;
1542 else if (!is_variable_sized (decl))
1543 install_var_local (decl, ctx);
1544 break;
1546 case OMP_CLAUSE_SHARED:
1547 decl = OMP_CLAUSE_DECL (c);
1548 /* Ignore shared directives in teams construct. */
1549 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1551 /* Global variables don't need to be copied,
1552 the receiver side will use them directly. */
1553 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1554 if (is_global_var (odecl))
1555 break;
1556 insert_decl_map (&ctx->cb, decl, odecl);
1557 break;
1559 gcc_assert (is_taskreg_ctx (ctx));
1560 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1561 || !is_variable_sized (decl));
1562 /* Global variables don't need to be copied,
1563 the receiver side will use them directly. */
1564 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1565 break;
1566 by_ref = use_pointer_for_field (decl, ctx);
1567 if (! TREE_READONLY (decl)
1568 || TREE_ADDRESSABLE (decl)
1569 || by_ref
1570 || is_reference (decl))
1572 install_var_field (decl, by_ref, 3, ctx);
1573 install_var_local (decl, ctx);
1574 break;
1576 /* We don't need to copy const scalar vars back. */
1577 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1578 goto do_private;
1580 case OMP_CLAUSE_LASTPRIVATE:
1581 /* Let the corresponding firstprivate clause create
1582 the variable. */
1583 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1584 break;
1585 /* FALLTHRU */
1587 case OMP_CLAUSE_FIRSTPRIVATE:
1588 case OMP_CLAUSE_REDUCTION:
1589 case OMP_CLAUSE_LINEAR:
1590 decl = OMP_CLAUSE_DECL (c);
1591 do_private:
1592 if (is_variable_sized (decl))
1594 if (is_task_ctx (ctx))
1595 install_var_field (decl, false, 1, ctx);
1596 break;
1598 else if (is_taskreg_ctx (ctx))
1600 bool global
1601 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1602 by_ref = use_pointer_for_field (decl, NULL);
1604 if (is_task_ctx (ctx)
1605 && (global || by_ref || is_reference (decl)))
1607 install_var_field (decl, false, 1, ctx);
1608 if (!global)
1609 install_var_field (decl, by_ref, 2, ctx);
1611 else if (!global)
1612 install_var_field (decl, by_ref, 3, ctx);
1614 install_var_local (decl, ctx);
1615 break;
1617 case OMP_CLAUSE__LOOPTEMP_:
1618 gcc_assert (is_parallel_ctx (ctx));
1619 decl = OMP_CLAUSE_DECL (c);
1620 install_var_field (decl, false, 3, ctx);
1621 install_var_local (decl, ctx);
1622 break;
1624 case OMP_CLAUSE_COPYPRIVATE:
1625 case OMP_CLAUSE_COPYIN:
1626 decl = OMP_CLAUSE_DECL (c);
1627 by_ref = use_pointer_for_field (decl, NULL);
1628 install_var_field (decl, by_ref, 3, ctx);
1629 break;
1631 case OMP_CLAUSE_DEFAULT:
1632 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1633 break;
1635 case OMP_CLAUSE_FINAL:
1636 case OMP_CLAUSE_IF:
1637 case OMP_CLAUSE_NUM_THREADS:
1638 case OMP_CLAUSE_NUM_TEAMS:
1639 case OMP_CLAUSE_THREAD_LIMIT:
1640 case OMP_CLAUSE_DEVICE:
1641 case OMP_CLAUSE_SCHEDULE:
1642 case OMP_CLAUSE_DIST_SCHEDULE:
1643 case OMP_CLAUSE_DEPEND:
1644 case OMP_CLAUSE__CILK_FOR_COUNT_:
1645 if (ctx->outer)
1646 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1647 break;
1649 case OMP_CLAUSE_TO:
1650 case OMP_CLAUSE_FROM:
1651 case OMP_CLAUSE_MAP:
1652 if (ctx->outer)
1653 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1654 decl = OMP_CLAUSE_DECL (c);
1655 /* Global variables with "omp declare target" attribute
1656 don't need to be copied, the receiver side will use them
1657 directly. */
1658 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1659 && DECL_P (decl)
1660 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1661 && varpool_node::get_create (decl)->offloadable)
1662 break;
1663 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1664 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1666 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1667 #pragma omp target data, there is nothing to map for
1668 those. */
1669 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1670 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1671 break;
1673 if (DECL_P (decl))
1675 if (DECL_SIZE (decl)
1676 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1678 tree decl2 = DECL_VALUE_EXPR (decl);
1679 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1680 decl2 = TREE_OPERAND (decl2, 0);
1681 gcc_assert (DECL_P (decl2));
1682 install_var_field (decl2, true, 3, ctx);
1683 install_var_local (decl2, ctx);
1684 install_var_local (decl, ctx);
1686 else
1688 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1689 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1690 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1691 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1692 install_var_field (decl, true, 7, ctx);
1693 else
1694 install_var_field (decl, true, 3, ctx);
1695 if (gimple_omp_target_kind (ctx->stmt)
1696 == GF_OMP_TARGET_KIND_REGION)
1697 install_var_local (decl, ctx);
1700 else
1702 tree base = get_base_address (decl);
1703 tree nc = OMP_CLAUSE_CHAIN (c);
1704 if (DECL_P (base)
1705 && nc != NULL_TREE
1706 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1707 && OMP_CLAUSE_DECL (nc) == base
1708 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1709 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1711 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1712 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1714 else
1716 if (ctx->outer)
1718 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1719 decl = OMP_CLAUSE_DECL (c);
1721 gcc_assert (!splay_tree_lookup (ctx->field_map,
1722 (splay_tree_key) decl));
1723 tree field
1724 = build_decl (OMP_CLAUSE_LOCATION (c),
1725 FIELD_DECL, NULL_TREE, ptr_type_node);
1726 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1727 insert_field_into_struct (ctx->record_type, field);
1728 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1729 (splay_tree_value) field);
1732 break;
1734 case OMP_CLAUSE_NOWAIT:
1735 case OMP_CLAUSE_ORDERED:
1736 case OMP_CLAUSE_COLLAPSE:
1737 case OMP_CLAUSE_UNTIED:
1738 case OMP_CLAUSE_MERGEABLE:
1739 case OMP_CLAUSE_PROC_BIND:
1740 case OMP_CLAUSE_SAFELEN:
1741 break;
1743 case OMP_CLAUSE_ALIGNED:
1744 decl = OMP_CLAUSE_DECL (c);
1745 if (is_global_var (decl)
1746 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1747 install_var_local (decl, ctx);
1748 break;
1750 default:
1751 gcc_unreachable ();
1755 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1757 switch (OMP_CLAUSE_CODE (c))
1759 case OMP_CLAUSE_LASTPRIVATE:
1760 /* Let the corresponding firstprivate clause create
1761 the variable. */
1762 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1763 scan_array_reductions = true;
1764 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1765 break;
1766 /* FALLTHRU */
1768 case OMP_CLAUSE_PRIVATE:
1769 case OMP_CLAUSE_FIRSTPRIVATE:
1770 case OMP_CLAUSE_REDUCTION:
1771 case OMP_CLAUSE_LINEAR:
1772 decl = OMP_CLAUSE_DECL (c);
1773 if (is_variable_sized (decl))
1774 install_var_local (decl, ctx);
1775 fixup_remapped_decl (decl, ctx,
1776 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1777 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1778 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1779 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1780 scan_array_reductions = true;
1781 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1782 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1783 scan_array_reductions = true;
1784 break;
1786 case OMP_CLAUSE_SHARED:
1787 /* Ignore shared directives in teams construct. */
1788 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1789 break;
1790 decl = OMP_CLAUSE_DECL (c);
1791 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1792 fixup_remapped_decl (decl, ctx, false);
1793 break;
1795 case OMP_CLAUSE_MAP:
1796 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1797 break;
1798 decl = OMP_CLAUSE_DECL (c);
1799 if (DECL_P (decl)
1800 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1801 && varpool_node::get_create (decl)->offloadable)
1802 break;
1803 if (DECL_P (decl))
1805 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1806 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1807 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1809 tree new_decl = lookup_decl (decl, ctx);
1810 TREE_TYPE (new_decl)
1811 = remap_type (TREE_TYPE (decl), &ctx->cb);
1813 else if (DECL_SIZE (decl)
1814 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1816 tree decl2 = DECL_VALUE_EXPR (decl);
1817 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1818 decl2 = TREE_OPERAND (decl2, 0);
1819 gcc_assert (DECL_P (decl2));
1820 fixup_remapped_decl (decl2, ctx, false);
1821 fixup_remapped_decl (decl, ctx, true);
1823 else
1824 fixup_remapped_decl (decl, ctx, false);
1826 break;
1828 case OMP_CLAUSE_COPYPRIVATE:
1829 case OMP_CLAUSE_COPYIN:
1830 case OMP_CLAUSE_DEFAULT:
1831 case OMP_CLAUSE_IF:
1832 case OMP_CLAUSE_NUM_THREADS:
1833 case OMP_CLAUSE_NUM_TEAMS:
1834 case OMP_CLAUSE_THREAD_LIMIT:
1835 case OMP_CLAUSE_DEVICE:
1836 case OMP_CLAUSE_SCHEDULE:
1837 case OMP_CLAUSE_DIST_SCHEDULE:
1838 case OMP_CLAUSE_NOWAIT:
1839 case OMP_CLAUSE_ORDERED:
1840 case OMP_CLAUSE_COLLAPSE:
1841 case OMP_CLAUSE_UNTIED:
1842 case OMP_CLAUSE_FINAL:
1843 case OMP_CLAUSE_MERGEABLE:
1844 case OMP_CLAUSE_PROC_BIND:
1845 case OMP_CLAUSE_SAFELEN:
1846 case OMP_CLAUSE_ALIGNED:
1847 case OMP_CLAUSE_DEPEND:
1848 case OMP_CLAUSE__LOOPTEMP_:
1849 case OMP_CLAUSE_TO:
1850 case OMP_CLAUSE_FROM:
1851 case OMP_CLAUSE__CILK_FOR_COUNT_:
1852 break;
1854 default:
1855 gcc_unreachable ();
1859 if (scan_array_reductions)
1860 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1861 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1862 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1864 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1865 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1867 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1868 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1869 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1870 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1871 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1872 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1875 /* Create a new name for omp child function. Returns an identifier. If
1876 IS_CILK_FOR is true then the suffix for the child function is
1877 "_cilk_for_fn." */
1879 static tree
1880 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1882 if (is_cilk_for)
1883 return clone_function_name (current_function_decl, "_cilk_for_fn");
1884 return clone_function_name (current_function_decl,
1885 task_copy ? "_omp_cpyfn" : "_omp_fn");
1888 /* Returns the type of the induction variable for the child function for
1889 _Cilk_for and the types for _high and _low variables based on TYPE. */
1891 static tree
1892 cilk_for_check_loop_diff_type (tree type)
1894 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
1896 if (TYPE_UNSIGNED (type))
1897 return uint32_type_node;
1898 else
1899 return integer_type_node;
1901 else
1903 if (TYPE_UNSIGNED (type))
1904 return uint64_type_node;
1905 else
1906 return long_long_integer_type_node;
1910 /* Build a decl for the omp child function. It'll not contain a body
1911 yet, just the bare decl. */
1913 static void
1914 create_omp_child_function (omp_context *ctx, bool task_copy)
1916 tree decl, type, name, t;
1918 tree cilk_for_count
1919 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
1920 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1921 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
1922 tree cilk_var_type = NULL_TREE;
1924 name = create_omp_child_function_name (task_copy,
1925 cilk_for_count != NULL_TREE);
1926 if (task_copy)
1927 type = build_function_type_list (void_type_node, ptr_type_node,
1928 ptr_type_node, NULL_TREE);
1929 else if (cilk_for_count)
1931 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
1932 cilk_var_type = cilk_for_check_loop_diff_type (type);
1933 type = build_function_type_list (void_type_node, ptr_type_node,
1934 cilk_var_type, cilk_var_type, NULL_TREE);
1936 else
1937 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1939 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1941 if (!task_copy)
1942 ctx->cb.dst_fn = decl;
1943 else
1944 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1946 TREE_STATIC (decl) = 1;
1947 TREE_USED (decl) = 1;
1948 DECL_ARTIFICIAL (decl) = 1;
1949 DECL_IGNORED_P (decl) = 0;
1950 TREE_PUBLIC (decl) = 0;
1951 DECL_UNINLINABLE (decl) = 1;
1952 DECL_EXTERNAL (decl) = 0;
1953 DECL_CONTEXT (decl) = NULL_TREE;
1954 DECL_INITIAL (decl) = make_node (BLOCK);
1955 if (cgraph_node::get (current_function_decl)->offloadable)
1956 cgraph_node::get_create (decl)->offloadable = 1;
1957 else
1959 omp_context *octx;
1960 for (octx = ctx; octx; octx = octx->outer)
1961 if (is_targetreg_ctx (octx))
1963 cgraph_node::get_create (decl)->offloadable = 1;
1964 g->have_offload = true;
1965 break;
1969 t = build_decl (DECL_SOURCE_LOCATION (decl),
1970 RESULT_DECL, NULL_TREE, void_type_node);
1971 DECL_ARTIFICIAL (t) = 1;
1972 DECL_IGNORED_P (t) = 1;
1973 DECL_CONTEXT (t) = decl;
1974 DECL_RESULT (decl) = t;
1976 /* _Cilk_for's child function requires two extra parameters called
1977 __low and __high that are set the by Cilk runtime when it calls this
1978 function. */
1979 if (cilk_for_count)
1981 t = build_decl (DECL_SOURCE_LOCATION (decl),
1982 PARM_DECL, get_identifier ("__high"), cilk_var_type);
1983 DECL_ARTIFICIAL (t) = 1;
1984 DECL_NAMELESS (t) = 1;
1985 DECL_ARG_TYPE (t) = ptr_type_node;
1986 DECL_CONTEXT (t) = current_function_decl;
1987 TREE_USED (t) = 1;
1988 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1989 DECL_ARGUMENTS (decl) = t;
1991 t = build_decl (DECL_SOURCE_LOCATION (decl),
1992 PARM_DECL, get_identifier ("__low"), cilk_var_type);
1993 DECL_ARTIFICIAL (t) = 1;
1994 DECL_NAMELESS (t) = 1;
1995 DECL_ARG_TYPE (t) = ptr_type_node;
1996 DECL_CONTEXT (t) = current_function_decl;
1997 TREE_USED (t) = 1;
1998 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1999 DECL_ARGUMENTS (decl) = t;
2002 tree data_name = get_identifier (".omp_data_i");
2003 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2004 ptr_type_node);
2005 DECL_ARTIFICIAL (t) = 1;
2006 DECL_NAMELESS (t) = 1;
2007 DECL_ARG_TYPE (t) = ptr_type_node;
2008 DECL_CONTEXT (t) = current_function_decl;
2009 TREE_USED (t) = 1;
2010 if (cilk_for_count)
2011 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2012 DECL_ARGUMENTS (decl) = t;
2013 if (!task_copy)
2014 ctx->receiver_decl = t;
2015 else
2017 t = build_decl (DECL_SOURCE_LOCATION (decl),
2018 PARM_DECL, get_identifier (".omp_data_o"),
2019 ptr_type_node);
2020 DECL_ARTIFICIAL (t) = 1;
2021 DECL_NAMELESS (t) = 1;
2022 DECL_ARG_TYPE (t) = ptr_type_node;
2023 DECL_CONTEXT (t) = current_function_decl;
2024 TREE_USED (t) = 1;
2025 TREE_ADDRESSABLE (t) = 1;
2026 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2027 DECL_ARGUMENTS (decl) = t;
2030 /* Allocate memory for the function structure. The call to
2031 allocate_struct_function clobbers CFUN, so we need to restore
2032 it afterward. */
2033 push_struct_function (decl);
2034 cfun->function_end_locus = gimple_location (ctx->stmt);
2035 pop_cfun ();
2038 /* Callback for walk_gimple_seq. Check if combined parallel
2039 contains gimple_omp_for_combined_into_p OMP_FOR. */
2041 static tree
2042 find_combined_for (gimple_stmt_iterator *gsi_p,
2043 bool *handled_ops_p,
2044 struct walk_stmt_info *wi)
2046 gimple stmt = gsi_stmt (*gsi_p);
2048 *handled_ops_p = true;
2049 switch (gimple_code (stmt))
2051 WALK_SUBSTMTS;
2053 case GIMPLE_OMP_FOR:
2054 if (gimple_omp_for_combined_into_p (stmt)
2055 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2057 wi->info = stmt;
2058 return integer_zero_node;
2060 break;
2061 default:
2062 break;
2064 return NULL;
2067 /* Scan an OpenMP parallel directive. */
2069 static void
2070 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2072 omp_context *ctx;
2073 tree name;
2074 gimple stmt = gsi_stmt (*gsi);
2076 /* Ignore parallel directives with empty bodies, unless there
2077 are copyin clauses. */
2078 if (optimize > 0
2079 && empty_body_p (gimple_omp_body (stmt))
2080 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2081 OMP_CLAUSE_COPYIN) == NULL)
2083 gsi_replace (gsi, gimple_build_nop (), false);
2084 return;
2087 if (gimple_omp_parallel_combined_p (stmt))
2089 gimple for_stmt;
2090 struct walk_stmt_info wi;
2092 memset (&wi, 0, sizeof (wi));
2093 wi.val_only = true;
2094 walk_gimple_seq (gimple_omp_body (stmt),
2095 find_combined_for, NULL, &wi);
2096 for_stmt = (gimple) wi.info;
2097 if (for_stmt)
2099 struct omp_for_data fd;
2100 extract_omp_for_data (for_stmt, &fd, NULL);
2101 /* We need two temporaries with fd.loop.v type (istart/iend)
2102 and then (fd.collapse - 1) temporaries with the same
2103 type for count2 ... countN-1 vars if not constant. */
2104 size_t count = 2, i;
2105 tree type = fd.iter_type;
2106 if (fd.collapse > 1
2107 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2108 count += fd.collapse - 1;
2109 for (i = 0; i < count; i++)
2111 tree temp = create_tmp_var (type, NULL);
2112 tree c = build_omp_clause (UNKNOWN_LOCATION,
2113 OMP_CLAUSE__LOOPTEMP_);
2114 insert_decl_map (&outer_ctx->cb, temp, temp);
2115 OMP_CLAUSE_DECL (c) = temp;
2116 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2117 gimple_omp_parallel_set_clauses (stmt, c);
2122 ctx = new_omp_context (stmt, outer_ctx);
2123 taskreg_contexts.safe_push (ctx);
2124 if (taskreg_nesting_level > 1)
2125 ctx->is_nested = true;
2126 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2127 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2128 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2129 name = create_tmp_var_name (".omp_data_s");
2130 name = build_decl (gimple_location (stmt),
2131 TYPE_DECL, name, ctx->record_type);
2132 DECL_ARTIFICIAL (name) = 1;
2133 DECL_NAMELESS (name) = 1;
2134 TYPE_NAME (ctx->record_type) = name;
2135 create_omp_child_function (ctx, false);
2136 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2138 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2139 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2141 if (TYPE_FIELDS (ctx->record_type) == NULL)
2142 ctx->record_type = ctx->receiver_decl = NULL;
2145 /* Scan an OpenMP task directive. */
2147 static void
2148 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2150 omp_context *ctx;
2151 tree name, t;
2152 gimple stmt = gsi_stmt (*gsi);
2154 /* Ignore task directives with empty bodies. */
2155 if (optimize > 0
2156 && empty_body_p (gimple_omp_body (stmt)))
2158 gsi_replace (gsi, gimple_build_nop (), false);
2159 return;
2162 ctx = new_omp_context (stmt, outer_ctx);
2163 taskreg_contexts.safe_push (ctx);
2164 if (taskreg_nesting_level > 1)
2165 ctx->is_nested = true;
2166 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2167 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2168 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2169 name = create_tmp_var_name (".omp_data_s");
2170 name = build_decl (gimple_location (stmt),
2171 TYPE_DECL, name, ctx->record_type);
2172 DECL_ARTIFICIAL (name) = 1;
2173 DECL_NAMELESS (name) = 1;
2174 TYPE_NAME (ctx->record_type) = name;
2175 create_omp_child_function (ctx, false);
2176 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2178 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2180 if (ctx->srecord_type)
2182 name = create_tmp_var_name (".omp_data_a");
2183 name = build_decl (gimple_location (stmt),
2184 TYPE_DECL, name, ctx->srecord_type);
2185 DECL_ARTIFICIAL (name) = 1;
2186 DECL_NAMELESS (name) = 1;
2187 TYPE_NAME (ctx->srecord_type) = name;
2188 create_omp_child_function (ctx, true);
2191 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2193 if (TYPE_FIELDS (ctx->record_type) == NULL)
2195 ctx->record_type = ctx->receiver_decl = NULL;
2196 t = build_int_cst (long_integer_type_node, 0);
2197 gimple_omp_task_set_arg_size (stmt, t);
2198 t = build_int_cst (long_integer_type_node, 1);
2199 gimple_omp_task_set_arg_align (stmt, t);
2204 /* If any decls have been made addressable during scan_omp,
2205 adjust their fields if needed, and layout record types
2206 of parallel/task constructs. */
2208 static void
2209 finish_taskreg_scan (omp_context *ctx)
2211 if (ctx->record_type == NULL_TREE)
2212 return;
2214 /* If any task_shared_vars were needed, verify all
2215 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2216 statements if use_pointer_for_field hasn't changed
2217 because of that. If it did, update field types now. */
2218 if (task_shared_vars)
2220 tree c;
2222 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2223 c; c = OMP_CLAUSE_CHAIN (c))
2224 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2226 tree decl = OMP_CLAUSE_DECL (c);
2228 /* Global variables don't need to be copied,
2229 the receiver side will use them directly. */
2230 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2231 continue;
2232 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2233 || !use_pointer_for_field (decl, ctx))
2234 continue;
2235 tree field = lookup_field (decl, ctx);
2236 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2237 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2238 continue;
2239 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2240 TREE_THIS_VOLATILE (field) = 0;
2241 DECL_USER_ALIGN (field) = 0;
2242 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2243 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2244 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2245 if (ctx->srecord_type)
2247 tree sfield = lookup_sfield (decl, ctx);
2248 TREE_TYPE (sfield) = TREE_TYPE (field);
2249 TREE_THIS_VOLATILE (sfield) = 0;
2250 DECL_USER_ALIGN (sfield) = 0;
2251 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2252 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2253 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2258 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2260 layout_type (ctx->record_type);
2261 fixup_child_record_type (ctx);
2263 else
2265 location_t loc = gimple_location (ctx->stmt);
2266 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2267 /* Move VLA fields to the end. */
2268 p = &TYPE_FIELDS (ctx->record_type);
2269 while (*p)
2270 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2271 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2273 *q = *p;
2274 *p = TREE_CHAIN (*p);
2275 TREE_CHAIN (*q) = NULL_TREE;
2276 q = &TREE_CHAIN (*q);
2278 else
2279 p = &DECL_CHAIN (*p);
2280 *p = vla_fields;
2281 layout_type (ctx->record_type);
2282 fixup_child_record_type (ctx);
2283 if (ctx->srecord_type)
2284 layout_type (ctx->srecord_type);
2285 tree t = fold_convert_loc (loc, long_integer_type_node,
2286 TYPE_SIZE_UNIT (ctx->record_type));
2287 gimple_omp_task_set_arg_size (ctx->stmt, t);
2288 t = build_int_cst (long_integer_type_node,
2289 TYPE_ALIGN_UNIT (ctx->record_type));
2290 gimple_omp_task_set_arg_align (ctx->stmt, t);
2295 /* Scan an OpenMP loop directive. */
2297 static void
2298 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2300 omp_context *ctx;
2301 size_t i;
2303 ctx = new_omp_context (stmt, outer_ctx);
2305 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2307 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2308 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2310 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2311 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2312 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2313 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2315 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2318 /* Scan an OpenMP sections directive. */
2320 static void
2321 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2323 omp_context *ctx;
2325 ctx = new_omp_context (stmt, outer_ctx);
2326 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2327 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2330 /* Scan an OpenMP single directive. */
2332 static void
2333 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2335 omp_context *ctx;
2336 tree name;
2338 ctx = new_omp_context (stmt, outer_ctx);
2339 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2340 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2341 name = create_tmp_var_name (".omp_copy_s");
2342 name = build_decl (gimple_location (stmt),
2343 TYPE_DECL, name, ctx->record_type);
2344 TYPE_NAME (ctx->record_type) = name;
2346 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2347 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2349 if (TYPE_FIELDS (ctx->record_type) == NULL)
2350 ctx->record_type = NULL;
2351 else
2352 layout_type (ctx->record_type);
2355 /* Scan an OpenMP target{, data, update} directive. */
2357 static void
2358 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2360 omp_context *ctx;
2361 tree name;
2362 int kind = gimple_omp_target_kind (stmt);
2364 ctx = new_omp_context (stmt, outer_ctx);
2365 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2366 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2367 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2368 name = create_tmp_var_name (".omp_data_t");
2369 name = build_decl (gimple_location (stmt),
2370 TYPE_DECL, name, ctx->record_type);
2371 DECL_ARTIFICIAL (name) = 1;
2372 DECL_NAMELESS (name) = 1;
2373 TYPE_NAME (ctx->record_type) = name;
2374 if (kind == GF_OMP_TARGET_KIND_REGION)
2376 create_omp_child_function (ctx, false);
2377 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2380 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2381 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2383 if (TYPE_FIELDS (ctx->record_type) == NULL)
2384 ctx->record_type = ctx->receiver_decl = NULL;
2385 else
2387 TYPE_FIELDS (ctx->record_type)
2388 = nreverse (TYPE_FIELDS (ctx->record_type));
2389 #ifdef ENABLE_CHECKING
2390 tree field;
2391 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2392 for (field = TYPE_FIELDS (ctx->record_type);
2393 field;
2394 field = DECL_CHAIN (field))
2395 gcc_assert (DECL_ALIGN (field) == align);
2396 #endif
2397 layout_type (ctx->record_type);
2398 if (kind == GF_OMP_TARGET_KIND_REGION)
2399 fixup_child_record_type (ctx);
2403 /* Scan an OpenMP teams directive. */
2405 static void
2406 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2408 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2409 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2410 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2413 /* Check OpenMP nesting restrictions. */
2414 static bool
2415 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2417 if (ctx != NULL)
2419 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2420 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2422 error_at (gimple_location (stmt),
2423 "OpenMP constructs may not be nested inside simd region");
2424 return false;
2426 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2428 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2429 || (gimple_omp_for_kind (stmt)
2430 != GF_OMP_FOR_KIND_DISTRIBUTE))
2431 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2433 error_at (gimple_location (stmt),
2434 "only distribute or parallel constructs are allowed to "
2435 "be closely nested inside teams construct");
2436 return false;
2440 switch (gimple_code (stmt))
2442 case GIMPLE_OMP_FOR:
2443 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2444 return true;
2445 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2447 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2449 error_at (gimple_location (stmt),
2450 "distribute construct must be closely nested inside "
2451 "teams construct");
2452 return false;
2454 return true;
2456 /* FALLTHRU */
2457 case GIMPLE_CALL:
2458 if (is_gimple_call (stmt)
2459 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2460 == BUILT_IN_GOMP_CANCEL
2461 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2462 == BUILT_IN_GOMP_CANCELLATION_POINT))
2464 const char *bad = NULL;
2465 const char *kind = NULL;
2466 if (ctx == NULL)
2468 error_at (gimple_location (stmt), "orphaned %qs construct",
2469 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2470 == BUILT_IN_GOMP_CANCEL
2471 ? "#pragma omp cancel"
2472 : "#pragma omp cancellation point");
2473 return false;
2475 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2476 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2477 : 0)
2479 case 1:
2480 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2481 bad = "#pragma omp parallel";
2482 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2483 == BUILT_IN_GOMP_CANCEL
2484 && !integer_zerop (gimple_call_arg (stmt, 1)))
2485 ctx->cancellable = true;
2486 kind = "parallel";
2487 break;
2488 case 2:
2489 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2490 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2491 bad = "#pragma omp for";
2492 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2493 == BUILT_IN_GOMP_CANCEL
2494 && !integer_zerop (gimple_call_arg (stmt, 1)))
2496 ctx->cancellable = true;
2497 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2498 OMP_CLAUSE_NOWAIT))
2499 warning_at (gimple_location (stmt), 0,
2500 "%<#pragma omp cancel for%> inside "
2501 "%<nowait%> for construct");
2502 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2503 OMP_CLAUSE_ORDERED))
2504 warning_at (gimple_location (stmt), 0,
2505 "%<#pragma omp cancel for%> inside "
2506 "%<ordered%> for construct");
2508 kind = "for";
2509 break;
2510 case 4:
2511 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2512 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2513 bad = "#pragma omp sections";
2514 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2515 == BUILT_IN_GOMP_CANCEL
2516 && !integer_zerop (gimple_call_arg (stmt, 1)))
2518 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2520 ctx->cancellable = true;
2521 if (find_omp_clause (gimple_omp_sections_clauses
2522 (ctx->stmt),
2523 OMP_CLAUSE_NOWAIT))
2524 warning_at (gimple_location (stmt), 0,
2525 "%<#pragma omp cancel sections%> inside "
2526 "%<nowait%> sections construct");
2528 else
2530 gcc_assert (ctx->outer
2531 && gimple_code (ctx->outer->stmt)
2532 == GIMPLE_OMP_SECTIONS);
2533 ctx->outer->cancellable = true;
2534 if (find_omp_clause (gimple_omp_sections_clauses
2535 (ctx->outer->stmt),
2536 OMP_CLAUSE_NOWAIT))
2537 warning_at (gimple_location (stmt), 0,
2538 "%<#pragma omp cancel sections%> inside "
2539 "%<nowait%> sections construct");
2542 kind = "sections";
2543 break;
2544 case 8:
2545 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2546 bad = "#pragma omp task";
2547 else
2548 ctx->cancellable = true;
2549 kind = "taskgroup";
2550 break;
2551 default:
2552 error_at (gimple_location (stmt), "invalid arguments");
2553 return false;
2555 if (bad)
2557 error_at (gimple_location (stmt),
2558 "%<%s %s%> construct not closely nested inside of %qs",
2559 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2560 == BUILT_IN_GOMP_CANCEL
2561 ? "#pragma omp cancel"
2562 : "#pragma omp cancellation point", kind, bad);
2563 return false;
2566 /* FALLTHRU */
2567 case GIMPLE_OMP_SECTIONS:
2568 case GIMPLE_OMP_SINGLE:
2569 for (; ctx != NULL; ctx = ctx->outer)
2570 switch (gimple_code (ctx->stmt))
2572 case GIMPLE_OMP_FOR:
2573 case GIMPLE_OMP_SECTIONS:
2574 case GIMPLE_OMP_SINGLE:
2575 case GIMPLE_OMP_ORDERED:
2576 case GIMPLE_OMP_MASTER:
2577 case GIMPLE_OMP_TASK:
2578 case GIMPLE_OMP_CRITICAL:
2579 if (is_gimple_call (stmt))
2581 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2582 != BUILT_IN_GOMP_BARRIER)
2583 return true;
2584 error_at (gimple_location (stmt),
2585 "barrier region may not be closely nested inside "
2586 "of work-sharing, critical, ordered, master or "
2587 "explicit task region");
2588 return false;
2590 error_at (gimple_location (stmt),
2591 "work-sharing region may not be closely nested inside "
2592 "of work-sharing, critical, ordered, master or explicit "
2593 "task region");
2594 return false;
2595 case GIMPLE_OMP_PARALLEL:
2596 return true;
2597 default:
2598 break;
2600 break;
2601 case GIMPLE_OMP_MASTER:
2602 for (; ctx != NULL; ctx = ctx->outer)
2603 switch (gimple_code (ctx->stmt))
2605 case GIMPLE_OMP_FOR:
2606 case GIMPLE_OMP_SECTIONS:
2607 case GIMPLE_OMP_SINGLE:
2608 case GIMPLE_OMP_TASK:
2609 error_at (gimple_location (stmt),
2610 "master region may not be closely nested inside "
2611 "of work-sharing or explicit task region");
2612 return false;
2613 case GIMPLE_OMP_PARALLEL:
2614 return true;
2615 default:
2616 break;
2618 break;
2619 case GIMPLE_OMP_ORDERED:
2620 for (; ctx != NULL; ctx = ctx->outer)
2621 switch (gimple_code (ctx->stmt))
2623 case GIMPLE_OMP_CRITICAL:
2624 case GIMPLE_OMP_TASK:
2625 error_at (gimple_location (stmt),
2626 "ordered region may not be closely nested inside "
2627 "of critical or explicit task region");
2628 return false;
2629 case GIMPLE_OMP_FOR:
2630 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2631 OMP_CLAUSE_ORDERED) == NULL)
2633 error_at (gimple_location (stmt),
2634 "ordered region must be closely nested inside "
2635 "a loop region with an ordered clause");
2636 return false;
2638 return true;
2639 case GIMPLE_OMP_PARALLEL:
2640 error_at (gimple_location (stmt),
2641 "ordered region must be closely nested inside "
2642 "a loop region with an ordered clause");
2643 return false;
2644 default:
2645 break;
2647 break;
2648 case GIMPLE_OMP_CRITICAL:
2649 for (; ctx != NULL; ctx = ctx->outer)
2650 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2651 && (gimple_omp_critical_name (stmt)
2652 == gimple_omp_critical_name (ctx->stmt)))
2654 error_at (gimple_location (stmt),
2655 "critical region may not be nested inside a critical "
2656 "region with the same name");
2657 return false;
2659 break;
2660 case GIMPLE_OMP_TEAMS:
2661 if (ctx == NULL
2662 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2663 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2665 error_at (gimple_location (stmt),
2666 "teams construct not closely nested inside of target "
2667 "region");
2668 return false;
2670 break;
2671 case GIMPLE_OMP_TARGET:
2672 for (; ctx != NULL; ctx = ctx->outer)
2673 if (is_targetreg_ctx (ctx))
2675 const char *name;
2676 switch (gimple_omp_target_kind (stmt))
2678 case GF_OMP_TARGET_KIND_REGION: name = "target"; break;
2679 case GF_OMP_TARGET_KIND_DATA: name = "target data"; break;
2680 case GF_OMP_TARGET_KIND_UPDATE: name = "target update"; break;
2681 default: gcc_unreachable ();
2683 warning_at (gimple_location (stmt), 0,
2684 "%s construct inside of target region", name);
2686 break;
2687 default:
2688 break;
2690 return true;
2694 /* Helper function scan_omp.
2696 Callback for walk_tree or operators in walk_gimple_stmt used to
2697 scan for OpenMP directives in TP. */
2699 static tree
2700 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2702 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2703 omp_context *ctx = (omp_context *) wi->info;
2704 tree t = *tp;
2706 switch (TREE_CODE (t))
2708 case VAR_DECL:
2709 case PARM_DECL:
2710 case LABEL_DECL:
2711 case RESULT_DECL:
2712 if (ctx)
2713 *tp = remap_decl (t, &ctx->cb);
2714 break;
2716 default:
2717 if (ctx && TYPE_P (t))
2718 *tp = remap_type (t, &ctx->cb);
2719 else if (!DECL_P (t))
2721 *walk_subtrees = 1;
2722 if (ctx)
2724 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2725 if (tem != TREE_TYPE (t))
2727 if (TREE_CODE (t) == INTEGER_CST)
2728 *tp = wide_int_to_tree (tem, t);
2729 else
2730 TREE_TYPE (t) = tem;
2734 break;
2737 return NULL_TREE;
2740 /* Return true if FNDECL is a setjmp or a longjmp. */
2742 static bool
2743 setjmp_or_longjmp_p (const_tree fndecl)
2745 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2746 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2747 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2748 return true;
2750 tree declname = DECL_NAME (fndecl);
2751 if (!declname)
2752 return false;
2753 const char *name = IDENTIFIER_POINTER (declname);
2754 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2758 /* Helper function for scan_omp.
2760 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2761 the current statement in GSI. */
2763 static tree
2764 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2765 struct walk_stmt_info *wi)
2767 gimple stmt = gsi_stmt (*gsi);
2768 omp_context *ctx = (omp_context *) wi->info;
2770 if (gimple_has_location (stmt))
2771 input_location = gimple_location (stmt);
2773 /* Check the OpenMP nesting restrictions. */
2774 bool remove = false;
2775 if (is_gimple_omp (stmt))
2776 remove = !check_omp_nesting_restrictions (stmt, ctx);
2777 else if (is_gimple_call (stmt))
2779 tree fndecl = gimple_call_fndecl (stmt);
2780 if (fndecl)
2782 if (setjmp_or_longjmp_p (fndecl)
2783 && ctx
2784 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2785 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2787 remove = true;
2788 error_at (gimple_location (stmt),
2789 "setjmp/longjmp inside simd construct");
2791 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2792 switch (DECL_FUNCTION_CODE (fndecl))
2794 case BUILT_IN_GOMP_BARRIER:
2795 case BUILT_IN_GOMP_CANCEL:
2796 case BUILT_IN_GOMP_CANCELLATION_POINT:
2797 case BUILT_IN_GOMP_TASKYIELD:
2798 case BUILT_IN_GOMP_TASKWAIT:
2799 case BUILT_IN_GOMP_TASKGROUP_START:
2800 case BUILT_IN_GOMP_TASKGROUP_END:
2801 remove = !check_omp_nesting_restrictions (stmt, ctx);
2802 break;
2803 default:
2804 break;
2808 if (remove)
2810 stmt = gimple_build_nop ();
2811 gsi_replace (gsi, stmt, false);
2814 *handled_ops_p = true;
2816 switch (gimple_code (stmt))
2818 case GIMPLE_OMP_PARALLEL:
2819 taskreg_nesting_level++;
2820 scan_omp_parallel (gsi, ctx);
2821 taskreg_nesting_level--;
2822 break;
2824 case GIMPLE_OMP_TASK:
2825 taskreg_nesting_level++;
2826 scan_omp_task (gsi, ctx);
2827 taskreg_nesting_level--;
2828 break;
2830 case GIMPLE_OMP_FOR:
2831 scan_omp_for (stmt, ctx);
2832 break;
2834 case GIMPLE_OMP_SECTIONS:
2835 scan_omp_sections (stmt, ctx);
2836 break;
2838 case GIMPLE_OMP_SINGLE:
2839 scan_omp_single (stmt, ctx);
2840 break;
2842 case GIMPLE_OMP_SECTION:
2843 case GIMPLE_OMP_MASTER:
2844 case GIMPLE_OMP_TASKGROUP:
2845 case GIMPLE_OMP_ORDERED:
2846 case GIMPLE_OMP_CRITICAL:
2847 ctx = new_omp_context (stmt, ctx);
2848 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2849 break;
2851 case GIMPLE_OMP_TARGET:
2852 scan_omp_target (stmt, ctx);
2853 break;
2855 case GIMPLE_OMP_TEAMS:
2856 scan_omp_teams (stmt, ctx);
2857 break;
2859 case GIMPLE_BIND:
2861 tree var;
2863 *handled_ops_p = false;
2864 if (ctx)
2865 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2866 insert_decl_map (&ctx->cb, var, var);
2868 break;
2869 default:
2870 *handled_ops_p = false;
2871 break;
2874 return NULL_TREE;
2878 /* Scan all the statements starting at the current statement. CTX
2879 contains context information about the OpenMP directives and
2880 clauses found during the scan. */
2882 static void
2883 scan_omp (gimple_seq *body_p, omp_context *ctx)
2885 location_t saved_location;
2886 struct walk_stmt_info wi;
2888 memset (&wi, 0, sizeof (wi));
2889 wi.info = ctx;
2890 wi.want_locations = true;
2892 saved_location = input_location;
2893 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2894 input_location = saved_location;
2897 /* Re-gimplification and code generation routines. */
2899 /* Build a call to GOMP_barrier. */
2901 static gimple
2902 build_omp_barrier (tree lhs)
2904 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2905 : BUILT_IN_GOMP_BARRIER);
2906 gimple g = gimple_build_call (fndecl, 0);
2907 if (lhs)
2908 gimple_call_set_lhs (g, lhs);
2909 return g;
2912 /* If a context was created for STMT when it was scanned, return it. */
2914 static omp_context *
2915 maybe_lookup_ctx (gimple stmt)
2917 splay_tree_node n;
2918 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2919 return n ? (omp_context *) n->value : NULL;
2923 /* Find the mapping for DECL in CTX or the immediately enclosing
2924 context that has a mapping for DECL.
2926 If CTX is a nested parallel directive, we may have to use the decl
2927 mappings created in CTX's parent context. Suppose that we have the
2928 following parallel nesting (variable UIDs showed for clarity):
2930 iD.1562 = 0;
2931 #omp parallel shared(iD.1562) -> outer parallel
2932 iD.1562 = iD.1562 + 1;
2934 #omp parallel shared (iD.1562) -> inner parallel
2935 iD.1562 = iD.1562 - 1;
2937 Each parallel structure will create a distinct .omp_data_s structure
2938 for copying iD.1562 in/out of the directive:
2940 outer parallel .omp_data_s.1.i -> iD.1562
2941 inner parallel .omp_data_s.2.i -> iD.1562
2943 A shared variable mapping will produce a copy-out operation before
2944 the parallel directive and a copy-in operation after it. So, in
2945 this case we would have:
2947 iD.1562 = 0;
2948 .omp_data_o.1.i = iD.1562;
2949 #omp parallel shared(iD.1562) -> outer parallel
2950 .omp_data_i.1 = &.omp_data_o.1
2951 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2953 .omp_data_o.2.i = iD.1562; -> **
2954 #omp parallel shared(iD.1562) -> inner parallel
2955 .omp_data_i.2 = &.omp_data_o.2
2956 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2959 ** This is a problem. The symbol iD.1562 cannot be referenced
2960 inside the body of the outer parallel region. But since we are
2961 emitting this copy operation while expanding the inner parallel
2962 directive, we need to access the CTX structure of the outer
2963 parallel directive to get the correct mapping:
2965 .omp_data_o.2.i = .omp_data_i.1->i
2967 Since there may be other workshare or parallel directives enclosing
2968 the parallel directive, it may be necessary to walk up the context
2969 parent chain. This is not a problem in general because nested
2970 parallelism happens only rarely. */
2972 static tree
2973 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2975 tree t;
2976 omp_context *up;
2978 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2979 t = maybe_lookup_decl (decl, up);
2981 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2983 return t ? t : decl;
2987 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2988 in outer contexts. */
2990 static tree
2991 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2993 tree t = NULL;
2994 omp_context *up;
2996 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2997 t = maybe_lookup_decl (decl, up);
2999 return t ? t : decl;
3003 /* Construct the initialization value for reduction CLAUSE. */
3005 tree
3006 omp_reduction_init (tree clause, tree type)
3008 location_t loc = OMP_CLAUSE_LOCATION (clause);
3009 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3011 case PLUS_EXPR:
3012 case MINUS_EXPR:
3013 case BIT_IOR_EXPR:
3014 case BIT_XOR_EXPR:
3015 case TRUTH_OR_EXPR:
3016 case TRUTH_ORIF_EXPR:
3017 case TRUTH_XOR_EXPR:
3018 case NE_EXPR:
3019 return build_zero_cst (type);
3021 case MULT_EXPR:
3022 case TRUTH_AND_EXPR:
3023 case TRUTH_ANDIF_EXPR:
3024 case EQ_EXPR:
3025 return fold_convert_loc (loc, type, integer_one_node);
3027 case BIT_AND_EXPR:
3028 return fold_convert_loc (loc, type, integer_minus_one_node);
3030 case MAX_EXPR:
3031 if (SCALAR_FLOAT_TYPE_P (type))
3033 REAL_VALUE_TYPE max, min;
3034 if (HONOR_INFINITIES (TYPE_MODE (type)))
3036 real_inf (&max);
3037 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3039 else
3040 real_maxval (&min, 1, TYPE_MODE (type));
3041 return build_real (type, min);
3043 else
3045 gcc_assert (INTEGRAL_TYPE_P (type));
3046 return TYPE_MIN_VALUE (type);
3049 case MIN_EXPR:
3050 if (SCALAR_FLOAT_TYPE_P (type))
3052 REAL_VALUE_TYPE max;
3053 if (HONOR_INFINITIES (TYPE_MODE (type)))
3054 real_inf (&max);
3055 else
3056 real_maxval (&max, 0, TYPE_MODE (type));
3057 return build_real (type, max);
3059 else
3061 gcc_assert (INTEGRAL_TYPE_P (type));
3062 return TYPE_MAX_VALUE (type);
3065 default:
3066 gcc_unreachable ();
3070 /* Return alignment to be assumed for var in CLAUSE, which should be
3071 OMP_CLAUSE_ALIGNED. */
3073 static tree
3074 omp_clause_aligned_alignment (tree clause)
3076 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3077 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3079 /* Otherwise return implementation defined alignment. */
3080 unsigned int al = 1;
3081 machine_mode mode, vmode;
3082 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3083 if (vs)
3084 vs = 1 << floor_log2 (vs);
3085 static enum mode_class classes[]
3086 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3087 for (int i = 0; i < 4; i += 2)
3088 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3089 mode != VOIDmode;
3090 mode = GET_MODE_WIDER_MODE (mode))
3092 vmode = targetm.vectorize.preferred_simd_mode (mode);
3093 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3094 continue;
3095 while (vs
3096 && GET_MODE_SIZE (vmode) < vs
3097 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3098 vmode = GET_MODE_2XWIDER_MODE (vmode);
3100 tree type = lang_hooks.types.type_for_mode (mode, 1);
3101 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3102 continue;
3103 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3104 / GET_MODE_SIZE (mode));
3105 if (TYPE_MODE (type) != vmode)
3106 continue;
3107 if (TYPE_ALIGN_UNIT (type) > al)
3108 al = TYPE_ALIGN_UNIT (type);
3110 return build_int_cst (integer_type_node, al);
3113 /* Return maximum possible vectorization factor for the target. */
3115 static int
3116 omp_max_vf (void)
3118 if (!optimize
3119 || optimize_debug
3120 || !flag_tree_loop_optimize
3121 || (!flag_tree_loop_vectorize
3122 && (global_options_set.x_flag_tree_loop_vectorize
3123 || global_options_set.x_flag_tree_vectorize)))
3124 return 1;
3126 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3127 if (vs)
3129 vs = 1 << floor_log2 (vs);
3130 return vs;
3132 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3133 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3134 return GET_MODE_NUNITS (vqimode);
3135 return 1;
3138 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3139 privatization. */
3141 static bool
3142 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3143 tree &idx, tree &lane, tree &ivar, tree &lvar)
3145 if (max_vf == 0)
3147 max_vf = omp_max_vf ();
3148 if (max_vf > 1)
3150 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3151 OMP_CLAUSE_SAFELEN);
3152 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3153 max_vf = 1;
3154 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3155 max_vf) == -1)
3156 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3158 if (max_vf > 1)
3160 idx = create_tmp_var (unsigned_type_node, NULL);
3161 lane = create_tmp_var (unsigned_type_node, NULL);
3164 if (max_vf == 1)
3165 return false;
3167 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3168 tree avar = create_tmp_var_raw (atype, NULL);
3169 if (TREE_ADDRESSABLE (new_var))
3170 TREE_ADDRESSABLE (avar) = 1;
3171 DECL_ATTRIBUTES (avar)
3172 = tree_cons (get_identifier ("omp simd array"), NULL,
3173 DECL_ATTRIBUTES (avar));
3174 gimple_add_tmp_var (avar);
3175 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3176 NULL_TREE, NULL_TREE);
3177 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3178 NULL_TREE, NULL_TREE);
3179 if (DECL_P (new_var))
3181 SET_DECL_VALUE_EXPR (new_var, lvar);
3182 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3184 return true;
3187 /* Helper function of lower_rec_input_clauses. For a reference
3188 in simd reduction, add an underlying variable it will reference. */
3190 static void
3191 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3193 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3194 if (TREE_CONSTANT (z))
3196 const char *name = NULL;
3197 if (DECL_NAME (new_vard))
3198 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3200 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3201 gimple_add_tmp_var (z);
3202 TREE_ADDRESSABLE (z) = 1;
3203 z = build_fold_addr_expr_loc (loc, z);
3204 gimplify_assign (new_vard, z, ilist);
3208 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3209 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3210 private variables. Initialization statements go in ILIST, while calls
3211 to destructors go in DLIST. */
3213 static void
3214 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3215 omp_context *ctx, struct omp_for_data *fd)
3217 tree c, dtor, copyin_seq, x, ptr;
3218 bool copyin_by_ref = false;
3219 bool lastprivate_firstprivate = false;
3220 bool reduction_omp_orig_ref = false;
3221 int pass;
3222 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3223 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3224 int max_vf = 0;
3225 tree lane = NULL_TREE, idx = NULL_TREE;
3226 tree ivar = NULL_TREE, lvar = NULL_TREE;
3227 gimple_seq llist[2] = { NULL, NULL };
3229 copyin_seq = NULL;
3231 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3232 with data sharing clauses referencing variable sized vars. That
3233 is unnecessarily hard to support and very unlikely to result in
3234 vectorized code anyway. */
3235 if (is_simd)
3236 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3237 switch (OMP_CLAUSE_CODE (c))
3239 case OMP_CLAUSE_LINEAR:
3240 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3241 max_vf = 1;
3242 /* FALLTHRU */
3243 case OMP_CLAUSE_REDUCTION:
3244 case OMP_CLAUSE_PRIVATE:
3245 case OMP_CLAUSE_FIRSTPRIVATE:
3246 case OMP_CLAUSE_LASTPRIVATE:
3247 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3248 max_vf = 1;
3249 break;
3250 default:
3251 continue;
3254 /* Do all the fixed sized types in the first pass, and the variable sized
3255 types in the second pass. This makes sure that the scalar arguments to
3256 the variable sized types are processed before we use them in the
3257 variable sized operations. */
3258 for (pass = 0; pass < 2; ++pass)
3260 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3262 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3263 tree var, new_var;
3264 bool by_ref;
3265 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3267 switch (c_kind)
3269 case OMP_CLAUSE_PRIVATE:
3270 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3271 continue;
3272 break;
3273 case OMP_CLAUSE_SHARED:
3274 /* Ignore shared directives in teams construct. */
3275 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3276 continue;
3277 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3279 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3280 continue;
3282 case OMP_CLAUSE_FIRSTPRIVATE:
3283 case OMP_CLAUSE_COPYIN:
3284 case OMP_CLAUSE_LINEAR:
3285 break;
3286 case OMP_CLAUSE_REDUCTION:
3287 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3288 reduction_omp_orig_ref = true;
3289 break;
3290 case OMP_CLAUSE__LOOPTEMP_:
3291 /* Handle _looptemp_ clauses only on parallel. */
3292 if (fd)
3293 continue;
3294 break;
3295 case OMP_CLAUSE_LASTPRIVATE:
3296 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3298 lastprivate_firstprivate = true;
3299 if (pass != 0)
3300 continue;
3302 /* Even without corresponding firstprivate, if
3303 decl is Fortran allocatable, it needs outer var
3304 reference. */
3305 else if (pass == 0
3306 && lang_hooks.decls.omp_private_outer_ref
3307 (OMP_CLAUSE_DECL (c)))
3308 lastprivate_firstprivate = true;
3309 break;
3310 case OMP_CLAUSE_ALIGNED:
3311 if (pass == 0)
3312 continue;
3313 var = OMP_CLAUSE_DECL (c);
3314 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3315 && !is_global_var (var))
3317 new_var = maybe_lookup_decl (var, ctx);
3318 if (new_var == NULL_TREE)
3319 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3320 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3321 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3322 omp_clause_aligned_alignment (c));
3323 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3324 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3325 gimplify_and_add (x, ilist);
3327 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3328 && is_global_var (var))
3330 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3331 new_var = lookup_decl (var, ctx);
3332 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3333 t = build_fold_addr_expr_loc (clause_loc, t);
3334 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3335 t = build_call_expr_loc (clause_loc, t2, 2, t,
3336 omp_clause_aligned_alignment (c));
3337 t = fold_convert_loc (clause_loc, ptype, t);
3338 x = create_tmp_var (ptype, NULL);
3339 t = build2 (MODIFY_EXPR, ptype, x, t);
3340 gimplify_and_add (t, ilist);
3341 t = build_simple_mem_ref_loc (clause_loc, x);
3342 SET_DECL_VALUE_EXPR (new_var, t);
3343 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3345 continue;
3346 default:
3347 continue;
3350 new_var = var = OMP_CLAUSE_DECL (c);
3351 if (c_kind != OMP_CLAUSE_COPYIN)
3352 new_var = lookup_decl (var, ctx);
3354 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3356 if (pass != 0)
3357 continue;
3359 else if (is_variable_sized (var))
3361 /* For variable sized types, we need to allocate the
3362 actual storage here. Call alloca and store the
3363 result in the pointer decl that we created elsewhere. */
3364 if (pass == 0)
3365 continue;
3367 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3369 gimple stmt;
3370 tree tmp, atmp;
3372 ptr = DECL_VALUE_EXPR (new_var);
3373 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3374 ptr = TREE_OPERAND (ptr, 0);
3375 gcc_assert (DECL_P (ptr));
3376 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3378 /* void *tmp = __builtin_alloca */
3379 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3380 stmt = gimple_build_call (atmp, 1, x);
3381 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3382 gimple_add_tmp_var (tmp);
3383 gimple_call_set_lhs (stmt, tmp);
3385 gimple_seq_add_stmt (ilist, stmt);
3387 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3388 gimplify_assign (ptr, x, ilist);
3391 else if (is_reference (var))
3393 /* For references that are being privatized for Fortran,
3394 allocate new backing storage for the new pointer
3395 variable. This allows us to avoid changing all the
3396 code that expects a pointer to something that expects
3397 a direct variable. */
3398 if (pass == 0)
3399 continue;
3401 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3402 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3404 x = build_receiver_ref (var, false, ctx);
3405 x = build_fold_addr_expr_loc (clause_loc, x);
3407 else if (TREE_CONSTANT (x))
3409 /* For reduction in SIMD loop, defer adding the
3410 initialization of the reference, because if we decide
3411 to use SIMD array for it, the initilization could cause
3412 expansion ICE. */
3413 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3414 x = NULL_TREE;
3415 else
3417 const char *name = NULL;
3418 if (DECL_NAME (var))
3419 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3421 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3422 name);
3423 gimple_add_tmp_var (x);
3424 TREE_ADDRESSABLE (x) = 1;
3425 x = build_fold_addr_expr_loc (clause_loc, x);
3428 else
3430 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3431 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3434 if (x)
3436 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3437 gimplify_assign (new_var, x, ilist);
3440 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3442 else if (c_kind == OMP_CLAUSE_REDUCTION
3443 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3445 if (pass == 0)
3446 continue;
3448 else if (pass != 0)
3449 continue;
3451 switch (OMP_CLAUSE_CODE (c))
3453 case OMP_CLAUSE_SHARED:
3454 /* Ignore shared directives in teams construct. */
3455 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3456 continue;
3457 /* Shared global vars are just accessed directly. */
3458 if (is_global_var (new_var))
3459 break;
3460 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3461 needs to be delayed until after fixup_child_record_type so
3462 that we get the correct type during the dereference. */
3463 by_ref = use_pointer_for_field (var, ctx);
3464 x = build_receiver_ref (var, by_ref, ctx);
3465 SET_DECL_VALUE_EXPR (new_var, x);
3466 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3468 /* ??? If VAR is not passed by reference, and the variable
3469 hasn't been initialized yet, then we'll get a warning for
3470 the store into the omp_data_s structure. Ideally, we'd be
3471 able to notice this and not store anything at all, but
3472 we're generating code too early. Suppress the warning. */
3473 if (!by_ref)
3474 TREE_NO_WARNING (var) = 1;
3475 break;
3477 case OMP_CLAUSE_LASTPRIVATE:
3478 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3479 break;
3480 /* FALLTHRU */
3482 case OMP_CLAUSE_PRIVATE:
3483 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3484 x = build_outer_var_ref (var, ctx);
3485 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3487 if (is_task_ctx (ctx))
3488 x = build_receiver_ref (var, false, ctx);
3489 else
3490 x = build_outer_var_ref (var, ctx);
3492 else
3493 x = NULL;
3494 do_private:
3495 tree nx;
3496 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3497 if (is_simd)
3499 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3500 if ((TREE_ADDRESSABLE (new_var) || nx || y
3501 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3502 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3503 idx, lane, ivar, lvar))
3505 if (nx)
3506 x = lang_hooks.decls.omp_clause_default_ctor
3507 (c, unshare_expr (ivar), x);
3508 if (nx && x)
3509 gimplify_and_add (x, &llist[0]);
3510 if (y)
3512 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3513 if (y)
3515 gimple_seq tseq = NULL;
3517 dtor = y;
3518 gimplify_stmt (&dtor, &tseq);
3519 gimple_seq_add_seq (&llist[1], tseq);
3522 break;
3525 if (nx)
3526 gimplify_and_add (nx, ilist);
3527 /* FALLTHRU */
3529 do_dtor:
3530 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3531 if (x)
3533 gimple_seq tseq = NULL;
3535 dtor = x;
3536 gimplify_stmt (&dtor, &tseq);
3537 gimple_seq_add_seq (dlist, tseq);
3539 break;
3541 case OMP_CLAUSE_LINEAR:
3542 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3543 goto do_firstprivate;
3544 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3545 x = NULL;
3546 else
3547 x = build_outer_var_ref (var, ctx);
3548 goto do_private;
3550 case OMP_CLAUSE_FIRSTPRIVATE:
3551 if (is_task_ctx (ctx))
3553 if (is_reference (var) || is_variable_sized (var))
3554 goto do_dtor;
3555 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3556 ctx))
3557 || use_pointer_for_field (var, NULL))
3559 x = build_receiver_ref (var, false, ctx);
3560 SET_DECL_VALUE_EXPR (new_var, x);
3561 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3562 goto do_dtor;
3565 do_firstprivate:
3566 x = build_outer_var_ref (var, ctx);
3567 if (is_simd)
3569 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3570 && gimple_omp_for_combined_into_p (ctx->stmt))
3572 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3573 tree stept = TREE_TYPE (t);
3574 tree ct = find_omp_clause (clauses,
3575 OMP_CLAUSE__LOOPTEMP_);
3576 gcc_assert (ct);
3577 tree l = OMP_CLAUSE_DECL (ct);
3578 tree n1 = fd->loop.n1;
3579 tree step = fd->loop.step;
3580 tree itype = TREE_TYPE (l);
3581 if (POINTER_TYPE_P (itype))
3582 itype = signed_type_for (itype);
3583 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3584 if (TYPE_UNSIGNED (itype)
3585 && fd->loop.cond_code == GT_EXPR)
3586 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3587 fold_build1 (NEGATE_EXPR, itype, l),
3588 fold_build1 (NEGATE_EXPR,
3589 itype, step));
3590 else
3591 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3592 t = fold_build2 (MULT_EXPR, stept,
3593 fold_convert (stept, l), t);
3595 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3597 x = lang_hooks.decls.omp_clause_linear_ctor
3598 (c, new_var, x, t);
3599 gimplify_and_add (x, ilist);
3600 goto do_dtor;
3603 if (POINTER_TYPE_P (TREE_TYPE (x)))
3604 x = fold_build2 (POINTER_PLUS_EXPR,
3605 TREE_TYPE (x), x, t);
3606 else
3607 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3610 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3611 || TREE_ADDRESSABLE (new_var))
3612 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3613 idx, lane, ivar, lvar))
3615 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3617 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3618 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3619 gimplify_and_add (x, ilist);
3620 gimple_stmt_iterator gsi
3621 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3622 gimple g
3623 = gimple_build_assign (unshare_expr (lvar), iv);
3624 gsi_insert_before_without_update (&gsi, g,
3625 GSI_SAME_STMT);
3626 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3627 enum tree_code code = PLUS_EXPR;
3628 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3629 code = POINTER_PLUS_EXPR;
3630 g = gimple_build_assign_with_ops (code, iv, iv, t);
3631 gsi_insert_before_without_update (&gsi, g,
3632 GSI_SAME_STMT);
3633 break;
3635 x = lang_hooks.decls.omp_clause_copy_ctor
3636 (c, unshare_expr (ivar), x);
3637 gimplify_and_add (x, &llist[0]);
3638 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3639 if (x)
3641 gimple_seq tseq = NULL;
3643 dtor = x;
3644 gimplify_stmt (&dtor, &tseq);
3645 gimple_seq_add_seq (&llist[1], tseq);
3647 break;
3650 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3651 gimplify_and_add (x, ilist);
3652 goto do_dtor;
3654 case OMP_CLAUSE__LOOPTEMP_:
3655 gcc_assert (is_parallel_ctx (ctx));
3656 x = build_outer_var_ref (var, ctx);
3657 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3658 gimplify_and_add (x, ilist);
3659 break;
3661 case OMP_CLAUSE_COPYIN:
3662 by_ref = use_pointer_for_field (var, NULL);
3663 x = build_receiver_ref (var, by_ref, ctx);
3664 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3665 append_to_statement_list (x, &copyin_seq);
3666 copyin_by_ref |= by_ref;
3667 break;
3669 case OMP_CLAUSE_REDUCTION:
3670 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3672 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3673 gimple tseq;
3674 x = build_outer_var_ref (var, ctx);
3676 if (is_reference (var)
3677 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3678 TREE_TYPE (x)))
3679 x = build_fold_addr_expr_loc (clause_loc, x);
3680 SET_DECL_VALUE_EXPR (placeholder, x);
3681 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3682 tree new_vard = new_var;
3683 if (is_reference (var))
3685 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3686 new_vard = TREE_OPERAND (new_var, 0);
3687 gcc_assert (DECL_P (new_vard));
3689 if (is_simd
3690 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3691 idx, lane, ivar, lvar))
3693 if (new_vard == new_var)
3695 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3696 SET_DECL_VALUE_EXPR (new_var, ivar);
3698 else
3700 SET_DECL_VALUE_EXPR (new_vard,
3701 build_fold_addr_expr (ivar));
3702 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3704 x = lang_hooks.decls.omp_clause_default_ctor
3705 (c, unshare_expr (ivar),
3706 build_outer_var_ref (var, ctx));
3707 if (x)
3708 gimplify_and_add (x, &llist[0]);
3709 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3711 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3712 lower_omp (&tseq, ctx);
3713 gimple_seq_add_seq (&llist[0], tseq);
3715 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3716 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3717 lower_omp (&tseq, ctx);
3718 gimple_seq_add_seq (&llist[1], tseq);
3719 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3720 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3721 if (new_vard == new_var)
3722 SET_DECL_VALUE_EXPR (new_var, lvar);
3723 else
3724 SET_DECL_VALUE_EXPR (new_vard,
3725 build_fold_addr_expr (lvar));
3726 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3727 if (x)
3729 tseq = NULL;
3730 dtor = x;
3731 gimplify_stmt (&dtor, &tseq);
3732 gimple_seq_add_seq (&llist[1], tseq);
3734 break;
3736 /* If this is a reference to constant size reduction var
3737 with placeholder, we haven't emitted the initializer
3738 for it because it is undesirable if SIMD arrays are used.
3739 But if they aren't used, we need to emit the deferred
3740 initialization now. */
3741 else if (is_reference (var) && is_simd)
3742 handle_simd_reference (clause_loc, new_vard, ilist);
3743 x = lang_hooks.decls.omp_clause_default_ctor
3744 (c, unshare_expr (new_var),
3745 build_outer_var_ref (var, ctx));
3746 if (x)
3747 gimplify_and_add (x, ilist);
3748 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3750 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3751 lower_omp (&tseq, ctx);
3752 gimple_seq_add_seq (ilist, tseq);
3754 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3755 if (is_simd)
3757 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3758 lower_omp (&tseq, ctx);
3759 gimple_seq_add_seq (dlist, tseq);
3760 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3762 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3763 goto do_dtor;
3765 else
3767 x = omp_reduction_init (c, TREE_TYPE (new_var));
3768 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3769 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3771 /* reduction(-:var) sums up the partial results, so it
3772 acts identically to reduction(+:var). */
3773 if (code == MINUS_EXPR)
3774 code = PLUS_EXPR;
3776 tree new_vard = new_var;
3777 if (is_simd && is_reference (var))
3779 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3780 new_vard = TREE_OPERAND (new_var, 0);
3781 gcc_assert (DECL_P (new_vard));
3783 if (is_simd
3784 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3785 idx, lane, ivar, lvar))
3787 tree ref = build_outer_var_ref (var, ctx);
3789 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3791 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3792 ref = build_outer_var_ref (var, ctx);
3793 gimplify_assign (ref, x, &llist[1]);
3795 if (new_vard != new_var)
3797 SET_DECL_VALUE_EXPR (new_vard,
3798 build_fold_addr_expr (lvar));
3799 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3802 else
3804 if (is_reference (var) && is_simd)
3805 handle_simd_reference (clause_loc, new_vard, ilist);
3806 gimplify_assign (new_var, x, ilist);
3807 if (is_simd)
3809 tree ref = build_outer_var_ref (var, ctx);
3811 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3812 ref = build_outer_var_ref (var, ctx);
3813 gimplify_assign (ref, x, dlist);
3817 break;
3819 default:
3820 gcc_unreachable ();
3825 if (lane)
3827 tree uid = create_tmp_var (ptr_type_node, "simduid");
3828 /* Don't want uninit warnings on simduid, it is always uninitialized,
3829 but we use it not for the value, but for the DECL_UID only. */
3830 TREE_NO_WARNING (uid) = 1;
3831 gimple g
3832 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3833 gimple_call_set_lhs (g, lane);
3834 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3835 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3836 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3837 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3838 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3839 gimple_omp_for_set_clauses (ctx->stmt, c);
3840 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3841 build_int_cst (unsigned_type_node, 0),
3842 NULL_TREE);
3843 gimple_seq_add_stmt (ilist, g);
3844 for (int i = 0; i < 2; i++)
3845 if (llist[i])
3847 tree vf = create_tmp_var (unsigned_type_node, NULL);
3848 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3849 gimple_call_set_lhs (g, vf);
3850 gimple_seq *seq = i == 0 ? ilist : dlist;
3851 gimple_seq_add_stmt (seq, g);
3852 tree t = build_int_cst (unsigned_type_node, 0);
3853 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3854 gimple_seq_add_stmt (seq, g);
3855 tree body = create_artificial_label (UNKNOWN_LOCATION);
3856 tree header = create_artificial_label (UNKNOWN_LOCATION);
3857 tree end = create_artificial_label (UNKNOWN_LOCATION);
3858 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3859 gimple_seq_add_stmt (seq, gimple_build_label (body));
3860 gimple_seq_add_seq (seq, llist[i]);
3861 t = build_int_cst (unsigned_type_node, 1);
3862 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3863 gimple_seq_add_stmt (seq, g);
3864 gimple_seq_add_stmt (seq, gimple_build_label (header));
3865 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3866 gimple_seq_add_stmt (seq, g);
3867 gimple_seq_add_stmt (seq, gimple_build_label (end));
3871 /* The copyin sequence is not to be executed by the main thread, since
3872 that would result in self-copies. Perhaps not visible to scalars,
3873 but it certainly is to C++ operator=. */
3874 if (copyin_seq)
3876 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3878 x = build2 (NE_EXPR, boolean_type_node, x,
3879 build_int_cst (TREE_TYPE (x), 0));
3880 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3881 gimplify_and_add (x, ilist);
3884 /* If any copyin variable is passed by reference, we must ensure the
3885 master thread doesn't modify it before it is copied over in all
3886 threads. Similarly for variables in both firstprivate and
3887 lastprivate clauses we need to ensure the lastprivate copying
3888 happens after firstprivate copying in all threads. And similarly
3889 for UDRs if initializer expression refers to omp_orig. */
3890 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3892 /* Don't add any barrier for #pragma omp simd or
3893 #pragma omp distribute. */
3894 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3895 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3896 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3899 /* If max_vf is non-zero, then we can use only a vectorization factor
3900 up to the max_vf we chose. So stick it into the safelen clause. */
3901 if (max_vf)
3903 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3904 OMP_CLAUSE_SAFELEN);
3905 if (c == NULL_TREE
3906 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
3907 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3908 max_vf) == 1))
3910 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3911 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3912 max_vf);
3913 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3914 gimple_omp_for_set_clauses (ctx->stmt, c);
3920 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3921 both parallel and workshare constructs. PREDICATE may be NULL if it's
3922 always true. */
3924 static void
3925 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3926 omp_context *ctx)
3928 tree x, c, label = NULL, orig_clauses = clauses;
3929 bool par_clauses = false;
3930 tree simduid = NULL, lastlane = NULL;
3932 /* Early exit if there are no lastprivate or linear clauses. */
3933 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3934 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3935 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3936 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3937 break;
3938 if (clauses == NULL)
3940 /* If this was a workshare clause, see if it had been combined
3941 with its parallel. In that case, look for the clauses on the
3942 parallel statement itself. */
3943 if (is_parallel_ctx (ctx))
3944 return;
3946 ctx = ctx->outer;
3947 if (ctx == NULL || !is_parallel_ctx (ctx))
3948 return;
3950 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3951 OMP_CLAUSE_LASTPRIVATE);
3952 if (clauses == NULL)
3953 return;
3954 par_clauses = true;
3957 if (predicate)
3959 gimple stmt;
3960 tree label_true, arm1, arm2;
3962 label = create_artificial_label (UNKNOWN_LOCATION);
3963 label_true = create_artificial_label (UNKNOWN_LOCATION);
3964 arm1 = TREE_OPERAND (predicate, 0);
3965 arm2 = TREE_OPERAND (predicate, 1);
3966 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3967 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3968 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3969 label_true, label);
3970 gimple_seq_add_stmt (stmt_list, stmt);
3971 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3974 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3975 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3977 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3978 if (simduid)
3979 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3982 for (c = clauses; c ;)
3984 tree var, new_var;
3985 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3987 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3988 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3989 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3991 var = OMP_CLAUSE_DECL (c);
3992 new_var = lookup_decl (var, ctx);
3994 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3996 tree val = DECL_VALUE_EXPR (new_var);
3997 if (TREE_CODE (val) == ARRAY_REF
3998 && VAR_P (TREE_OPERAND (val, 0))
3999 && lookup_attribute ("omp simd array",
4000 DECL_ATTRIBUTES (TREE_OPERAND (val,
4001 0))))
4003 if (lastlane == NULL)
4005 lastlane = create_tmp_var (unsigned_type_node, NULL);
4006 gimple g
4007 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4008 2, simduid,
4009 TREE_OPERAND (val, 1));
4010 gimple_call_set_lhs (g, lastlane);
4011 gimple_seq_add_stmt (stmt_list, g);
4013 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4014 TREE_OPERAND (val, 0), lastlane,
4015 NULL_TREE, NULL_TREE);
4019 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4020 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4022 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4023 gimple_seq_add_seq (stmt_list,
4024 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4025 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4027 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4028 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4030 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4031 gimple_seq_add_seq (stmt_list,
4032 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4033 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4036 x = build_outer_var_ref (var, ctx);
4037 if (is_reference (var))
4038 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4039 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4040 gimplify_and_add (x, stmt_list);
4042 c = OMP_CLAUSE_CHAIN (c);
4043 if (c == NULL && !par_clauses)
4045 /* If this was a workshare clause, see if it had been combined
4046 with its parallel. In that case, continue looking for the
4047 clauses also on the parallel statement itself. */
4048 if (is_parallel_ctx (ctx))
4049 break;
4051 ctx = ctx->outer;
4052 if (ctx == NULL || !is_parallel_ctx (ctx))
4053 break;
4055 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4056 OMP_CLAUSE_LASTPRIVATE);
4057 par_clauses = true;
4061 if (label)
4062 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4066 /* Generate code to implement the REDUCTION clauses. */
4068 static void
4069 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4071 gimple_seq sub_seq = NULL;
4072 gimple stmt;
4073 tree x, c;
4074 int count = 0;
4076 /* SIMD reductions are handled in lower_rec_input_clauses. */
4077 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4078 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4079 return;
4081 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4082 update in that case, otherwise use a lock. */
4083 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4084 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4086 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4088 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4089 count = -1;
4090 break;
4092 count++;
4095 if (count == 0)
4096 return;
4098 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4100 tree var, ref, new_var;
4101 enum tree_code code;
4102 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4104 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4105 continue;
4107 var = OMP_CLAUSE_DECL (c);
4108 new_var = lookup_decl (var, ctx);
4109 if (is_reference (var))
4110 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4111 ref = build_outer_var_ref (var, ctx);
4112 code = OMP_CLAUSE_REDUCTION_CODE (c);
4114 /* reduction(-:var) sums up the partial results, so it acts
4115 identically to reduction(+:var). */
4116 if (code == MINUS_EXPR)
4117 code = PLUS_EXPR;
4119 if (count == 1)
4121 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4123 addr = save_expr (addr);
4124 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4125 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4126 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4127 gimplify_and_add (x, stmt_seqp);
4128 return;
4131 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4133 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4135 if (is_reference (var)
4136 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4137 TREE_TYPE (ref)))
4138 ref = build_fold_addr_expr_loc (clause_loc, ref);
4139 SET_DECL_VALUE_EXPR (placeholder, ref);
4140 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4141 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4142 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4143 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4144 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4146 else
4148 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4149 ref = build_outer_var_ref (var, ctx);
4150 gimplify_assign (ref, x, &sub_seq);
4154 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4156 gimple_seq_add_stmt (stmt_seqp, stmt);
4158 gimple_seq_add_seq (stmt_seqp, sub_seq);
4160 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4162 gimple_seq_add_stmt (stmt_seqp, stmt);
4166 /* Generate code to implement the COPYPRIVATE clauses. */
4168 static void
4169 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4170 omp_context *ctx)
4172 tree c;
4174 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4176 tree var, new_var, ref, x;
4177 bool by_ref;
4178 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4180 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4181 continue;
4183 var = OMP_CLAUSE_DECL (c);
4184 by_ref = use_pointer_for_field (var, NULL);
4186 ref = build_sender_ref (var, ctx);
4187 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4188 if (by_ref)
4190 x = build_fold_addr_expr_loc (clause_loc, new_var);
4191 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4193 gimplify_assign (ref, x, slist);
4195 ref = build_receiver_ref (var, false, ctx);
4196 if (by_ref)
4198 ref = fold_convert_loc (clause_loc,
4199 build_pointer_type (TREE_TYPE (new_var)),
4200 ref);
4201 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4203 if (is_reference (var))
4205 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4206 ref = build_simple_mem_ref_loc (clause_loc, ref);
4207 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4209 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4210 gimplify_and_add (x, rlist);
4215 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4216 and REDUCTION from the sender (aka parent) side. */
4218 static void
4219 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4220 omp_context *ctx)
4222 tree c;
4224 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4226 tree val, ref, x, var;
4227 bool by_ref, do_in = false, do_out = false;
4228 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4230 switch (OMP_CLAUSE_CODE (c))
4232 case OMP_CLAUSE_PRIVATE:
4233 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4234 break;
4235 continue;
4236 case OMP_CLAUSE_FIRSTPRIVATE:
4237 case OMP_CLAUSE_COPYIN:
4238 case OMP_CLAUSE_LASTPRIVATE:
4239 case OMP_CLAUSE_REDUCTION:
4240 case OMP_CLAUSE__LOOPTEMP_:
4241 break;
4242 default:
4243 continue;
4246 val = OMP_CLAUSE_DECL (c);
4247 var = lookup_decl_in_outer_ctx (val, ctx);
4249 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4250 && is_global_var (var))
4251 continue;
4252 if (is_variable_sized (val))
4253 continue;
4254 by_ref = use_pointer_for_field (val, NULL);
4256 switch (OMP_CLAUSE_CODE (c))
4258 case OMP_CLAUSE_PRIVATE:
4259 case OMP_CLAUSE_FIRSTPRIVATE:
4260 case OMP_CLAUSE_COPYIN:
4261 case OMP_CLAUSE__LOOPTEMP_:
4262 do_in = true;
4263 break;
4265 case OMP_CLAUSE_LASTPRIVATE:
4266 if (by_ref || is_reference (val))
4268 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4269 continue;
4270 do_in = true;
4272 else
4274 do_out = true;
4275 if (lang_hooks.decls.omp_private_outer_ref (val))
4276 do_in = true;
4278 break;
4280 case OMP_CLAUSE_REDUCTION:
4281 do_in = true;
4282 do_out = !(by_ref || is_reference (val));
4283 break;
4285 default:
4286 gcc_unreachable ();
4289 if (do_in)
4291 ref = build_sender_ref (val, ctx);
4292 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4293 gimplify_assign (ref, x, ilist);
4294 if (is_task_ctx (ctx))
4295 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4298 if (do_out)
4300 ref = build_sender_ref (val, ctx);
4301 gimplify_assign (var, ref, olist);
4306 /* Generate code to implement SHARED from the sender (aka parent)
4307 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4308 list things that got automatically shared. */
4310 static void
4311 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4313 tree var, ovar, nvar, f, x, record_type;
4315 if (ctx->record_type == NULL)
4316 return;
4318 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4319 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4321 ovar = DECL_ABSTRACT_ORIGIN (f);
4322 nvar = maybe_lookup_decl (ovar, ctx);
4323 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4324 continue;
4326 /* If CTX is a nested parallel directive. Find the immediately
4327 enclosing parallel or workshare construct that contains a
4328 mapping for OVAR. */
4329 var = lookup_decl_in_outer_ctx (ovar, ctx);
4331 if (use_pointer_for_field (ovar, ctx))
4333 x = build_sender_ref (ovar, ctx);
4334 var = build_fold_addr_expr (var);
4335 gimplify_assign (x, var, ilist);
4337 else
4339 x = build_sender_ref (ovar, ctx);
4340 gimplify_assign (x, var, ilist);
4342 if (!TREE_READONLY (var)
4343 /* We don't need to receive a new reference to a result
4344 or parm decl. In fact we may not store to it as we will
4345 invalidate any pending RSO and generate wrong gimple
4346 during inlining. */
4347 && !((TREE_CODE (var) == RESULT_DECL
4348 || TREE_CODE (var) == PARM_DECL)
4349 && DECL_BY_REFERENCE (var)))
4351 x = build_sender_ref (ovar, ctx);
4352 gimplify_assign (var, x, olist);
4359 /* A convenience function to build an empty GIMPLE_COND with just the
4360 condition. */
4362 static gimple
4363 gimple_build_cond_empty (tree cond)
4365 enum tree_code pred_code;
4366 tree lhs, rhs;
4368 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4369 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4373 /* Build the function calls to GOMP_parallel_start etc to actually
4374 generate the parallel operation. REGION is the parallel region
4375 being expanded. BB is the block where to insert the code. WS_ARGS
4376 will be set if this is a call to a combined parallel+workshare
4377 construct, it contains the list of additional arguments needed by
4378 the workshare construct. */
4380 static void
4381 expand_parallel_call (struct omp_region *region, basic_block bb,
4382 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4384 tree t, t1, t2, val, cond, c, clauses, flags;
4385 gimple_stmt_iterator gsi;
4386 gimple stmt;
4387 enum built_in_function start_ix;
4388 int start_ix2;
4389 location_t clause_loc;
4390 vec<tree, va_gc> *args;
4392 clauses = gimple_omp_parallel_clauses (entry_stmt);
4394 /* Determine what flavor of GOMP_parallel we will be
4395 emitting. */
4396 start_ix = BUILT_IN_GOMP_PARALLEL;
4397 if (is_combined_parallel (region))
4399 switch (region->inner->type)
4401 case GIMPLE_OMP_FOR:
4402 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4403 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4404 + (region->inner->sched_kind
4405 == OMP_CLAUSE_SCHEDULE_RUNTIME
4406 ? 3 : region->inner->sched_kind));
4407 start_ix = (enum built_in_function)start_ix2;
4408 break;
4409 case GIMPLE_OMP_SECTIONS:
4410 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4411 break;
4412 default:
4413 gcc_unreachable ();
4417 /* By default, the value of NUM_THREADS is zero (selected at run time)
4418 and there is no conditional. */
4419 cond = NULL_TREE;
4420 val = build_int_cst (unsigned_type_node, 0);
4421 flags = build_int_cst (unsigned_type_node, 0);
4423 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4424 if (c)
4425 cond = OMP_CLAUSE_IF_EXPR (c);
4427 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4428 if (c)
4430 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4431 clause_loc = OMP_CLAUSE_LOCATION (c);
4433 else
4434 clause_loc = gimple_location (entry_stmt);
4436 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4437 if (c)
4438 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4440 /* Ensure 'val' is of the correct type. */
4441 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4443 /* If we found the clause 'if (cond)', build either
4444 (cond != 0) or (cond ? val : 1u). */
4445 if (cond)
4447 cond = gimple_boolify (cond);
4449 if (integer_zerop (val))
4450 val = fold_build2_loc (clause_loc,
4451 EQ_EXPR, unsigned_type_node, cond,
4452 build_int_cst (TREE_TYPE (cond), 0));
4453 else
4455 basic_block cond_bb, then_bb, else_bb;
4456 edge e, e_then, e_else;
4457 tree tmp_then, tmp_else, tmp_join, tmp_var;
4459 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4460 if (gimple_in_ssa_p (cfun))
4462 tmp_then = make_ssa_name (tmp_var, NULL);
4463 tmp_else = make_ssa_name (tmp_var, NULL);
4464 tmp_join = make_ssa_name (tmp_var, NULL);
4466 else
4468 tmp_then = tmp_var;
4469 tmp_else = tmp_var;
4470 tmp_join = tmp_var;
4473 e = split_block (bb, NULL);
4474 cond_bb = e->src;
4475 bb = e->dest;
4476 remove_edge (e);
4478 then_bb = create_empty_bb (cond_bb);
4479 else_bb = create_empty_bb (then_bb);
4480 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4481 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4483 stmt = gimple_build_cond_empty (cond);
4484 gsi = gsi_start_bb (cond_bb);
4485 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4487 gsi = gsi_start_bb (then_bb);
4488 stmt = gimple_build_assign (tmp_then, val);
4489 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4491 gsi = gsi_start_bb (else_bb);
4492 stmt = gimple_build_assign
4493 (tmp_else, build_int_cst (unsigned_type_node, 1));
4494 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4496 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4497 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4498 add_bb_to_loop (then_bb, cond_bb->loop_father);
4499 add_bb_to_loop (else_bb, cond_bb->loop_father);
4500 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4501 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4503 if (gimple_in_ssa_p (cfun))
4505 gimple phi = create_phi_node (tmp_join, bb);
4506 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4507 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4510 val = tmp_join;
4513 gsi = gsi_start_bb (bb);
4514 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4515 false, GSI_CONTINUE_LINKING);
4518 gsi = gsi_last_bb (bb);
4519 t = gimple_omp_parallel_data_arg (entry_stmt);
4520 if (t == NULL)
4521 t1 = null_pointer_node;
4522 else
4523 t1 = build_fold_addr_expr (t);
4524 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4526 vec_alloc (args, 4 + vec_safe_length (ws_args));
4527 args->quick_push (t2);
4528 args->quick_push (t1);
4529 args->quick_push (val);
4530 if (ws_args)
4531 args->splice (*ws_args);
4532 args->quick_push (flags);
4534 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4535 builtin_decl_explicit (start_ix), args);
4537 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4538 false, GSI_CONTINUE_LINKING);
4541 /* Insert a function call whose name is FUNC_NAME with the information from
4542 ENTRY_STMT into the basic_block BB. */
4544 static void
4545 expand_cilk_for_call (basic_block bb, gimple entry_stmt,
4546 vec <tree, va_gc> *ws_args)
4548 tree t, t1, t2;
4549 gimple_stmt_iterator gsi;
4550 vec <tree, va_gc> *args;
4552 gcc_assert (vec_safe_length (ws_args) == 2);
4553 tree func_name = (*ws_args)[0];
4554 tree grain = (*ws_args)[1];
4556 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
4557 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
4558 gcc_assert (count != NULL_TREE);
4559 count = OMP_CLAUSE_OPERAND (count, 0);
4561 gsi = gsi_last_bb (bb);
4562 t = gimple_omp_parallel_data_arg (entry_stmt);
4563 if (t == NULL)
4564 t1 = null_pointer_node;
4565 else
4566 t1 = build_fold_addr_expr (t);
4567 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4569 vec_alloc (args, 4);
4570 args->quick_push (t2);
4571 args->quick_push (t1);
4572 args->quick_push (count);
4573 args->quick_push (grain);
4574 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
4576 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
4577 GSI_CONTINUE_LINKING);
4580 /* Build the function call to GOMP_task to actually
4581 generate the task operation. BB is the block where to insert the code. */
4583 static void
4584 expand_task_call (basic_block bb, gimple entry_stmt)
4586 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4587 gimple_stmt_iterator gsi;
4588 location_t loc = gimple_location (entry_stmt);
4590 clauses = gimple_omp_task_clauses (entry_stmt);
4592 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4593 if (c)
4594 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4595 else
4596 cond = boolean_true_node;
4598 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4599 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4600 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4601 flags = build_int_cst (unsigned_type_node,
4602 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4604 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4605 if (c)
4607 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4608 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4609 build_int_cst (unsigned_type_node, 2),
4610 build_int_cst (unsigned_type_node, 0));
4611 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4613 if (depend)
4614 depend = OMP_CLAUSE_DECL (depend);
4615 else
4616 depend = build_int_cst (ptr_type_node, 0);
4618 gsi = gsi_last_bb (bb);
4619 t = gimple_omp_task_data_arg (entry_stmt);
4620 if (t == NULL)
4621 t2 = null_pointer_node;
4622 else
4623 t2 = build_fold_addr_expr_loc (loc, t);
4624 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4625 t = gimple_omp_task_copy_fn (entry_stmt);
4626 if (t == NULL)
4627 t3 = null_pointer_node;
4628 else
4629 t3 = build_fold_addr_expr_loc (loc, t);
4631 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4632 8, t1, t2, t3,
4633 gimple_omp_task_arg_size (entry_stmt),
4634 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4635 depend);
4637 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4638 false, GSI_CONTINUE_LINKING);
4642 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4643 catch handler and return it. This prevents programs from violating the
4644 structured block semantics with throws. */
4646 static gimple_seq
4647 maybe_catch_exception (gimple_seq body)
4649 gimple g;
4650 tree decl;
4652 if (!flag_exceptions)
4653 return body;
4655 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4656 decl = lang_hooks.eh_protect_cleanup_actions ();
4657 else
4658 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4660 g = gimple_build_eh_must_not_throw (decl);
4661 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4662 GIMPLE_TRY_CATCH);
4664 return gimple_seq_alloc_with_stmt (g);
4667 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4669 static tree
4670 vec2chain (vec<tree, va_gc> *v)
4672 tree chain = NULL_TREE, t;
4673 unsigned ix;
4675 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4677 DECL_CHAIN (t) = chain;
4678 chain = t;
4681 return chain;
4685 /* Remove barriers in REGION->EXIT's block. Note that this is only
4686 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4687 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4688 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4689 removed. */
4691 static void
4692 remove_exit_barrier (struct omp_region *region)
4694 gimple_stmt_iterator gsi;
4695 basic_block exit_bb;
4696 edge_iterator ei;
4697 edge e;
4698 gimple stmt;
4699 int any_addressable_vars = -1;
4701 exit_bb = region->exit;
4703 /* If the parallel region doesn't return, we don't have REGION->EXIT
4704 block at all. */
4705 if (! exit_bb)
4706 return;
4708 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4709 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4710 statements that can appear in between are extremely limited -- no
4711 memory operations at all. Here, we allow nothing at all, so the
4712 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4713 gsi = gsi_last_bb (exit_bb);
4714 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4715 gsi_prev (&gsi);
4716 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4717 return;
4719 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4721 gsi = gsi_last_bb (e->src);
4722 if (gsi_end_p (gsi))
4723 continue;
4724 stmt = gsi_stmt (gsi);
4725 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4726 && !gimple_omp_return_nowait_p (stmt))
4728 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4729 in many cases. If there could be tasks queued, the barrier
4730 might be needed to let the tasks run before some local
4731 variable of the parallel that the task uses as shared
4732 runs out of scope. The task can be spawned either
4733 from within current function (this would be easy to check)
4734 or from some function it calls and gets passed an address
4735 of such a variable. */
4736 if (any_addressable_vars < 0)
4738 gimple parallel_stmt = last_stmt (region->entry);
4739 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4740 tree local_decls, block, decl;
4741 unsigned ix;
4743 any_addressable_vars = 0;
4744 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4745 if (TREE_ADDRESSABLE (decl))
4747 any_addressable_vars = 1;
4748 break;
4750 for (block = gimple_block (stmt);
4751 !any_addressable_vars
4752 && block
4753 && TREE_CODE (block) == BLOCK;
4754 block = BLOCK_SUPERCONTEXT (block))
4756 for (local_decls = BLOCK_VARS (block);
4757 local_decls;
4758 local_decls = DECL_CHAIN (local_decls))
4759 if (TREE_ADDRESSABLE (local_decls))
4761 any_addressable_vars = 1;
4762 break;
4764 if (block == gimple_block (parallel_stmt))
4765 break;
4768 if (!any_addressable_vars)
4769 gimple_omp_return_set_nowait (stmt);
4774 static void
4775 remove_exit_barriers (struct omp_region *region)
4777 if (region->type == GIMPLE_OMP_PARALLEL)
4778 remove_exit_barrier (region);
4780 if (region->inner)
4782 region = region->inner;
4783 remove_exit_barriers (region);
4784 while (region->next)
4786 region = region->next;
4787 remove_exit_barriers (region);
4792 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4793 calls. These can't be declared as const functions, but
4794 within one parallel body they are constant, so they can be
4795 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4796 which are declared const. Similarly for task body, except
4797 that in untied task omp_get_thread_num () can change at any task
4798 scheduling point. */
4800 static void
4801 optimize_omp_library_calls (gimple entry_stmt)
4803 basic_block bb;
4804 gimple_stmt_iterator gsi;
4805 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4806 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4807 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4808 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4809 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4810 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4811 OMP_CLAUSE_UNTIED) != NULL);
4813 FOR_EACH_BB_FN (bb, cfun)
4814 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4816 gimple call = gsi_stmt (gsi);
4817 tree decl;
4819 if (is_gimple_call (call)
4820 && (decl = gimple_call_fndecl (call))
4821 && DECL_EXTERNAL (decl)
4822 && TREE_PUBLIC (decl)
4823 && DECL_INITIAL (decl) == NULL)
4825 tree built_in;
4827 if (DECL_NAME (decl) == thr_num_id)
4829 /* In #pragma omp task untied omp_get_thread_num () can change
4830 during the execution of the task region. */
4831 if (untied_task)
4832 continue;
4833 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4835 else if (DECL_NAME (decl) == num_thr_id)
4836 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4837 else
4838 continue;
4840 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4841 || gimple_call_num_args (call) != 0)
4842 continue;
4844 if (flag_exceptions && !TREE_NOTHROW (decl))
4845 continue;
4847 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4848 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4849 TREE_TYPE (TREE_TYPE (built_in))))
4850 continue;
4852 gimple_call_set_fndecl (call, built_in);
4857 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4858 regimplified. */
4860 static tree
4861 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4863 tree t = *tp;
4865 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4866 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4867 return t;
4869 if (TREE_CODE (t) == ADDR_EXPR)
4870 recompute_tree_invariant_for_addr_expr (t);
4872 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4873 return NULL_TREE;
4876 /* Prepend TO = FROM assignment before *GSI_P. */
4878 static void
4879 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4881 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4882 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4883 true, GSI_SAME_STMT);
4884 gimple stmt = gimple_build_assign (to, from);
4885 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4886 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4887 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4889 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4890 gimple_regimplify_operands (stmt, &gsi);
4894 /* Expand the OpenMP parallel or task directive starting at REGION. */
4896 static void
4897 expand_omp_taskreg (struct omp_region *region)
4899 basic_block entry_bb, exit_bb, new_bb;
4900 struct function *child_cfun;
4901 tree child_fn, block, t;
4902 gimple_stmt_iterator gsi;
4903 gimple entry_stmt, stmt;
4904 edge e;
4905 vec<tree, va_gc> *ws_args;
4907 entry_stmt = last_stmt (region->entry);
4908 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4909 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4911 entry_bb = region->entry;
4912 exit_bb = region->exit;
4914 bool is_cilk_for
4915 = (flag_cilkplus
4916 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
4917 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
4918 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
4920 if (is_cilk_for)
4921 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
4922 and the inner statement contains the name of the built-in function
4923 and grain. */
4924 ws_args = region->inner->ws_args;
4925 else if (is_combined_parallel (region))
4926 ws_args = region->ws_args;
4927 else
4928 ws_args = NULL;
4930 if (child_cfun->cfg)
4932 /* Due to inlining, it may happen that we have already outlined
4933 the region, in which case all we need to do is make the
4934 sub-graph unreachable and emit the parallel call. */
4935 edge entry_succ_e, exit_succ_e;
4937 entry_succ_e = single_succ_edge (entry_bb);
4939 gsi = gsi_last_bb (entry_bb);
4940 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4941 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4942 gsi_remove (&gsi, true);
4944 new_bb = entry_bb;
4945 if (exit_bb)
4947 exit_succ_e = single_succ_edge (exit_bb);
4948 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4950 remove_edge_and_dominated_blocks (entry_succ_e);
4952 else
4954 unsigned srcidx, dstidx, num;
4956 /* If the parallel region needs data sent from the parent
4957 function, then the very first statement (except possible
4958 tree profile counter updates) of the parallel body
4959 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4960 &.OMP_DATA_O is passed as an argument to the child function,
4961 we need to replace it with the argument as seen by the child
4962 function.
4964 In most cases, this will end up being the identity assignment
4965 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4966 a function call that has been inlined, the original PARM_DECL
4967 .OMP_DATA_I may have been converted into a different local
4968 variable. In which case, we need to keep the assignment. */
4969 if (gimple_omp_taskreg_data_arg (entry_stmt))
4971 basic_block entry_succ_bb = single_succ (entry_bb);
4972 tree arg, narg;
4973 gimple parcopy_stmt = NULL;
4975 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4977 gimple stmt;
4979 gcc_assert (!gsi_end_p (gsi));
4980 stmt = gsi_stmt (gsi);
4981 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4982 continue;
4984 if (gimple_num_ops (stmt) == 2)
4986 tree arg = gimple_assign_rhs1 (stmt);
4988 /* We're ignore the subcode because we're
4989 effectively doing a STRIP_NOPS. */
4991 if (TREE_CODE (arg) == ADDR_EXPR
4992 && TREE_OPERAND (arg, 0)
4993 == gimple_omp_taskreg_data_arg (entry_stmt))
4995 parcopy_stmt = stmt;
4996 break;
5001 gcc_assert (parcopy_stmt != NULL);
5002 arg = DECL_ARGUMENTS (child_fn);
5004 if (!gimple_in_ssa_p (cfun))
5006 if (gimple_assign_lhs (parcopy_stmt) == arg)
5007 gsi_remove (&gsi, true);
5008 else
5010 /* ?? Is setting the subcode really necessary ?? */
5011 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5012 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5015 else
5017 /* If we are in ssa form, we must load the value from the default
5018 definition of the argument. That should not be defined now,
5019 since the argument is not used uninitialized. */
5020 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5021 narg = make_ssa_name (arg, gimple_build_nop ());
5022 set_ssa_default_def (cfun, arg, narg);
5023 /* ?? Is setting the subcode really necessary ?? */
5024 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5025 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5026 update_stmt (parcopy_stmt);
5030 /* Declare local variables needed in CHILD_CFUN. */
5031 block = DECL_INITIAL (child_fn);
5032 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5033 /* The gimplifier could record temporaries in parallel/task block
5034 rather than in containing function's local_decls chain,
5035 which would mean cgraph missed finalizing them. Do it now. */
5036 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5037 if (TREE_CODE (t) == VAR_DECL
5038 && TREE_STATIC (t)
5039 && !DECL_EXTERNAL (t))
5040 varpool_node::finalize_decl (t);
5041 DECL_SAVED_TREE (child_fn) = NULL;
5042 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5043 gimple_set_body (child_fn, NULL);
5044 TREE_USED (block) = 1;
5046 /* Reset DECL_CONTEXT on function arguments. */
5047 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5048 DECL_CONTEXT (t) = child_fn;
5050 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5051 so that it can be moved to the child function. */
5052 gsi = gsi_last_bb (entry_bb);
5053 stmt = gsi_stmt (gsi);
5054 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5055 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5056 gsi_remove (&gsi, true);
5057 e = split_block (entry_bb, stmt);
5058 entry_bb = e->dest;
5059 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5061 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5062 if (exit_bb)
5064 gsi = gsi_last_bb (exit_bb);
5065 gcc_assert (!gsi_end_p (gsi)
5066 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5067 stmt = gimple_build_return (NULL);
5068 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5069 gsi_remove (&gsi, true);
5072 /* Move the parallel region into CHILD_CFUN. */
5074 if (gimple_in_ssa_p (cfun))
5076 init_tree_ssa (child_cfun);
5077 init_ssa_operands (child_cfun);
5078 child_cfun->gimple_df->in_ssa_p = true;
5079 block = NULL_TREE;
5081 else
5082 block = gimple_block (entry_stmt);
5084 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5085 if (exit_bb)
5086 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5087 /* When the OMP expansion process cannot guarantee an up-to-date
5088 loop tree arrange for the child function to fixup loops. */
5089 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5090 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5092 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5093 num = vec_safe_length (child_cfun->local_decls);
5094 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5096 t = (*child_cfun->local_decls)[srcidx];
5097 if (DECL_CONTEXT (t) == cfun->decl)
5098 continue;
5099 if (srcidx != dstidx)
5100 (*child_cfun->local_decls)[dstidx] = t;
5101 dstidx++;
5103 if (dstidx != num)
5104 vec_safe_truncate (child_cfun->local_decls, dstidx);
5106 /* Inform the callgraph about the new function. */
5107 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5108 cgraph_node::add_new_function (child_fn, true);
5110 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5111 fixed in a following pass. */
5112 push_cfun (child_cfun);
5113 if (optimize)
5114 optimize_omp_library_calls (entry_stmt);
5115 cgraph_edge::rebuild_edges ();
5117 /* Some EH regions might become dead, see PR34608. If
5118 pass_cleanup_cfg isn't the first pass to happen with the
5119 new child, these dead EH edges might cause problems.
5120 Clean them up now. */
5121 if (flag_exceptions)
5123 basic_block bb;
5124 bool changed = false;
5126 FOR_EACH_BB_FN (bb, cfun)
5127 changed |= gimple_purge_dead_eh_edges (bb);
5128 if (changed)
5129 cleanup_tree_cfg ();
5131 if (gimple_in_ssa_p (cfun))
5132 update_ssa (TODO_update_ssa);
5133 pop_cfun ();
5136 /* Emit a library call to launch the children threads. */
5137 if (is_cilk_for)
5138 expand_cilk_for_call (new_bb, entry_stmt, ws_args);
5139 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5140 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
5141 else
5142 expand_task_call (new_bb, entry_stmt);
5143 if (gimple_in_ssa_p (cfun))
5144 update_ssa (TODO_update_ssa_only_virtuals);
5148 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5149 of the combined collapse > 1 loop constructs, generate code like:
5150 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5151 if (cond3 is <)
5152 adj = STEP3 - 1;
5153 else
5154 adj = STEP3 + 1;
5155 count3 = (adj + N32 - N31) / STEP3;
5156 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5157 if (cond2 is <)
5158 adj = STEP2 - 1;
5159 else
5160 adj = STEP2 + 1;
5161 count2 = (adj + N22 - N21) / STEP2;
5162 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5163 if (cond1 is <)
5164 adj = STEP1 - 1;
5165 else
5166 adj = STEP1 + 1;
5167 count1 = (adj + N12 - N11) / STEP1;
5168 count = count1 * count2 * count3;
5169 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5170 count = 0;
5171 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5172 of the combined loop constructs, just initialize COUNTS array
5173 from the _looptemp_ clauses. */
5175 /* NOTE: It *could* be better to moosh all of the BBs together,
5176 creating one larger BB with all the computation and the unexpected
5177 jump at the end. I.e.
5179 bool zero3, zero2, zero1, zero;
5181 zero3 = N32 c3 N31;
5182 count3 = (N32 - N31) /[cl] STEP3;
5183 zero2 = N22 c2 N21;
5184 count2 = (N22 - N21) /[cl] STEP2;
5185 zero1 = N12 c1 N11;
5186 count1 = (N12 - N11) /[cl] STEP1;
5187 zero = zero3 || zero2 || zero1;
5188 count = count1 * count2 * count3;
5189 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5191 After all, we expect the zero=false, and thus we expect to have to
5192 evaluate all of the comparison expressions, so short-circuiting
5193 oughtn't be a win. Since the condition isn't protecting a
5194 denominator, we're not concerned about divide-by-zero, so we can
5195 fully evaluate count even if a numerator turned out to be wrong.
5197 It seems like putting this all together would create much better
5198 scheduling opportunities, and less pressure on the chip's branch
5199 predictor. */
5201 static void
5202 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5203 basic_block &entry_bb, tree *counts,
5204 basic_block &zero_iter_bb, int &first_zero_iter,
5205 basic_block &l2_dom_bb)
5207 tree t, type = TREE_TYPE (fd->loop.v);
5208 gimple stmt;
5209 edge e, ne;
5210 int i;
5212 /* Collapsed loops need work for expansion into SSA form. */
5213 gcc_assert (!gimple_in_ssa_p (cfun));
5215 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5216 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5218 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5219 isn't supposed to be handled, as the inner loop doesn't
5220 use it. */
5221 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5222 OMP_CLAUSE__LOOPTEMP_);
5223 gcc_assert (innerc);
5224 for (i = 0; i < fd->collapse; i++)
5226 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5227 OMP_CLAUSE__LOOPTEMP_);
5228 gcc_assert (innerc);
5229 if (i)
5230 counts[i] = OMP_CLAUSE_DECL (innerc);
5231 else
5232 counts[0] = NULL_TREE;
5234 return;
5237 for (i = 0; i < fd->collapse; i++)
5239 tree itype = TREE_TYPE (fd->loops[i].v);
5241 if (SSA_VAR_P (fd->loop.n2)
5242 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5243 fold_convert (itype, fd->loops[i].n1),
5244 fold_convert (itype, fd->loops[i].n2)))
5245 == NULL_TREE || !integer_onep (t)))
5247 tree n1, n2;
5248 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5249 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5250 true, GSI_SAME_STMT);
5251 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5252 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5253 true, GSI_SAME_STMT);
5254 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5255 NULL_TREE, NULL_TREE);
5256 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5257 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5258 expand_omp_regimplify_p, NULL, NULL)
5259 || walk_tree (gimple_cond_rhs_ptr (stmt),
5260 expand_omp_regimplify_p, NULL, NULL))
5262 *gsi = gsi_for_stmt (stmt);
5263 gimple_regimplify_operands (stmt, gsi);
5265 e = split_block (entry_bb, stmt);
5266 if (zero_iter_bb == NULL)
5268 first_zero_iter = i;
5269 zero_iter_bb = create_empty_bb (entry_bb);
5270 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5271 *gsi = gsi_after_labels (zero_iter_bb);
5272 stmt = gimple_build_assign (fd->loop.n2,
5273 build_zero_cst (type));
5274 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5275 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5276 entry_bb);
5278 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5279 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5280 e->flags = EDGE_TRUE_VALUE;
5281 e->probability = REG_BR_PROB_BASE - ne->probability;
5282 if (l2_dom_bb == NULL)
5283 l2_dom_bb = entry_bb;
5284 entry_bb = e->dest;
5285 *gsi = gsi_last_bb (entry_bb);
5288 if (POINTER_TYPE_P (itype))
5289 itype = signed_type_for (itype);
5290 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5291 ? -1 : 1));
5292 t = fold_build2 (PLUS_EXPR, itype,
5293 fold_convert (itype, fd->loops[i].step), t);
5294 t = fold_build2 (PLUS_EXPR, itype, t,
5295 fold_convert (itype, fd->loops[i].n2));
5296 t = fold_build2 (MINUS_EXPR, itype, t,
5297 fold_convert (itype, fd->loops[i].n1));
5298 /* ?? We could probably use CEIL_DIV_EXPR instead of
5299 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5300 generate the same code in the end because generically we
5301 don't know that the values involved must be negative for
5302 GT?? */
5303 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5304 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5305 fold_build1 (NEGATE_EXPR, itype, t),
5306 fold_build1 (NEGATE_EXPR, itype,
5307 fold_convert (itype,
5308 fd->loops[i].step)));
5309 else
5310 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5311 fold_convert (itype, fd->loops[i].step));
5312 t = fold_convert (type, t);
5313 if (TREE_CODE (t) == INTEGER_CST)
5314 counts[i] = t;
5315 else
5317 counts[i] = create_tmp_reg (type, ".count");
5318 expand_omp_build_assign (gsi, counts[i], t);
5320 if (SSA_VAR_P (fd->loop.n2))
5322 if (i == 0)
5323 t = counts[0];
5324 else
5325 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5326 expand_omp_build_assign (gsi, fd->loop.n2, t);
5332 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5333 T = V;
5334 V3 = N31 + (T % count3) * STEP3;
5335 T = T / count3;
5336 V2 = N21 + (T % count2) * STEP2;
5337 T = T / count2;
5338 V1 = N11 + T * STEP1;
5339 if this loop doesn't have an inner loop construct combined with it.
5340 If it does have an inner loop construct combined with it and the
5341 iteration count isn't known constant, store values from counts array
5342 into its _looptemp_ temporaries instead. */
5344 static void
5345 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5346 tree *counts, gimple inner_stmt, tree startvar)
5348 int i;
5349 if (gimple_omp_for_combined_p (fd->for_stmt))
5351 /* If fd->loop.n2 is constant, then no propagation of the counts
5352 is needed, they are constant. */
5353 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5354 return;
5356 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5357 ? gimple_omp_parallel_clauses (inner_stmt)
5358 : gimple_omp_for_clauses (inner_stmt);
5359 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5360 isn't supposed to be handled, as the inner loop doesn't
5361 use it. */
5362 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5363 gcc_assert (innerc);
5364 for (i = 0; i < fd->collapse; i++)
5366 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5367 OMP_CLAUSE__LOOPTEMP_);
5368 gcc_assert (innerc);
5369 if (i)
5371 tree tem = OMP_CLAUSE_DECL (innerc);
5372 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5373 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5374 false, GSI_CONTINUE_LINKING);
5375 gimple stmt = gimple_build_assign (tem, t);
5376 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5379 return;
5382 tree type = TREE_TYPE (fd->loop.v);
5383 tree tem = create_tmp_reg (type, ".tem");
5384 gimple stmt = gimple_build_assign (tem, startvar);
5385 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5387 for (i = fd->collapse - 1; i >= 0; i--)
5389 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5390 itype = vtype;
5391 if (POINTER_TYPE_P (vtype))
5392 itype = signed_type_for (vtype);
5393 if (i != 0)
5394 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5395 else
5396 t = tem;
5397 t = fold_convert (itype, t);
5398 t = fold_build2 (MULT_EXPR, itype, t,
5399 fold_convert (itype, fd->loops[i].step));
5400 if (POINTER_TYPE_P (vtype))
5401 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5402 else
5403 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5404 t = force_gimple_operand_gsi (gsi, t,
5405 DECL_P (fd->loops[i].v)
5406 && TREE_ADDRESSABLE (fd->loops[i].v),
5407 NULL_TREE, false,
5408 GSI_CONTINUE_LINKING);
5409 stmt = gimple_build_assign (fd->loops[i].v, t);
5410 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5411 if (i != 0)
5413 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5414 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5415 false, GSI_CONTINUE_LINKING);
5416 stmt = gimple_build_assign (tem, t);
5417 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5423 /* Helper function for expand_omp_for_*. Generate code like:
5424 L10:
5425 V3 += STEP3;
5426 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5427 L11:
5428 V3 = N31;
5429 V2 += STEP2;
5430 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5431 L12:
5432 V2 = N21;
5433 V1 += STEP1;
5434 goto BODY_BB; */
5436 static basic_block
5437 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5438 basic_block body_bb)
5440 basic_block last_bb, bb, collapse_bb = NULL;
5441 int i;
5442 gimple_stmt_iterator gsi;
5443 edge e;
5444 tree t;
5445 gimple stmt;
5447 last_bb = cont_bb;
5448 for (i = fd->collapse - 1; i >= 0; i--)
5450 tree vtype = TREE_TYPE (fd->loops[i].v);
5452 bb = create_empty_bb (last_bb);
5453 add_bb_to_loop (bb, last_bb->loop_father);
5454 gsi = gsi_start_bb (bb);
5456 if (i < fd->collapse - 1)
5458 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5459 e->probability = REG_BR_PROB_BASE / 8;
5461 t = fd->loops[i + 1].n1;
5462 t = force_gimple_operand_gsi (&gsi, t,
5463 DECL_P (fd->loops[i + 1].v)
5464 && TREE_ADDRESSABLE (fd->loops[i
5465 + 1].v),
5466 NULL_TREE, false,
5467 GSI_CONTINUE_LINKING);
5468 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5469 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5471 else
5472 collapse_bb = bb;
5474 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5476 if (POINTER_TYPE_P (vtype))
5477 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5478 else
5479 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5480 t = force_gimple_operand_gsi (&gsi, t,
5481 DECL_P (fd->loops[i].v)
5482 && TREE_ADDRESSABLE (fd->loops[i].v),
5483 NULL_TREE, false, GSI_CONTINUE_LINKING);
5484 stmt = gimple_build_assign (fd->loops[i].v, t);
5485 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5487 if (i > 0)
5489 t = fd->loops[i].n2;
5490 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5491 false, GSI_CONTINUE_LINKING);
5492 tree v = fd->loops[i].v;
5493 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5494 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5495 false, GSI_CONTINUE_LINKING);
5496 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5497 stmt = gimple_build_cond_empty (t);
5498 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5499 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5500 e->probability = REG_BR_PROB_BASE * 7 / 8;
5502 else
5503 make_edge (bb, body_bb, EDGE_FALLTHRU);
5504 last_bb = bb;
5507 return collapse_bb;
5511 /* A subroutine of expand_omp_for. Generate code for a parallel
5512 loop with any schedule. Given parameters:
5514 for (V = N1; V cond N2; V += STEP) BODY;
5516 where COND is "<" or ">", we generate pseudocode
5518 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5519 if (more) goto L0; else goto L3;
5521 V = istart0;
5522 iend = iend0;
5524 BODY;
5525 V += STEP;
5526 if (V cond iend) goto L1; else goto L2;
5528 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5531 If this is a combined omp parallel loop, instead of the call to
5532 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5533 If this is gimple_omp_for_combined_p loop, then instead of assigning
5534 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5535 inner GIMPLE_OMP_FOR and V += STEP; and
5536 if (V cond iend) goto L1; else goto L2; are removed.
5538 For collapsed loops, given parameters:
5539 collapse(3)
5540 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5541 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5542 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5543 BODY;
5545 we generate pseudocode
5547 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5548 if (cond3 is <)
5549 adj = STEP3 - 1;
5550 else
5551 adj = STEP3 + 1;
5552 count3 = (adj + N32 - N31) / STEP3;
5553 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5554 if (cond2 is <)
5555 adj = STEP2 - 1;
5556 else
5557 adj = STEP2 + 1;
5558 count2 = (adj + N22 - N21) / STEP2;
5559 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5560 if (cond1 is <)
5561 adj = STEP1 - 1;
5562 else
5563 adj = STEP1 + 1;
5564 count1 = (adj + N12 - N11) / STEP1;
5565 count = count1 * count2 * count3;
5566 goto Z1;
5568 count = 0;
5570 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5571 if (more) goto L0; else goto L3;
5573 V = istart0;
5574 T = V;
5575 V3 = N31 + (T % count3) * STEP3;
5576 T = T / count3;
5577 V2 = N21 + (T % count2) * STEP2;
5578 T = T / count2;
5579 V1 = N11 + T * STEP1;
5580 iend = iend0;
5582 BODY;
5583 V += 1;
5584 if (V < iend) goto L10; else goto L2;
5585 L10:
5586 V3 += STEP3;
5587 if (V3 cond3 N32) goto L1; else goto L11;
5588 L11:
5589 V3 = N31;
5590 V2 += STEP2;
5591 if (V2 cond2 N22) goto L1; else goto L12;
5592 L12:
5593 V2 = N21;
5594 V1 += STEP1;
5595 goto L1;
5597 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5602 static void
5603 expand_omp_for_generic (struct omp_region *region,
5604 struct omp_for_data *fd,
5605 enum built_in_function start_fn,
5606 enum built_in_function next_fn,
5607 gimple inner_stmt)
5609 tree type, istart0, iend0, iend;
5610 tree t, vmain, vback, bias = NULL_TREE;
5611 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5612 basic_block l2_bb = NULL, l3_bb = NULL;
5613 gimple_stmt_iterator gsi;
5614 gimple stmt;
5615 bool in_combined_parallel = is_combined_parallel (region);
5616 bool broken_loop = region->cont == NULL;
5617 edge e, ne;
5618 tree *counts = NULL;
5619 int i;
5621 gcc_assert (!broken_loop || !in_combined_parallel);
5622 gcc_assert (fd->iter_type == long_integer_type_node
5623 || !in_combined_parallel);
5625 type = TREE_TYPE (fd->loop.v);
5626 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5627 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5628 TREE_ADDRESSABLE (istart0) = 1;
5629 TREE_ADDRESSABLE (iend0) = 1;
5631 /* See if we need to bias by LLONG_MIN. */
5632 if (fd->iter_type == long_long_unsigned_type_node
5633 && TREE_CODE (type) == INTEGER_TYPE
5634 && !TYPE_UNSIGNED (type))
5636 tree n1, n2;
5638 if (fd->loop.cond_code == LT_EXPR)
5640 n1 = fd->loop.n1;
5641 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5643 else
5645 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5646 n2 = fd->loop.n1;
5648 if (TREE_CODE (n1) != INTEGER_CST
5649 || TREE_CODE (n2) != INTEGER_CST
5650 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5651 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5654 entry_bb = region->entry;
5655 cont_bb = region->cont;
5656 collapse_bb = NULL;
5657 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5658 gcc_assert (broken_loop
5659 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5660 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5661 l1_bb = single_succ (l0_bb);
5662 if (!broken_loop)
5664 l2_bb = create_empty_bb (cont_bb);
5665 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5666 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5668 else
5669 l2_bb = NULL;
5670 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5671 exit_bb = region->exit;
5673 gsi = gsi_last_bb (entry_bb);
5675 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5676 if (fd->collapse > 1)
5678 int first_zero_iter = -1;
5679 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5681 counts = XALLOCAVEC (tree, fd->collapse);
5682 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5683 zero_iter_bb, first_zero_iter,
5684 l2_dom_bb);
5686 if (zero_iter_bb)
5688 /* Some counts[i] vars might be uninitialized if
5689 some loop has zero iterations. But the body shouldn't
5690 be executed in that case, so just avoid uninit warnings. */
5691 for (i = first_zero_iter; i < fd->collapse; i++)
5692 if (SSA_VAR_P (counts[i]))
5693 TREE_NO_WARNING (counts[i]) = 1;
5694 gsi_prev (&gsi);
5695 e = split_block (entry_bb, gsi_stmt (gsi));
5696 entry_bb = e->dest;
5697 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5698 gsi = gsi_last_bb (entry_bb);
5699 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5700 get_immediate_dominator (CDI_DOMINATORS,
5701 zero_iter_bb));
5704 if (in_combined_parallel)
5706 /* In a combined parallel loop, emit a call to
5707 GOMP_loop_foo_next. */
5708 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5709 build_fold_addr_expr (istart0),
5710 build_fold_addr_expr (iend0));
5712 else
5714 tree t0, t1, t2, t3, t4;
5715 /* If this is not a combined parallel loop, emit a call to
5716 GOMP_loop_foo_start in ENTRY_BB. */
5717 t4 = build_fold_addr_expr (iend0);
5718 t3 = build_fold_addr_expr (istart0);
5719 t2 = fold_convert (fd->iter_type, fd->loop.step);
5720 t1 = fd->loop.n2;
5721 t0 = fd->loop.n1;
5722 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5724 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5725 OMP_CLAUSE__LOOPTEMP_);
5726 gcc_assert (innerc);
5727 t0 = OMP_CLAUSE_DECL (innerc);
5728 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5729 OMP_CLAUSE__LOOPTEMP_);
5730 gcc_assert (innerc);
5731 t1 = OMP_CLAUSE_DECL (innerc);
5733 if (POINTER_TYPE_P (TREE_TYPE (t0))
5734 && TYPE_PRECISION (TREE_TYPE (t0))
5735 != TYPE_PRECISION (fd->iter_type))
5737 /* Avoid casting pointers to integer of a different size. */
5738 tree itype = signed_type_for (type);
5739 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5740 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5742 else
5744 t1 = fold_convert (fd->iter_type, t1);
5745 t0 = fold_convert (fd->iter_type, t0);
5747 if (bias)
5749 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5750 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5752 if (fd->iter_type == long_integer_type_node)
5754 if (fd->chunk_size)
5756 t = fold_convert (fd->iter_type, fd->chunk_size);
5757 t = build_call_expr (builtin_decl_explicit (start_fn),
5758 6, t0, t1, t2, t, t3, t4);
5760 else
5761 t = build_call_expr (builtin_decl_explicit (start_fn),
5762 5, t0, t1, t2, t3, t4);
5764 else
5766 tree t5;
5767 tree c_bool_type;
5768 tree bfn_decl;
5770 /* The GOMP_loop_ull_*start functions have additional boolean
5771 argument, true for < loops and false for > loops.
5772 In Fortran, the C bool type can be different from
5773 boolean_type_node. */
5774 bfn_decl = builtin_decl_explicit (start_fn);
5775 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5776 t5 = build_int_cst (c_bool_type,
5777 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5778 if (fd->chunk_size)
5780 tree bfn_decl = builtin_decl_explicit (start_fn);
5781 t = fold_convert (fd->iter_type, fd->chunk_size);
5782 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5784 else
5785 t = build_call_expr (builtin_decl_explicit (start_fn),
5786 6, t5, t0, t1, t2, t3, t4);
5789 if (TREE_TYPE (t) != boolean_type_node)
5790 t = fold_build2 (NE_EXPR, boolean_type_node,
5791 t, build_int_cst (TREE_TYPE (t), 0));
5792 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5793 true, GSI_SAME_STMT);
5794 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5796 /* Remove the GIMPLE_OMP_FOR statement. */
5797 gsi_remove (&gsi, true);
5799 /* Iteration setup for sequential loop goes in L0_BB. */
5800 tree startvar = fd->loop.v;
5801 tree endvar = NULL_TREE;
5803 if (gimple_omp_for_combined_p (fd->for_stmt))
5805 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5806 && gimple_omp_for_kind (inner_stmt)
5807 == GF_OMP_FOR_KIND_SIMD);
5808 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5809 OMP_CLAUSE__LOOPTEMP_);
5810 gcc_assert (innerc);
5811 startvar = OMP_CLAUSE_DECL (innerc);
5812 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5813 OMP_CLAUSE__LOOPTEMP_);
5814 gcc_assert (innerc);
5815 endvar = OMP_CLAUSE_DECL (innerc);
5818 gsi = gsi_start_bb (l0_bb);
5819 t = istart0;
5820 if (bias)
5821 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5822 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5823 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5824 t = fold_convert (TREE_TYPE (startvar), t);
5825 t = force_gimple_operand_gsi (&gsi, t,
5826 DECL_P (startvar)
5827 && TREE_ADDRESSABLE (startvar),
5828 NULL_TREE, false, GSI_CONTINUE_LINKING);
5829 stmt = gimple_build_assign (startvar, t);
5830 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5832 t = iend0;
5833 if (bias)
5834 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5835 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5836 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5837 t = fold_convert (TREE_TYPE (startvar), t);
5838 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5839 false, GSI_CONTINUE_LINKING);
5840 if (endvar)
5842 stmt = gimple_build_assign (endvar, iend);
5843 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5844 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
5845 stmt = gimple_build_assign (fd->loop.v, iend);
5846 else
5847 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend,
5848 NULL_TREE);
5849 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5851 if (fd->collapse > 1)
5852 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5854 if (!broken_loop)
5856 /* Code to control the increment and predicate for the sequential
5857 loop goes in the CONT_BB. */
5858 gsi = gsi_last_bb (cont_bb);
5859 stmt = gsi_stmt (gsi);
5860 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5861 vmain = gimple_omp_continue_control_use (stmt);
5862 vback = gimple_omp_continue_control_def (stmt);
5864 if (!gimple_omp_for_combined_p (fd->for_stmt))
5866 if (POINTER_TYPE_P (type))
5867 t = fold_build_pointer_plus (vmain, fd->loop.step);
5868 else
5869 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5870 t = force_gimple_operand_gsi (&gsi, t,
5871 DECL_P (vback)
5872 && TREE_ADDRESSABLE (vback),
5873 NULL_TREE, true, GSI_SAME_STMT);
5874 stmt = gimple_build_assign (vback, t);
5875 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5877 t = build2 (fd->loop.cond_code, boolean_type_node,
5878 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5879 iend);
5880 stmt = gimple_build_cond_empty (t);
5881 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5884 /* Remove GIMPLE_OMP_CONTINUE. */
5885 gsi_remove (&gsi, true);
5887 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5888 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5890 /* Emit code to get the next parallel iteration in L2_BB. */
5891 gsi = gsi_start_bb (l2_bb);
5893 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5894 build_fold_addr_expr (istart0),
5895 build_fold_addr_expr (iend0));
5896 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5897 false, GSI_CONTINUE_LINKING);
5898 if (TREE_TYPE (t) != boolean_type_node)
5899 t = fold_build2 (NE_EXPR, boolean_type_node,
5900 t, build_int_cst (TREE_TYPE (t), 0));
5901 stmt = gimple_build_cond_empty (t);
5902 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5905 /* Add the loop cleanup function. */
5906 gsi = gsi_last_bb (exit_bb);
5907 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5908 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5909 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5910 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5911 else
5912 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5913 stmt = gimple_build_call (t, 0);
5914 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5915 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5916 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5917 gsi_remove (&gsi, true);
5919 /* Connect the new blocks. */
5920 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5921 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5923 if (!broken_loop)
5925 gimple_seq phis;
5927 e = find_edge (cont_bb, l3_bb);
5928 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5930 phis = phi_nodes (l3_bb);
5931 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5933 gimple phi = gsi_stmt (gsi);
5934 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5935 PHI_ARG_DEF_FROM_EDGE (phi, e));
5937 remove_edge (e);
5939 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5940 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5941 e = find_edge (cont_bb, l1_bb);
5942 if (gimple_omp_for_combined_p (fd->for_stmt))
5944 remove_edge (e);
5945 e = NULL;
5947 else if (fd->collapse > 1)
5949 remove_edge (e);
5950 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5952 else
5953 e->flags = EDGE_TRUE_VALUE;
5954 if (e)
5956 e->probability = REG_BR_PROB_BASE * 7 / 8;
5957 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5959 else
5961 e = find_edge (cont_bb, l2_bb);
5962 e->flags = EDGE_FALLTHRU;
5964 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5966 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5967 recompute_dominator (CDI_DOMINATORS, l2_bb));
5968 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5969 recompute_dominator (CDI_DOMINATORS, l3_bb));
5970 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5971 recompute_dominator (CDI_DOMINATORS, l0_bb));
5972 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5973 recompute_dominator (CDI_DOMINATORS, l1_bb));
5975 struct loop *outer_loop = alloc_loop ();
5976 outer_loop->header = l0_bb;
5977 outer_loop->latch = l2_bb;
5978 add_loop (outer_loop, l0_bb->loop_father);
5980 if (!gimple_omp_for_combined_p (fd->for_stmt))
5982 struct loop *loop = alloc_loop ();
5983 loop->header = l1_bb;
5984 /* The loop may have multiple latches. */
5985 add_loop (loop, outer_loop);
5991 /* A subroutine of expand_omp_for. Generate code for a parallel
5992 loop with static schedule and no specified chunk size. Given
5993 parameters:
5995 for (V = N1; V cond N2; V += STEP) BODY;
5997 where COND is "<" or ">", we generate pseudocode
5999 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6000 if (cond is <)
6001 adj = STEP - 1;
6002 else
6003 adj = STEP + 1;
6004 if ((__typeof (V)) -1 > 0 && cond is >)
6005 n = -(adj + N2 - N1) / -STEP;
6006 else
6007 n = (adj + N2 - N1) / STEP;
6008 q = n / nthreads;
6009 tt = n % nthreads;
6010 if (threadid < tt) goto L3; else goto L4;
6012 tt = 0;
6013 q = q + 1;
6015 s0 = q * threadid + tt;
6016 e0 = s0 + q;
6017 V = s0 * STEP + N1;
6018 if (s0 >= e0) goto L2; else goto L0;
6020 e = e0 * STEP + N1;
6022 BODY;
6023 V += STEP;
6024 if (V cond e) goto L1;
6028 static void
6029 expand_omp_for_static_nochunk (struct omp_region *region,
6030 struct omp_for_data *fd,
6031 gimple inner_stmt)
6033 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6034 tree type, itype, vmain, vback;
6035 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6036 basic_block body_bb, cont_bb, collapse_bb = NULL;
6037 basic_block fin_bb;
6038 gimple_stmt_iterator gsi;
6039 gimple stmt;
6040 edge ep;
6041 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6042 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6043 bool broken_loop = region->cont == NULL;
6044 tree *counts = NULL;
6045 tree n1, n2, step;
6047 itype = type = TREE_TYPE (fd->loop.v);
6048 if (POINTER_TYPE_P (type))
6049 itype = signed_type_for (type);
6051 entry_bb = region->entry;
6052 cont_bb = region->cont;
6053 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6054 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6055 gcc_assert (broken_loop
6056 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6057 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6058 body_bb = single_succ (seq_start_bb);
6059 if (!broken_loop)
6061 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6062 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6064 exit_bb = region->exit;
6066 /* Iteration space partitioning goes in ENTRY_BB. */
6067 gsi = gsi_last_bb (entry_bb);
6068 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6070 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6072 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6073 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6076 if (fd->collapse > 1)
6078 int first_zero_iter = -1;
6079 basic_block l2_dom_bb = NULL;
6081 counts = XALLOCAVEC (tree, fd->collapse);
6082 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6083 fin_bb, first_zero_iter,
6084 l2_dom_bb);
6085 t = NULL_TREE;
6087 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6088 t = integer_one_node;
6089 else
6090 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6091 fold_convert (type, fd->loop.n1),
6092 fold_convert (type, fd->loop.n2));
6093 if (fd->collapse == 1
6094 && TYPE_UNSIGNED (type)
6095 && (t == NULL_TREE || !integer_onep (t)))
6097 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6098 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6099 true, GSI_SAME_STMT);
6100 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6101 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6102 true, GSI_SAME_STMT);
6103 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6104 NULL_TREE, NULL_TREE);
6105 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6106 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6107 expand_omp_regimplify_p, NULL, NULL)
6108 || walk_tree (gimple_cond_rhs_ptr (stmt),
6109 expand_omp_regimplify_p, NULL, NULL))
6111 gsi = gsi_for_stmt (stmt);
6112 gimple_regimplify_operands (stmt, &gsi);
6114 ep = split_block (entry_bb, stmt);
6115 ep->flags = EDGE_TRUE_VALUE;
6116 entry_bb = ep->dest;
6117 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6118 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6119 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6120 if (gimple_in_ssa_p (cfun))
6122 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6123 for (gsi = gsi_start_phis (fin_bb);
6124 !gsi_end_p (gsi); gsi_next (&gsi))
6126 gimple phi = gsi_stmt (gsi);
6127 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6128 ep, UNKNOWN_LOCATION);
6131 gsi = gsi_last_bb (entry_bb);
6134 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6135 t = fold_convert (itype, t);
6136 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6137 true, GSI_SAME_STMT);
6139 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6140 t = fold_convert (itype, t);
6141 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6142 true, GSI_SAME_STMT);
6144 n1 = fd->loop.n1;
6145 n2 = fd->loop.n2;
6146 step = fd->loop.step;
6147 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6149 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6150 OMP_CLAUSE__LOOPTEMP_);
6151 gcc_assert (innerc);
6152 n1 = OMP_CLAUSE_DECL (innerc);
6153 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6154 OMP_CLAUSE__LOOPTEMP_);
6155 gcc_assert (innerc);
6156 n2 = OMP_CLAUSE_DECL (innerc);
6158 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6159 true, NULL_TREE, true, GSI_SAME_STMT);
6160 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6161 true, NULL_TREE, true, GSI_SAME_STMT);
6162 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6163 true, NULL_TREE, true, GSI_SAME_STMT);
6165 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6166 t = fold_build2 (PLUS_EXPR, itype, step, t);
6167 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6168 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6169 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6170 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6171 fold_build1 (NEGATE_EXPR, itype, t),
6172 fold_build1 (NEGATE_EXPR, itype, step));
6173 else
6174 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6175 t = fold_convert (itype, t);
6176 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6178 q = create_tmp_reg (itype, "q");
6179 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6180 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6181 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6183 tt = create_tmp_reg (itype, "tt");
6184 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6185 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6186 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6188 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6189 stmt = gimple_build_cond_empty (t);
6190 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6192 second_bb = split_block (entry_bb, stmt)->dest;
6193 gsi = gsi_last_bb (second_bb);
6194 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6196 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6197 GSI_SAME_STMT);
6198 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
6199 build_int_cst (itype, 1));
6200 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6202 third_bb = split_block (second_bb, stmt)->dest;
6203 gsi = gsi_last_bb (third_bb);
6204 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6206 t = build2 (MULT_EXPR, itype, q, threadid);
6207 t = build2 (PLUS_EXPR, itype, t, tt);
6208 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6210 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6211 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6213 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6214 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6216 /* Remove the GIMPLE_OMP_FOR statement. */
6217 gsi_remove (&gsi, true);
6219 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6220 gsi = gsi_start_bb (seq_start_bb);
6222 tree startvar = fd->loop.v;
6223 tree endvar = NULL_TREE;
6225 if (gimple_omp_for_combined_p (fd->for_stmt))
6227 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6228 ? gimple_omp_parallel_clauses (inner_stmt)
6229 : gimple_omp_for_clauses (inner_stmt);
6230 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6231 gcc_assert (innerc);
6232 startvar = OMP_CLAUSE_DECL (innerc);
6233 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6234 OMP_CLAUSE__LOOPTEMP_);
6235 gcc_assert (innerc);
6236 endvar = OMP_CLAUSE_DECL (innerc);
6238 t = fold_convert (itype, s0);
6239 t = fold_build2 (MULT_EXPR, itype, t, step);
6240 if (POINTER_TYPE_P (type))
6241 t = fold_build_pointer_plus (n1, t);
6242 else
6243 t = fold_build2 (PLUS_EXPR, type, t, n1);
6244 t = fold_convert (TREE_TYPE (startvar), t);
6245 t = force_gimple_operand_gsi (&gsi, t,
6246 DECL_P (startvar)
6247 && TREE_ADDRESSABLE (startvar),
6248 NULL_TREE, false, GSI_CONTINUE_LINKING);
6249 stmt = gimple_build_assign (startvar, t);
6250 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6252 t = fold_convert (itype, e0);
6253 t = fold_build2 (MULT_EXPR, itype, t, step);
6254 if (POINTER_TYPE_P (type))
6255 t = fold_build_pointer_plus (n1, t);
6256 else
6257 t = fold_build2 (PLUS_EXPR, type, t, n1);
6258 t = fold_convert (TREE_TYPE (startvar), t);
6259 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6260 false, GSI_CONTINUE_LINKING);
6261 if (endvar)
6263 stmt = gimple_build_assign (endvar, e);
6264 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6265 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6266 stmt = gimple_build_assign (fd->loop.v, e);
6267 else
6268 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6269 NULL_TREE);
6270 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6272 if (fd->collapse > 1)
6273 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6275 if (!broken_loop)
6277 /* The code controlling the sequential loop replaces the
6278 GIMPLE_OMP_CONTINUE. */
6279 gsi = gsi_last_bb (cont_bb);
6280 stmt = gsi_stmt (gsi);
6281 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6282 vmain = gimple_omp_continue_control_use (stmt);
6283 vback = gimple_omp_continue_control_def (stmt);
6285 if (!gimple_omp_for_combined_p (fd->for_stmt))
6287 if (POINTER_TYPE_P (type))
6288 t = fold_build_pointer_plus (vmain, step);
6289 else
6290 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6291 t = force_gimple_operand_gsi (&gsi, t,
6292 DECL_P (vback)
6293 && TREE_ADDRESSABLE (vback),
6294 NULL_TREE, true, GSI_SAME_STMT);
6295 stmt = gimple_build_assign (vback, t);
6296 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6298 t = build2 (fd->loop.cond_code, boolean_type_node,
6299 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6300 ? t : vback, e);
6301 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6304 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6305 gsi_remove (&gsi, true);
6307 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6308 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6311 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6312 gsi = gsi_last_bb (exit_bb);
6313 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6315 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6316 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6318 gsi_remove (&gsi, true);
6320 /* Connect all the blocks. */
6321 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6322 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6323 ep = find_edge (entry_bb, second_bb);
6324 ep->flags = EDGE_TRUE_VALUE;
6325 ep->probability = REG_BR_PROB_BASE / 4;
6326 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6327 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6329 if (!broken_loop)
6331 ep = find_edge (cont_bb, body_bb);
6332 if (gimple_omp_for_combined_p (fd->for_stmt))
6334 remove_edge (ep);
6335 ep = NULL;
6337 else if (fd->collapse > 1)
6339 remove_edge (ep);
6340 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6342 else
6343 ep->flags = EDGE_TRUE_VALUE;
6344 find_edge (cont_bb, fin_bb)->flags
6345 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6348 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6349 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6350 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6352 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6353 recompute_dominator (CDI_DOMINATORS, body_bb));
6354 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6355 recompute_dominator (CDI_DOMINATORS, fin_bb));
6357 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6359 struct loop *loop = alloc_loop ();
6360 loop->header = body_bb;
6361 if (collapse_bb == NULL)
6362 loop->latch = cont_bb;
6363 add_loop (loop, body_bb->loop_father);
6368 /* A subroutine of expand_omp_for. Generate code for a parallel
6369 loop with static schedule and a specified chunk size. Given
6370 parameters:
6372 for (V = N1; V cond N2; V += STEP) BODY;
6374 where COND is "<" or ">", we generate pseudocode
6376 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6377 if (cond is <)
6378 adj = STEP - 1;
6379 else
6380 adj = STEP + 1;
6381 if ((__typeof (V)) -1 > 0 && cond is >)
6382 n = -(adj + N2 - N1) / -STEP;
6383 else
6384 n = (adj + N2 - N1) / STEP;
6385 trip = 0;
6386 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6387 here so that V is defined
6388 if the loop is not entered
6390 s0 = (trip * nthreads + threadid) * CHUNK;
6391 e0 = min(s0 + CHUNK, n);
6392 if (s0 < n) goto L1; else goto L4;
6394 V = s0 * STEP + N1;
6395 e = e0 * STEP + N1;
6397 BODY;
6398 V += STEP;
6399 if (V cond e) goto L2; else goto L3;
6401 trip += 1;
6402 goto L0;
6406 static void
6407 expand_omp_for_static_chunk (struct omp_region *region,
6408 struct omp_for_data *fd, gimple inner_stmt)
6410 tree n, s0, e0, e, t;
6411 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6412 tree type, itype, vmain, vback, vextra;
6413 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6414 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6415 gimple_stmt_iterator gsi;
6416 gimple stmt;
6417 edge se;
6418 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6419 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6420 bool broken_loop = region->cont == NULL;
6421 tree *counts = NULL;
6422 tree n1, n2, step;
6424 itype = type = TREE_TYPE (fd->loop.v);
6425 if (POINTER_TYPE_P (type))
6426 itype = signed_type_for (type);
6428 entry_bb = region->entry;
6429 se = split_block (entry_bb, last_stmt (entry_bb));
6430 entry_bb = se->src;
6431 iter_part_bb = se->dest;
6432 cont_bb = region->cont;
6433 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6434 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6435 gcc_assert (broken_loop
6436 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6437 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6438 body_bb = single_succ (seq_start_bb);
6439 if (!broken_loop)
6441 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6442 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6443 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6445 exit_bb = region->exit;
6447 /* Trip and adjustment setup goes in ENTRY_BB. */
6448 gsi = gsi_last_bb (entry_bb);
6449 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6451 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6453 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6454 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6457 if (fd->collapse > 1)
6459 int first_zero_iter = -1;
6460 basic_block l2_dom_bb = NULL;
6462 counts = XALLOCAVEC (tree, fd->collapse);
6463 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6464 fin_bb, first_zero_iter,
6465 l2_dom_bb);
6466 t = NULL_TREE;
6468 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6469 t = integer_one_node;
6470 else
6471 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6472 fold_convert (type, fd->loop.n1),
6473 fold_convert (type, fd->loop.n2));
6474 if (fd->collapse == 1
6475 && TYPE_UNSIGNED (type)
6476 && (t == NULL_TREE || !integer_onep (t)))
6478 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6479 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6480 true, GSI_SAME_STMT);
6481 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6482 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6483 true, GSI_SAME_STMT);
6484 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6485 NULL_TREE, NULL_TREE);
6486 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6487 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6488 expand_omp_regimplify_p, NULL, NULL)
6489 || walk_tree (gimple_cond_rhs_ptr (stmt),
6490 expand_omp_regimplify_p, NULL, NULL))
6492 gsi = gsi_for_stmt (stmt);
6493 gimple_regimplify_operands (stmt, &gsi);
6495 se = split_block (entry_bb, stmt);
6496 se->flags = EDGE_TRUE_VALUE;
6497 entry_bb = se->dest;
6498 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6499 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6500 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6501 if (gimple_in_ssa_p (cfun))
6503 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6504 for (gsi = gsi_start_phis (fin_bb);
6505 !gsi_end_p (gsi); gsi_next (&gsi))
6507 gimple phi = gsi_stmt (gsi);
6508 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6509 se, UNKNOWN_LOCATION);
6512 gsi = gsi_last_bb (entry_bb);
6515 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6516 t = fold_convert (itype, t);
6517 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6518 true, GSI_SAME_STMT);
6520 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6521 t = fold_convert (itype, t);
6522 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6523 true, GSI_SAME_STMT);
6525 n1 = fd->loop.n1;
6526 n2 = fd->loop.n2;
6527 step = fd->loop.step;
6528 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6530 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6531 OMP_CLAUSE__LOOPTEMP_);
6532 gcc_assert (innerc);
6533 n1 = OMP_CLAUSE_DECL (innerc);
6534 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6535 OMP_CLAUSE__LOOPTEMP_);
6536 gcc_assert (innerc);
6537 n2 = OMP_CLAUSE_DECL (innerc);
6539 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6540 true, NULL_TREE, true, GSI_SAME_STMT);
6541 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6542 true, NULL_TREE, true, GSI_SAME_STMT);
6543 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6544 true, NULL_TREE, true, GSI_SAME_STMT);
6545 fd->chunk_size
6546 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
6547 true, NULL_TREE, true, GSI_SAME_STMT);
6549 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6550 t = fold_build2 (PLUS_EXPR, itype, step, t);
6551 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6552 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6553 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6554 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6555 fold_build1 (NEGATE_EXPR, itype, t),
6556 fold_build1 (NEGATE_EXPR, itype, step));
6557 else
6558 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6559 t = fold_convert (itype, t);
6560 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6561 true, GSI_SAME_STMT);
6563 trip_var = create_tmp_reg (itype, ".trip");
6564 if (gimple_in_ssa_p (cfun))
6566 trip_init = make_ssa_name (trip_var, NULL);
6567 trip_main = make_ssa_name (trip_var, NULL);
6568 trip_back = make_ssa_name (trip_var, NULL);
6570 else
6572 trip_init = trip_var;
6573 trip_main = trip_var;
6574 trip_back = trip_var;
6577 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6578 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6580 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6581 t = fold_build2 (MULT_EXPR, itype, t, step);
6582 if (POINTER_TYPE_P (type))
6583 t = fold_build_pointer_plus (n1, t);
6584 else
6585 t = fold_build2 (PLUS_EXPR, type, t, n1);
6586 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6587 true, GSI_SAME_STMT);
6589 /* Remove the GIMPLE_OMP_FOR. */
6590 gsi_remove (&gsi, true);
6592 /* Iteration space partitioning goes in ITER_PART_BB. */
6593 gsi = gsi_last_bb (iter_part_bb);
6595 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6596 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6597 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6598 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6599 false, GSI_CONTINUE_LINKING);
6601 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6602 t = fold_build2 (MIN_EXPR, itype, t, n);
6603 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6604 false, GSI_CONTINUE_LINKING);
6606 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6607 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6609 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6610 gsi = gsi_start_bb (seq_start_bb);
6612 tree startvar = fd->loop.v;
6613 tree endvar = NULL_TREE;
6615 if (gimple_omp_for_combined_p (fd->for_stmt))
6617 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6618 ? gimple_omp_parallel_clauses (inner_stmt)
6619 : gimple_omp_for_clauses (inner_stmt);
6620 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6621 gcc_assert (innerc);
6622 startvar = OMP_CLAUSE_DECL (innerc);
6623 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6624 OMP_CLAUSE__LOOPTEMP_);
6625 gcc_assert (innerc);
6626 endvar = OMP_CLAUSE_DECL (innerc);
6629 t = fold_convert (itype, s0);
6630 t = fold_build2 (MULT_EXPR, itype, t, step);
6631 if (POINTER_TYPE_P (type))
6632 t = fold_build_pointer_plus (n1, t);
6633 else
6634 t = fold_build2 (PLUS_EXPR, type, t, n1);
6635 t = fold_convert (TREE_TYPE (startvar), t);
6636 t = force_gimple_operand_gsi (&gsi, t,
6637 DECL_P (startvar)
6638 && TREE_ADDRESSABLE (startvar),
6639 NULL_TREE, false, GSI_CONTINUE_LINKING);
6640 stmt = gimple_build_assign (startvar, t);
6641 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6643 t = fold_convert (itype, e0);
6644 t = fold_build2 (MULT_EXPR, itype, t, step);
6645 if (POINTER_TYPE_P (type))
6646 t = fold_build_pointer_plus (n1, t);
6647 else
6648 t = fold_build2 (PLUS_EXPR, type, t, n1);
6649 t = fold_convert (TREE_TYPE (startvar), t);
6650 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6651 false, GSI_CONTINUE_LINKING);
6652 if (endvar)
6654 stmt = gimple_build_assign (endvar, e);
6655 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6656 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6657 stmt = gimple_build_assign (fd->loop.v, e);
6658 else
6659 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6660 NULL_TREE);
6661 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6663 if (fd->collapse > 1)
6664 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6666 if (!broken_loop)
6668 /* The code controlling the sequential loop goes in CONT_BB,
6669 replacing the GIMPLE_OMP_CONTINUE. */
6670 gsi = gsi_last_bb (cont_bb);
6671 stmt = gsi_stmt (gsi);
6672 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6673 vmain = gimple_omp_continue_control_use (stmt);
6674 vback = gimple_omp_continue_control_def (stmt);
6676 if (!gimple_omp_for_combined_p (fd->for_stmt))
6678 if (POINTER_TYPE_P (type))
6679 t = fold_build_pointer_plus (vmain, step);
6680 else
6681 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6682 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
6683 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6684 true, GSI_SAME_STMT);
6685 stmt = gimple_build_assign (vback, t);
6686 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6688 t = build2 (fd->loop.cond_code, boolean_type_node,
6689 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6690 ? t : vback, e);
6691 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6694 /* Remove GIMPLE_OMP_CONTINUE. */
6695 gsi_remove (&gsi, true);
6697 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6698 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6700 /* Trip update code goes into TRIP_UPDATE_BB. */
6701 gsi = gsi_start_bb (trip_update_bb);
6703 t = build_int_cst (itype, 1);
6704 t = build2 (PLUS_EXPR, itype, trip_main, t);
6705 stmt = gimple_build_assign (trip_back, t);
6706 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6709 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6710 gsi = gsi_last_bb (exit_bb);
6711 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6713 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6714 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6716 gsi_remove (&gsi, true);
6718 /* Connect the new blocks. */
6719 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6720 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6722 if (!broken_loop)
6724 se = find_edge (cont_bb, body_bb);
6725 if (gimple_omp_for_combined_p (fd->for_stmt))
6727 remove_edge (se);
6728 se = NULL;
6730 else if (fd->collapse > 1)
6732 remove_edge (se);
6733 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6735 else
6736 se->flags = EDGE_TRUE_VALUE;
6737 find_edge (cont_bb, trip_update_bb)->flags
6738 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6740 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6743 if (gimple_in_ssa_p (cfun))
6745 gimple_stmt_iterator psi;
6746 gimple phi;
6747 edge re, ene;
6748 edge_var_map *vm;
6749 size_t i;
6751 gcc_assert (fd->collapse == 1 && !broken_loop);
6753 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6754 remove arguments of the phi nodes in fin_bb. We need to create
6755 appropriate phi nodes in iter_part_bb instead. */
6756 se = single_pred_edge (fin_bb);
6757 re = single_succ_edge (trip_update_bb);
6758 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
6759 ene = single_succ_edge (entry_bb);
6761 psi = gsi_start_phis (fin_bb);
6762 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6763 gsi_next (&psi), ++i)
6765 gimple nphi;
6766 source_location locus;
6768 phi = gsi_stmt (psi);
6769 t = gimple_phi_result (phi);
6770 gcc_assert (t == redirect_edge_var_map_result (vm));
6771 nphi = create_phi_node (t, iter_part_bb);
6773 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6774 locus = gimple_phi_arg_location_from_edge (phi, se);
6776 /* A special case -- fd->loop.v is not yet computed in
6777 iter_part_bb, we need to use vextra instead. */
6778 if (t == fd->loop.v)
6779 t = vextra;
6780 add_phi_arg (nphi, t, ene, locus);
6781 locus = redirect_edge_var_map_location (vm);
6782 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6784 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6785 redirect_edge_var_map_clear (re);
6786 while (1)
6788 psi = gsi_start_phis (fin_bb);
6789 if (gsi_end_p (psi))
6790 break;
6791 remove_phi_node (&psi, false);
6794 /* Make phi node for trip. */
6795 phi = create_phi_node (trip_main, iter_part_bb);
6796 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6797 UNKNOWN_LOCATION);
6798 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6799 UNKNOWN_LOCATION);
6802 if (!broken_loop)
6803 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6804 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6805 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6806 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6807 recompute_dominator (CDI_DOMINATORS, fin_bb));
6808 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6809 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6810 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6811 recompute_dominator (CDI_DOMINATORS, body_bb));
6813 if (!broken_loop)
6815 struct loop *trip_loop = alloc_loop ();
6816 trip_loop->header = iter_part_bb;
6817 trip_loop->latch = trip_update_bb;
6818 add_loop (trip_loop, iter_part_bb->loop_father);
6820 if (!gimple_omp_for_combined_p (fd->for_stmt))
6822 struct loop *loop = alloc_loop ();
6823 loop->header = body_bb;
6824 if (collapse_bb == NULL)
6825 loop->latch = cont_bb;
6826 add_loop (loop, trip_loop);
6831 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
6832 Given parameters:
6833 for (V = N1; V cond N2; V += STEP) BODY;
6835 where COND is "<" or ">" or "!=", we generate pseudocode
6837 for (ind_var = low; ind_var < high; ind_var++)
6839 V = n1 + (ind_var * STEP)
6841 <BODY>
6844 In the above pseudocode, low and high are function parameters of the
6845 child function. In the function below, we are inserting a temp.
6846 variable that will be making a call to two OMP functions that will not be
6847 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
6848 with _Cilk_for). These functions are replaced with low and high
6849 by the function that handles taskreg. */
6852 static void
6853 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
6855 bool broken_loop = region->cont == NULL;
6856 basic_block entry_bb = region->entry;
6857 basic_block cont_bb = region->cont;
6859 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6860 gcc_assert (broken_loop
6861 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6862 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6863 basic_block l1_bb, l2_bb;
6865 if (!broken_loop)
6867 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6868 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6869 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6870 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6872 else
6874 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6875 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6876 l2_bb = single_succ (l1_bb);
6878 basic_block exit_bb = region->exit;
6879 basic_block l2_dom_bb = NULL;
6881 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
6883 /* Below statements until the "tree high_val = ..." are pseudo statements
6884 used to pass information to be used by expand_omp_taskreg.
6885 low_val and high_val will be replaced by the __low and __high
6886 parameter from the child function.
6888 The call_exprs part is a place-holder, it is mainly used
6889 to distinctly identify to the top-level part that this is
6890 where we should put low and high (reasoning given in header
6891 comment). */
6893 tree child_fndecl
6894 = gimple_omp_parallel_child_fn (last_stmt (region->outer->entry));
6895 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
6896 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
6898 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
6899 high_val = t;
6900 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
6901 low_val = t;
6903 gcc_assert (low_val && high_val);
6905 tree type = TREE_TYPE (low_val);
6906 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
6907 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6909 /* Not needed in SSA form right now. */
6910 gcc_assert (!gimple_in_ssa_p (cfun));
6911 if (l2_dom_bb == NULL)
6912 l2_dom_bb = l1_bb;
6914 tree n1 = low_val;
6915 tree n2 = high_val;
6917 gimple stmt = gimple_build_assign (ind_var, n1);
6919 /* Replace the GIMPLE_OMP_FOR statement. */
6920 gsi_replace (&gsi, stmt, true);
6922 if (!broken_loop)
6924 /* Code to control the increment goes in the CONT_BB. */
6925 gsi = gsi_last_bb (cont_bb);
6926 stmt = gsi_stmt (gsi);
6927 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6928 stmt = gimple_build_assign_with_ops (PLUS_EXPR, ind_var, ind_var,
6929 build_one_cst (type));
6931 /* Replace GIMPLE_OMP_CONTINUE. */
6932 gsi_replace (&gsi, stmt, true);
6935 /* Emit the condition in L1_BB. */
6936 gsi = gsi_after_labels (l1_bb);
6937 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
6938 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
6939 fd->loop.step);
6940 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
6941 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6942 fd->loop.n1, fold_convert (sizetype, t));
6943 else
6944 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6945 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
6946 t = fold_convert (TREE_TYPE (fd->loop.v), t);
6947 expand_omp_build_assign (&gsi, fd->loop.v, t);
6949 /* The condition is always '<' since the runtime will fill in the low
6950 and high values. */
6951 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
6952 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6954 /* Remove GIMPLE_OMP_RETURN. */
6955 gsi = gsi_last_bb (exit_bb);
6956 gsi_remove (&gsi, true);
6958 /* Connect the new blocks. */
6959 remove_edge (FALLTHRU_EDGE (entry_bb));
6961 edge e, ne;
6962 if (!broken_loop)
6964 remove_edge (BRANCH_EDGE (entry_bb));
6965 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6967 e = BRANCH_EDGE (l1_bb);
6968 ne = FALLTHRU_EDGE (l1_bb);
6969 e->flags = EDGE_TRUE_VALUE;
6971 else
6973 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6975 ne = single_succ_edge (l1_bb);
6976 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6979 ne->flags = EDGE_FALSE_VALUE;
6980 e->probability = REG_BR_PROB_BASE * 7 / 8;
6981 ne->probability = REG_BR_PROB_BASE / 8;
6983 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6984 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6985 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6987 if (!broken_loop)
6989 struct loop *loop = alloc_loop ();
6990 loop->header = l1_bb;
6991 loop->latch = cont_bb;
6992 add_loop (loop, l1_bb->loop_father);
6993 loop->safelen = INT_MAX;
6996 /* Pick the correct library function based on the precision of the
6997 induction variable type. */
6998 tree lib_fun = NULL_TREE;
6999 if (TYPE_PRECISION (type) == 32)
7000 lib_fun = cilk_for_32_fndecl;
7001 else if (TYPE_PRECISION (type) == 64)
7002 lib_fun = cilk_for_64_fndecl;
7003 else
7004 gcc_unreachable ();
7006 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7008 /* WS_ARGS contains the library function flavor to call:
7009 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7010 user-defined grain value. If the user does not define one, then zero
7011 is passed in by the parser. */
7012 vec_alloc (region->ws_args, 2);
7013 region->ws_args->quick_push (lib_fun);
7014 region->ws_args->quick_push (fd->chunk_size);
7017 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7018 loop. Given parameters:
7020 for (V = N1; V cond N2; V += STEP) BODY;
7022 where COND is "<" or ">", we generate pseudocode
7024 V = N1;
7025 goto L1;
7027 BODY;
7028 V += STEP;
7030 if (V cond N2) goto L0; else goto L2;
7033 For collapsed loops, given parameters:
7034 collapse(3)
7035 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7036 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7037 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7038 BODY;
7040 we generate pseudocode
7042 if (cond3 is <)
7043 adj = STEP3 - 1;
7044 else
7045 adj = STEP3 + 1;
7046 count3 = (adj + N32 - N31) / STEP3;
7047 if (cond2 is <)
7048 adj = STEP2 - 1;
7049 else
7050 adj = STEP2 + 1;
7051 count2 = (adj + N22 - N21) / STEP2;
7052 if (cond1 is <)
7053 adj = STEP1 - 1;
7054 else
7055 adj = STEP1 + 1;
7056 count1 = (adj + N12 - N11) / STEP1;
7057 count = count1 * count2 * count3;
7058 V = 0;
7059 V1 = N11;
7060 V2 = N21;
7061 V3 = N31;
7062 goto L1;
7064 BODY;
7065 V += 1;
7066 V3 += STEP3;
7067 V2 += (V3 cond3 N32) ? 0 : STEP2;
7068 V3 = (V3 cond3 N32) ? V3 : N31;
7069 V1 += (V2 cond2 N22) ? 0 : STEP1;
7070 V2 = (V2 cond2 N22) ? V2 : N21;
7072 if (V < count) goto L0; else goto L2;
7077 static void
7078 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7080 tree type, t;
7081 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7082 gimple_stmt_iterator gsi;
7083 gimple stmt;
7084 bool broken_loop = region->cont == NULL;
7085 edge e, ne;
7086 tree *counts = NULL;
7087 int i;
7088 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7089 OMP_CLAUSE_SAFELEN);
7090 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7091 OMP_CLAUSE__SIMDUID_);
7092 tree n1, n2;
7094 type = TREE_TYPE (fd->loop.v);
7095 entry_bb = region->entry;
7096 cont_bb = region->cont;
7097 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7098 gcc_assert (broken_loop
7099 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7100 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7101 if (!broken_loop)
7103 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7104 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7105 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7106 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7108 else
7110 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7111 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7112 l2_bb = single_succ (l1_bb);
7114 exit_bb = region->exit;
7115 l2_dom_bb = NULL;
7117 gsi = gsi_last_bb (entry_bb);
7119 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7120 /* Not needed in SSA form right now. */
7121 gcc_assert (!gimple_in_ssa_p (cfun));
7122 if (fd->collapse > 1)
7124 int first_zero_iter = -1;
7125 basic_block zero_iter_bb = l2_bb;
7127 counts = XALLOCAVEC (tree, fd->collapse);
7128 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7129 zero_iter_bb, first_zero_iter,
7130 l2_dom_bb);
7132 if (l2_dom_bb == NULL)
7133 l2_dom_bb = l1_bb;
7135 n1 = fd->loop.n1;
7136 n2 = fd->loop.n2;
7137 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7139 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7140 OMP_CLAUSE__LOOPTEMP_);
7141 gcc_assert (innerc);
7142 n1 = OMP_CLAUSE_DECL (innerc);
7143 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7144 OMP_CLAUSE__LOOPTEMP_);
7145 gcc_assert (innerc);
7146 n2 = OMP_CLAUSE_DECL (innerc);
7147 expand_omp_build_assign (&gsi, fd->loop.v,
7148 fold_convert (type, n1));
7149 if (fd->collapse > 1)
7151 gsi_prev (&gsi);
7152 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7153 gsi_next (&gsi);
7156 else
7158 expand_omp_build_assign (&gsi, fd->loop.v,
7159 fold_convert (type, fd->loop.n1));
7160 if (fd->collapse > 1)
7161 for (i = 0; i < fd->collapse; i++)
7163 tree itype = TREE_TYPE (fd->loops[i].v);
7164 if (POINTER_TYPE_P (itype))
7165 itype = signed_type_for (itype);
7166 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7167 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7171 /* Remove the GIMPLE_OMP_FOR statement. */
7172 gsi_remove (&gsi, true);
7174 if (!broken_loop)
7176 /* Code to control the increment goes in the CONT_BB. */
7177 gsi = gsi_last_bb (cont_bb);
7178 stmt = gsi_stmt (gsi);
7179 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7181 if (POINTER_TYPE_P (type))
7182 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7183 else
7184 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7185 expand_omp_build_assign (&gsi, fd->loop.v, t);
7187 if (fd->collapse > 1)
7189 i = fd->collapse - 1;
7190 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7192 t = fold_convert (sizetype, fd->loops[i].step);
7193 t = fold_build_pointer_plus (fd->loops[i].v, t);
7195 else
7197 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7198 fd->loops[i].step);
7199 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7200 fd->loops[i].v, t);
7202 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7204 for (i = fd->collapse - 1; i > 0; i--)
7206 tree itype = TREE_TYPE (fd->loops[i].v);
7207 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7208 if (POINTER_TYPE_P (itype2))
7209 itype2 = signed_type_for (itype2);
7210 t = build3 (COND_EXPR, itype2,
7211 build2 (fd->loops[i].cond_code, boolean_type_node,
7212 fd->loops[i].v,
7213 fold_convert (itype, fd->loops[i].n2)),
7214 build_int_cst (itype2, 0),
7215 fold_convert (itype2, fd->loops[i - 1].step));
7216 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7217 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7218 else
7219 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7220 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7222 t = build3 (COND_EXPR, itype,
7223 build2 (fd->loops[i].cond_code, boolean_type_node,
7224 fd->loops[i].v,
7225 fold_convert (itype, fd->loops[i].n2)),
7226 fd->loops[i].v,
7227 fold_convert (itype, fd->loops[i].n1));
7228 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7232 /* Remove GIMPLE_OMP_CONTINUE. */
7233 gsi_remove (&gsi, true);
7236 /* Emit the condition in L1_BB. */
7237 gsi = gsi_start_bb (l1_bb);
7239 t = fold_convert (type, n2);
7240 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7241 false, GSI_CONTINUE_LINKING);
7242 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7243 stmt = gimple_build_cond_empty (t);
7244 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7245 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
7246 NULL, NULL)
7247 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
7248 NULL, NULL))
7250 gsi = gsi_for_stmt (stmt);
7251 gimple_regimplify_operands (stmt, &gsi);
7254 /* Remove GIMPLE_OMP_RETURN. */
7255 gsi = gsi_last_bb (exit_bb);
7256 gsi_remove (&gsi, true);
7258 /* Connect the new blocks. */
7259 remove_edge (FALLTHRU_EDGE (entry_bb));
7261 if (!broken_loop)
7263 remove_edge (BRANCH_EDGE (entry_bb));
7264 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7266 e = BRANCH_EDGE (l1_bb);
7267 ne = FALLTHRU_EDGE (l1_bb);
7268 e->flags = EDGE_TRUE_VALUE;
7270 else
7272 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7274 ne = single_succ_edge (l1_bb);
7275 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7278 ne->flags = EDGE_FALSE_VALUE;
7279 e->probability = REG_BR_PROB_BASE * 7 / 8;
7280 ne->probability = REG_BR_PROB_BASE / 8;
7282 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7283 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7284 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7286 if (!broken_loop)
7288 struct loop *loop = alloc_loop ();
7289 loop->header = l1_bb;
7290 loop->latch = cont_bb;
7291 add_loop (loop, l1_bb->loop_father);
7292 if (safelen == NULL_TREE)
7293 loop->safelen = INT_MAX;
7294 else
7296 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7297 if (TREE_CODE (safelen) != INTEGER_CST)
7298 loop->safelen = 0;
7299 else if (!tree_fits_uhwi_p (safelen)
7300 || tree_to_uhwi (safelen) > INT_MAX)
7301 loop->safelen = INT_MAX;
7302 else
7303 loop->safelen = tree_to_uhwi (safelen);
7304 if (loop->safelen == 1)
7305 loop->safelen = 0;
7307 if (simduid)
7309 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7310 cfun->has_simduid_loops = true;
7312 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7313 the loop. */
7314 if ((flag_tree_loop_vectorize
7315 || (!global_options_set.x_flag_tree_loop_vectorize
7316 && !global_options_set.x_flag_tree_vectorize))
7317 && flag_tree_loop_optimize
7318 && loop->safelen > 1)
7320 loop->force_vectorize = true;
7321 cfun->has_force_vectorize_loops = true;
7327 /* Expand the OpenMP loop defined by REGION. */
7329 static void
7330 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7332 struct omp_for_data fd;
7333 struct omp_for_data_loop *loops;
7335 loops
7336 = (struct omp_for_data_loop *)
7337 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7338 * sizeof (struct omp_for_data_loop));
7339 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
7340 region->sched_kind = fd.sched_kind;
7342 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7343 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7344 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7345 if (region->cont)
7347 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7348 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7349 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7351 else
7352 /* If there isn't a continue then this is a degerate case where
7353 the introduction of abnormal edges during lowering will prevent
7354 original loops from being detected. Fix that up. */
7355 loops_state_set (LOOPS_NEED_FIXUP);
7357 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7358 expand_omp_simd (region, &fd);
7359 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7360 expand_cilk_for (region, &fd);
7361 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7362 && !fd.have_ordered)
7364 if (fd.chunk_size == NULL)
7365 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7366 else
7367 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7369 else
7371 int fn_index, start_ix, next_ix;
7373 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7374 == GF_OMP_FOR_KIND_FOR);
7375 if (fd.chunk_size == NULL
7376 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7377 fd.chunk_size = integer_zero_node;
7378 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7379 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7380 ? 3 : fd.sched_kind;
7381 fn_index += fd.have_ordered * 4;
7382 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7383 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7384 if (fd.iter_type == long_long_unsigned_type_node)
7386 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7387 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7388 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7389 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7391 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7392 (enum built_in_function) next_ix, inner_stmt);
7395 if (gimple_in_ssa_p (cfun))
7396 update_ssa (TODO_update_ssa_only_virtuals);
7400 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7402 v = GOMP_sections_start (n);
7404 switch (v)
7406 case 0:
7407 goto L2;
7408 case 1:
7409 section 1;
7410 goto L1;
7411 case 2:
7413 case n:
7415 default:
7416 abort ();
7419 v = GOMP_sections_next ();
7420 goto L0;
7422 reduction;
7424 If this is a combined parallel sections, replace the call to
7425 GOMP_sections_start with call to GOMP_sections_next. */
7427 static void
7428 expand_omp_sections (struct omp_region *region)
7430 tree t, u, vin = NULL, vmain, vnext, l2;
7431 unsigned len;
7432 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7433 gimple_stmt_iterator si, switch_si;
7434 gimple sections_stmt, stmt, cont;
7435 edge_iterator ei;
7436 edge e;
7437 struct omp_region *inner;
7438 unsigned i, casei;
7439 bool exit_reachable = region->cont != NULL;
7441 gcc_assert (region->exit != NULL);
7442 entry_bb = region->entry;
7443 l0_bb = single_succ (entry_bb);
7444 l1_bb = region->cont;
7445 l2_bb = region->exit;
7446 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7447 l2 = gimple_block_label (l2_bb);
7448 else
7450 /* This can happen if there are reductions. */
7451 len = EDGE_COUNT (l0_bb->succs);
7452 gcc_assert (len > 0);
7453 e = EDGE_SUCC (l0_bb, len - 1);
7454 si = gsi_last_bb (e->dest);
7455 l2 = NULL_TREE;
7456 if (gsi_end_p (si)
7457 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7458 l2 = gimple_block_label (e->dest);
7459 else
7460 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7462 si = gsi_last_bb (e->dest);
7463 if (gsi_end_p (si)
7464 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7466 l2 = gimple_block_label (e->dest);
7467 break;
7471 if (exit_reachable)
7472 default_bb = create_empty_bb (l1_bb->prev_bb);
7473 else
7474 default_bb = create_empty_bb (l0_bb);
7476 /* We will build a switch() with enough cases for all the
7477 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7478 and a default case to abort if something goes wrong. */
7479 len = EDGE_COUNT (l0_bb->succs);
7481 /* Use vec::quick_push on label_vec throughout, since we know the size
7482 in advance. */
7483 auto_vec<tree> label_vec (len);
7485 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7486 GIMPLE_OMP_SECTIONS statement. */
7487 si = gsi_last_bb (entry_bb);
7488 sections_stmt = gsi_stmt (si);
7489 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7490 vin = gimple_omp_sections_control (sections_stmt);
7491 if (!is_combined_parallel (region))
7493 /* If we are not inside a combined parallel+sections region,
7494 call GOMP_sections_start. */
7495 t = build_int_cst (unsigned_type_node, len - 1);
7496 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7497 stmt = gimple_build_call (u, 1, t);
7499 else
7501 /* Otherwise, call GOMP_sections_next. */
7502 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7503 stmt = gimple_build_call (u, 0);
7505 gimple_call_set_lhs (stmt, vin);
7506 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7507 gsi_remove (&si, true);
7509 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7510 L0_BB. */
7511 switch_si = gsi_last_bb (l0_bb);
7512 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7513 if (exit_reachable)
7515 cont = last_stmt (l1_bb);
7516 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7517 vmain = gimple_omp_continue_control_use (cont);
7518 vnext = gimple_omp_continue_control_def (cont);
7520 else
7522 vmain = vin;
7523 vnext = NULL_TREE;
7526 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7527 label_vec.quick_push (t);
7528 i = 1;
7530 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7531 for (inner = region->inner, casei = 1;
7532 inner;
7533 inner = inner->next, i++, casei++)
7535 basic_block s_entry_bb, s_exit_bb;
7537 /* Skip optional reduction region. */
7538 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7540 --i;
7541 --casei;
7542 continue;
7545 s_entry_bb = inner->entry;
7546 s_exit_bb = inner->exit;
7548 t = gimple_block_label (s_entry_bb);
7549 u = build_int_cst (unsigned_type_node, casei);
7550 u = build_case_label (u, NULL, t);
7551 label_vec.quick_push (u);
7553 si = gsi_last_bb (s_entry_bb);
7554 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7555 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7556 gsi_remove (&si, true);
7557 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7559 if (s_exit_bb == NULL)
7560 continue;
7562 si = gsi_last_bb (s_exit_bb);
7563 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7564 gsi_remove (&si, true);
7566 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7569 /* Error handling code goes in DEFAULT_BB. */
7570 t = gimple_block_label (default_bb);
7571 u = build_case_label (NULL, NULL, t);
7572 make_edge (l0_bb, default_bb, 0);
7573 add_bb_to_loop (default_bb, current_loops->tree_root);
7575 stmt = gimple_build_switch (vmain, u, label_vec);
7576 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7577 gsi_remove (&switch_si, true);
7579 si = gsi_start_bb (default_bb);
7580 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7581 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7583 if (exit_reachable)
7585 tree bfn_decl;
7587 /* Code to get the next section goes in L1_BB. */
7588 si = gsi_last_bb (l1_bb);
7589 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7591 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7592 stmt = gimple_build_call (bfn_decl, 0);
7593 gimple_call_set_lhs (stmt, vnext);
7594 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7595 gsi_remove (&si, true);
7597 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7600 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7601 si = gsi_last_bb (l2_bb);
7602 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7603 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7604 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7605 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7606 else
7607 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7608 stmt = gimple_build_call (t, 0);
7609 if (gimple_omp_return_lhs (gsi_stmt (si)))
7610 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7611 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7612 gsi_remove (&si, true);
7614 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7618 /* Expand code for an OpenMP single directive. We've already expanded
7619 much of the code, here we simply place the GOMP_barrier call. */
7621 static void
7622 expand_omp_single (struct omp_region *region)
7624 basic_block entry_bb, exit_bb;
7625 gimple_stmt_iterator si;
7627 entry_bb = region->entry;
7628 exit_bb = region->exit;
7630 si = gsi_last_bb (entry_bb);
7631 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7632 gsi_remove (&si, true);
7633 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7635 si = gsi_last_bb (exit_bb);
7636 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7638 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7639 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7641 gsi_remove (&si, true);
7642 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7646 /* Generic expansion for OpenMP synchronization directives: master,
7647 ordered and critical. All we need to do here is remove the entry
7648 and exit markers for REGION. */
7650 static void
7651 expand_omp_synch (struct omp_region *region)
7653 basic_block entry_bb, exit_bb;
7654 gimple_stmt_iterator si;
7656 entry_bb = region->entry;
7657 exit_bb = region->exit;
7659 si = gsi_last_bb (entry_bb);
7660 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7661 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7662 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7663 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7664 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7665 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7666 gsi_remove (&si, true);
7667 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7669 if (exit_bb)
7671 si = gsi_last_bb (exit_bb);
7672 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7673 gsi_remove (&si, true);
7674 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7678 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7679 operation as a normal volatile load. */
7681 static bool
7682 expand_omp_atomic_load (basic_block load_bb, tree addr,
7683 tree loaded_val, int index)
7685 enum built_in_function tmpbase;
7686 gimple_stmt_iterator gsi;
7687 basic_block store_bb;
7688 location_t loc;
7689 gimple stmt;
7690 tree decl, call, type, itype;
7692 gsi = gsi_last_bb (load_bb);
7693 stmt = gsi_stmt (gsi);
7694 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7695 loc = gimple_location (stmt);
7697 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7698 is smaller than word size, then expand_atomic_load assumes that the load
7699 is atomic. We could avoid the builtin entirely in this case. */
7701 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7702 decl = builtin_decl_explicit (tmpbase);
7703 if (decl == NULL_TREE)
7704 return false;
7706 type = TREE_TYPE (loaded_val);
7707 itype = TREE_TYPE (TREE_TYPE (decl));
7709 call = build_call_expr_loc (loc, decl, 2, addr,
7710 build_int_cst (NULL,
7711 gimple_omp_atomic_seq_cst_p (stmt)
7712 ? MEMMODEL_SEQ_CST
7713 : MEMMODEL_RELAXED));
7714 if (!useless_type_conversion_p (type, itype))
7715 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7716 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7718 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7719 gsi_remove (&gsi, true);
7721 store_bb = single_succ (load_bb);
7722 gsi = gsi_last_bb (store_bb);
7723 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7724 gsi_remove (&gsi, true);
7726 if (gimple_in_ssa_p (cfun))
7727 update_ssa (TODO_update_ssa_no_phi);
7729 return true;
7732 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7733 operation as a normal volatile store. */
7735 static bool
7736 expand_omp_atomic_store (basic_block load_bb, tree addr,
7737 tree loaded_val, tree stored_val, int index)
7739 enum built_in_function tmpbase;
7740 gimple_stmt_iterator gsi;
7741 basic_block store_bb = single_succ (load_bb);
7742 location_t loc;
7743 gimple stmt;
7744 tree decl, call, type, itype;
7745 machine_mode imode;
7746 bool exchange;
7748 gsi = gsi_last_bb (load_bb);
7749 stmt = gsi_stmt (gsi);
7750 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7752 /* If the load value is needed, then this isn't a store but an exchange. */
7753 exchange = gimple_omp_atomic_need_value_p (stmt);
7755 gsi = gsi_last_bb (store_bb);
7756 stmt = gsi_stmt (gsi);
7757 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7758 loc = gimple_location (stmt);
7760 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7761 is smaller than word size, then expand_atomic_store assumes that the store
7762 is atomic. We could avoid the builtin entirely in this case. */
7764 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7765 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7766 decl = builtin_decl_explicit (tmpbase);
7767 if (decl == NULL_TREE)
7768 return false;
7770 type = TREE_TYPE (stored_val);
7772 /* Dig out the type of the function's second argument. */
7773 itype = TREE_TYPE (decl);
7774 itype = TYPE_ARG_TYPES (itype);
7775 itype = TREE_CHAIN (itype);
7776 itype = TREE_VALUE (itype);
7777 imode = TYPE_MODE (itype);
7779 if (exchange && !can_atomic_exchange_p (imode, true))
7780 return false;
7782 if (!useless_type_conversion_p (itype, type))
7783 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7784 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7785 build_int_cst (NULL,
7786 gimple_omp_atomic_seq_cst_p (stmt)
7787 ? MEMMODEL_SEQ_CST
7788 : MEMMODEL_RELAXED));
7789 if (exchange)
7791 if (!useless_type_conversion_p (type, itype))
7792 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7793 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7796 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7797 gsi_remove (&gsi, true);
7799 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7800 gsi = gsi_last_bb (load_bb);
7801 gsi_remove (&gsi, true);
7803 if (gimple_in_ssa_p (cfun))
7804 update_ssa (TODO_update_ssa_no_phi);
7806 return true;
7809 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7810 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7811 size of the data type, and thus usable to find the index of the builtin
7812 decl. Returns false if the expression is not of the proper form. */
7814 static bool
7815 expand_omp_atomic_fetch_op (basic_block load_bb,
7816 tree addr, tree loaded_val,
7817 tree stored_val, int index)
7819 enum built_in_function oldbase, newbase, tmpbase;
7820 tree decl, itype, call;
7821 tree lhs, rhs;
7822 basic_block store_bb = single_succ (load_bb);
7823 gimple_stmt_iterator gsi;
7824 gimple stmt;
7825 location_t loc;
7826 enum tree_code code;
7827 bool need_old, need_new;
7828 machine_mode imode;
7829 bool seq_cst;
7831 /* We expect to find the following sequences:
7833 load_bb:
7834 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7836 store_bb:
7837 val = tmp OP something; (or: something OP tmp)
7838 GIMPLE_OMP_STORE (val)
7840 ???FIXME: Allow a more flexible sequence.
7841 Perhaps use data flow to pick the statements.
7845 gsi = gsi_after_labels (store_bb);
7846 stmt = gsi_stmt (gsi);
7847 loc = gimple_location (stmt);
7848 if (!is_gimple_assign (stmt))
7849 return false;
7850 gsi_next (&gsi);
7851 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7852 return false;
7853 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7854 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7855 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7856 gcc_checking_assert (!need_old || !need_new);
7858 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7859 return false;
7861 /* Check for one of the supported fetch-op operations. */
7862 code = gimple_assign_rhs_code (stmt);
7863 switch (code)
7865 case PLUS_EXPR:
7866 case POINTER_PLUS_EXPR:
7867 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7868 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7869 break;
7870 case MINUS_EXPR:
7871 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7872 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7873 break;
7874 case BIT_AND_EXPR:
7875 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7876 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7877 break;
7878 case BIT_IOR_EXPR:
7879 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7880 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7881 break;
7882 case BIT_XOR_EXPR:
7883 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7884 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7885 break;
7886 default:
7887 return false;
7890 /* Make sure the expression is of the proper form. */
7891 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7892 rhs = gimple_assign_rhs2 (stmt);
7893 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7894 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7895 rhs = gimple_assign_rhs1 (stmt);
7896 else
7897 return false;
7899 tmpbase = ((enum built_in_function)
7900 ((need_new ? newbase : oldbase) + index + 1));
7901 decl = builtin_decl_explicit (tmpbase);
7902 if (decl == NULL_TREE)
7903 return false;
7904 itype = TREE_TYPE (TREE_TYPE (decl));
7905 imode = TYPE_MODE (itype);
7907 /* We could test all of the various optabs involved, but the fact of the
7908 matter is that (with the exception of i486 vs i586 and xadd) all targets
7909 that support any atomic operaton optab also implements compare-and-swap.
7910 Let optabs.c take care of expanding any compare-and-swap loop. */
7911 if (!can_compare_and_swap_p (imode, true))
7912 return false;
7914 gsi = gsi_last_bb (load_bb);
7915 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7917 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7918 It only requires that the operation happen atomically. Thus we can
7919 use the RELAXED memory model. */
7920 call = build_call_expr_loc (loc, decl, 3, addr,
7921 fold_convert_loc (loc, itype, rhs),
7922 build_int_cst (NULL,
7923 seq_cst ? MEMMODEL_SEQ_CST
7924 : MEMMODEL_RELAXED));
7926 if (need_old || need_new)
7928 lhs = need_old ? loaded_val : stored_val;
7929 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7930 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7932 else
7933 call = fold_convert_loc (loc, void_type_node, call);
7934 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7935 gsi_remove (&gsi, true);
7937 gsi = gsi_last_bb (store_bb);
7938 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7939 gsi_remove (&gsi, true);
7940 gsi = gsi_last_bb (store_bb);
7941 gsi_remove (&gsi, true);
7943 if (gimple_in_ssa_p (cfun))
7944 update_ssa (TODO_update_ssa_no_phi);
7946 return true;
7949 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7951 oldval = *addr;
7952 repeat:
7953 newval = rhs; // with oldval replacing *addr in rhs
7954 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7955 if (oldval != newval)
7956 goto repeat;
7958 INDEX is log2 of the size of the data type, and thus usable to find the
7959 index of the builtin decl. */
7961 static bool
7962 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7963 tree addr, tree loaded_val, tree stored_val,
7964 int index)
7966 tree loadedi, storedi, initial, new_storedi, old_vali;
7967 tree type, itype, cmpxchg, iaddr;
7968 gimple_stmt_iterator si;
7969 basic_block loop_header = single_succ (load_bb);
7970 gimple phi, stmt;
7971 edge e;
7972 enum built_in_function fncode;
7974 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7975 order to use the RELAXED memory model effectively. */
7976 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7977 + index + 1);
7978 cmpxchg = builtin_decl_explicit (fncode);
7979 if (cmpxchg == NULL_TREE)
7980 return false;
7981 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7982 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7984 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7985 return false;
7987 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7988 si = gsi_last_bb (load_bb);
7989 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7991 /* For floating-point values, we'll need to view-convert them to integers
7992 so that we can perform the atomic compare and swap. Simplify the
7993 following code by always setting up the "i"ntegral variables. */
7994 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7996 tree iaddr_val;
7998 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7999 true), NULL);
8000 iaddr_val
8001 = force_gimple_operand_gsi (&si,
8002 fold_convert (TREE_TYPE (iaddr), addr),
8003 false, NULL_TREE, true, GSI_SAME_STMT);
8004 stmt = gimple_build_assign (iaddr, iaddr_val);
8005 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8006 loadedi = create_tmp_var (itype, NULL);
8007 if (gimple_in_ssa_p (cfun))
8008 loadedi = make_ssa_name (loadedi, NULL);
8010 else
8012 iaddr = addr;
8013 loadedi = loaded_val;
8016 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8017 tree loaddecl = builtin_decl_explicit (fncode);
8018 if (loaddecl)
8019 initial
8020 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8021 build_call_expr (loaddecl, 2, iaddr,
8022 build_int_cst (NULL_TREE,
8023 MEMMODEL_RELAXED)));
8024 else
8025 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8026 build_int_cst (TREE_TYPE (iaddr), 0));
8028 initial
8029 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8030 GSI_SAME_STMT);
8032 /* Move the value to the LOADEDI temporary. */
8033 if (gimple_in_ssa_p (cfun))
8035 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8036 phi = create_phi_node (loadedi, loop_header);
8037 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8038 initial);
8040 else
8041 gsi_insert_before (&si,
8042 gimple_build_assign (loadedi, initial),
8043 GSI_SAME_STMT);
8044 if (loadedi != loaded_val)
8046 gimple_stmt_iterator gsi2;
8047 tree x;
8049 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8050 gsi2 = gsi_start_bb (loop_header);
8051 if (gimple_in_ssa_p (cfun))
8053 gimple stmt;
8054 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8055 true, GSI_SAME_STMT);
8056 stmt = gimple_build_assign (loaded_val, x);
8057 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8059 else
8061 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8062 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8063 true, GSI_SAME_STMT);
8066 gsi_remove (&si, true);
8068 si = gsi_last_bb (store_bb);
8069 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8071 if (iaddr == addr)
8072 storedi = stored_val;
8073 else
8074 storedi =
8075 force_gimple_operand_gsi (&si,
8076 build1 (VIEW_CONVERT_EXPR, itype,
8077 stored_val), true, NULL_TREE, true,
8078 GSI_SAME_STMT);
8080 /* Build the compare&swap statement. */
8081 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8082 new_storedi = force_gimple_operand_gsi (&si,
8083 fold_convert (TREE_TYPE (loadedi),
8084 new_storedi),
8085 true, NULL_TREE,
8086 true, GSI_SAME_STMT);
8088 if (gimple_in_ssa_p (cfun))
8089 old_vali = loadedi;
8090 else
8092 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
8093 stmt = gimple_build_assign (old_vali, loadedi);
8094 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8096 stmt = gimple_build_assign (loadedi, new_storedi);
8097 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8100 /* Note that we always perform the comparison as an integer, even for
8101 floating point. This allows the atomic operation to properly
8102 succeed even with NaNs and -0.0. */
8103 stmt = gimple_build_cond_empty
8104 (build2 (NE_EXPR, boolean_type_node,
8105 new_storedi, old_vali));
8106 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8108 /* Update cfg. */
8109 e = single_succ_edge (store_bb);
8110 e->flags &= ~EDGE_FALLTHRU;
8111 e->flags |= EDGE_FALSE_VALUE;
8113 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8115 /* Copy the new value to loadedi (we already did that before the condition
8116 if we are not in SSA). */
8117 if (gimple_in_ssa_p (cfun))
8119 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8120 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8123 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8124 gsi_remove (&si, true);
8126 struct loop *loop = alloc_loop ();
8127 loop->header = loop_header;
8128 loop->latch = store_bb;
8129 add_loop (loop, loop_header->loop_father);
8131 if (gimple_in_ssa_p (cfun))
8132 update_ssa (TODO_update_ssa_no_phi);
8134 return true;
8137 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8139 GOMP_atomic_start ();
8140 *addr = rhs;
8141 GOMP_atomic_end ();
8143 The result is not globally atomic, but works so long as all parallel
8144 references are within #pragma omp atomic directives. According to
8145 responses received from omp@openmp.org, appears to be within spec.
8146 Which makes sense, since that's how several other compilers handle
8147 this situation as well.
8148 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8149 expanding. STORED_VAL is the operand of the matching
8150 GIMPLE_OMP_ATOMIC_STORE.
8152 We replace
8153 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8154 loaded_val = *addr;
8156 and replace
8157 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8158 *addr = stored_val;
8161 static bool
8162 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8163 tree addr, tree loaded_val, tree stored_val)
8165 gimple_stmt_iterator si;
8166 gimple stmt;
8167 tree t;
8169 si = gsi_last_bb (load_bb);
8170 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8172 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8173 t = build_call_expr (t, 0);
8174 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8176 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8177 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8178 gsi_remove (&si, true);
8180 si = gsi_last_bb (store_bb);
8181 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8183 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8184 stored_val);
8185 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8187 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8188 t = build_call_expr (t, 0);
8189 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8190 gsi_remove (&si, true);
8192 if (gimple_in_ssa_p (cfun))
8193 update_ssa (TODO_update_ssa_no_phi);
8194 return true;
8197 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8198 using expand_omp_atomic_fetch_op. If it failed, we try to
8199 call expand_omp_atomic_pipeline, and if it fails too, the
8200 ultimate fallback is wrapping the operation in a mutex
8201 (expand_omp_atomic_mutex). REGION is the atomic region built
8202 by build_omp_regions_1(). */
8204 static void
8205 expand_omp_atomic (struct omp_region *region)
8207 basic_block load_bb = region->entry, store_bb = region->exit;
8208 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
8209 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8210 tree addr = gimple_omp_atomic_load_rhs (load);
8211 tree stored_val = gimple_omp_atomic_store_val (store);
8212 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8213 HOST_WIDE_INT index;
8215 /* Make sure the type is one of the supported sizes. */
8216 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8217 index = exact_log2 (index);
8218 if (index >= 0 && index <= 4)
8220 unsigned int align = TYPE_ALIGN_UNIT (type);
8222 /* __sync builtins require strict data alignment. */
8223 if (exact_log2 (align) >= index)
8225 /* Atomic load. */
8226 if (loaded_val == stored_val
8227 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8228 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8229 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8230 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8231 return;
8233 /* Atomic store. */
8234 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8235 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8236 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8237 && store_bb == single_succ (load_bb)
8238 && first_stmt (store_bb) == store
8239 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8240 stored_val, index))
8241 return;
8243 /* When possible, use specialized atomic update functions. */
8244 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8245 && store_bb == single_succ (load_bb)
8246 && expand_omp_atomic_fetch_op (load_bb, addr,
8247 loaded_val, stored_val, index))
8248 return;
8250 /* If we don't have specialized __sync builtins, try and implement
8251 as a compare and swap loop. */
8252 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8253 loaded_val, stored_val, index))
8254 return;
8258 /* The ultimate fallback is wrapping the operation in a mutex. */
8259 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8263 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
8265 static void
8266 expand_omp_target (struct omp_region *region)
8268 basic_block entry_bb, exit_bb, new_bb;
8269 struct function *child_cfun = NULL;
8270 tree child_fn = NULL_TREE, block, t;
8271 gimple_stmt_iterator gsi;
8272 gimple entry_stmt, stmt;
8273 edge e;
8275 entry_stmt = last_stmt (region->entry);
8276 new_bb = region->entry;
8277 int kind = gimple_omp_target_kind (entry_stmt);
8278 if (kind == GF_OMP_TARGET_KIND_REGION)
8280 child_fn = gimple_omp_target_child_fn (entry_stmt);
8281 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8284 entry_bb = region->entry;
8285 exit_bb = region->exit;
8287 if (kind == GF_OMP_TARGET_KIND_REGION)
8289 unsigned srcidx, dstidx, num;
8290 struct cgraph_node *node;
8292 /* If the target region needs data sent from the parent
8293 function, then the very first statement (except possible
8294 tree profile counter updates) of the parallel body
8295 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8296 &.OMP_DATA_O is passed as an argument to the child function,
8297 we need to replace it with the argument as seen by the child
8298 function.
8300 In most cases, this will end up being the identity assignment
8301 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8302 a function call that has been inlined, the original PARM_DECL
8303 .OMP_DATA_I may have been converted into a different local
8304 variable. In which case, we need to keep the assignment. */
8305 if (gimple_omp_target_data_arg (entry_stmt))
8307 basic_block entry_succ_bb = single_succ (entry_bb);
8308 gimple_stmt_iterator gsi;
8309 tree arg;
8310 gimple tgtcopy_stmt = NULL;
8311 tree sender
8312 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
8314 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8316 gcc_assert (!gsi_end_p (gsi));
8317 stmt = gsi_stmt (gsi);
8318 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8319 continue;
8321 if (gimple_num_ops (stmt) == 2)
8323 tree arg = gimple_assign_rhs1 (stmt);
8325 /* We're ignoring the subcode because we're
8326 effectively doing a STRIP_NOPS. */
8328 if (TREE_CODE (arg) == ADDR_EXPR
8329 && TREE_OPERAND (arg, 0) == sender)
8331 tgtcopy_stmt = stmt;
8332 break;
8337 gcc_assert (tgtcopy_stmt != NULL);
8338 arg = DECL_ARGUMENTS (child_fn);
8340 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8341 gsi_remove (&gsi, true);
8344 /* Declare local variables needed in CHILD_CFUN. */
8345 block = DECL_INITIAL (child_fn);
8346 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8347 /* The gimplifier could record temporaries in target block
8348 rather than in containing function's local_decls chain,
8349 which would mean cgraph missed finalizing them. Do it now. */
8350 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8351 if (TREE_CODE (t) == VAR_DECL
8352 && TREE_STATIC (t)
8353 && !DECL_EXTERNAL (t))
8354 varpool_node::finalize_decl (t);
8355 DECL_SAVED_TREE (child_fn) = NULL;
8356 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8357 gimple_set_body (child_fn, NULL);
8358 TREE_USED (block) = 1;
8360 /* Reset DECL_CONTEXT on function arguments. */
8361 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8362 DECL_CONTEXT (t) = child_fn;
8364 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8365 so that it can be moved to the child function. */
8366 gsi = gsi_last_bb (entry_bb);
8367 stmt = gsi_stmt (gsi);
8368 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
8369 && gimple_omp_target_kind (stmt)
8370 == GF_OMP_TARGET_KIND_REGION);
8371 gsi_remove (&gsi, true);
8372 e = split_block (entry_bb, stmt);
8373 entry_bb = e->dest;
8374 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8376 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8377 if (exit_bb)
8379 gsi = gsi_last_bb (exit_bb);
8380 gcc_assert (!gsi_end_p (gsi)
8381 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8382 stmt = gimple_build_return (NULL);
8383 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8384 gsi_remove (&gsi, true);
8387 /* Move the target region into CHILD_CFUN. */
8389 block = gimple_block (entry_stmt);
8391 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8392 if (exit_bb)
8393 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8394 /* When the OMP expansion process cannot guarantee an up-to-date
8395 loop tree arrange for the child function to fixup loops. */
8396 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8397 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8399 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8400 num = vec_safe_length (child_cfun->local_decls);
8401 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8403 t = (*child_cfun->local_decls)[srcidx];
8404 if (DECL_CONTEXT (t) == cfun->decl)
8405 continue;
8406 if (srcidx != dstidx)
8407 (*child_cfun->local_decls)[dstidx] = t;
8408 dstidx++;
8410 if (dstidx != num)
8411 vec_safe_truncate (child_cfun->local_decls, dstidx);
8413 /* Inform the callgraph about the new function. */
8414 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8415 cgraph_node::add_new_function (child_fn, true);
8417 /* Add the new function to the offload table. */
8418 vec_safe_push (offload_funcs, child_fn);
8420 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8421 fixed in a following pass. */
8422 push_cfun (child_cfun);
8423 cgraph_edge::rebuild_edges ();
8425 /* Prevent IPA from removing child_fn as unreachable, since there are no
8426 refs from the parent function to child_fn in offload LTO mode. */
8427 node = cgraph_node::get (child_fn);
8428 node->mark_force_output ();
8430 /* Some EH regions might become dead, see PR34608. If
8431 pass_cleanup_cfg isn't the first pass to happen with the
8432 new child, these dead EH edges might cause problems.
8433 Clean them up now. */
8434 if (flag_exceptions)
8436 basic_block bb;
8437 bool changed = false;
8439 FOR_EACH_BB_FN (bb, cfun)
8440 changed |= gimple_purge_dead_eh_edges (bb);
8441 if (changed)
8442 cleanup_tree_cfg ();
8444 pop_cfun ();
8447 /* Emit a library call to launch the target region, or do data
8448 transfers. */
8449 tree t1, t2, t3, t4, device, cond, c, clauses;
8450 enum built_in_function start_ix;
8451 location_t clause_loc;
8453 clauses = gimple_omp_target_clauses (entry_stmt);
8455 if (kind == GF_OMP_TARGET_KIND_REGION)
8456 start_ix = BUILT_IN_GOMP_TARGET;
8457 else if (kind == GF_OMP_TARGET_KIND_DATA)
8458 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8459 else
8460 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8462 /* By default, the value of DEVICE is -1 (let runtime library choose)
8463 and there is no conditional. */
8464 cond = NULL_TREE;
8465 device = build_int_cst (integer_type_node, -1);
8467 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8468 if (c)
8469 cond = OMP_CLAUSE_IF_EXPR (c);
8471 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8472 if (c)
8474 device = OMP_CLAUSE_DEVICE_ID (c);
8475 clause_loc = OMP_CLAUSE_LOCATION (c);
8477 else
8478 clause_loc = gimple_location (entry_stmt);
8480 /* Ensure 'device' is of the correct type. */
8481 device = fold_convert_loc (clause_loc, integer_type_node, device);
8483 /* If we found the clause 'if (cond)', build
8484 (cond ? device : -2). */
8485 if (cond)
8487 cond = gimple_boolify (cond);
8489 basic_block cond_bb, then_bb, else_bb;
8490 edge e;
8491 tree tmp_var;
8493 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8494 if (kind != GF_OMP_TARGET_KIND_REGION)
8496 gsi = gsi_last_bb (new_bb);
8497 gsi_prev (&gsi);
8498 e = split_block (new_bb, gsi_stmt (gsi));
8500 else
8501 e = split_block (new_bb, NULL);
8502 cond_bb = e->src;
8503 new_bb = e->dest;
8504 remove_edge (e);
8506 then_bb = create_empty_bb (cond_bb);
8507 else_bb = create_empty_bb (then_bb);
8508 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8509 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8511 stmt = gimple_build_cond_empty (cond);
8512 gsi = gsi_last_bb (cond_bb);
8513 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8515 gsi = gsi_start_bb (then_bb);
8516 stmt = gimple_build_assign (tmp_var, device);
8517 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8519 gsi = gsi_start_bb (else_bb);
8520 stmt = gimple_build_assign (tmp_var,
8521 build_int_cst (integer_type_node, -2));
8522 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8524 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8525 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8526 add_bb_to_loop (then_bb, cond_bb->loop_father);
8527 add_bb_to_loop (else_bb, cond_bb->loop_father);
8528 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8529 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8531 device = tmp_var;
8534 gsi = gsi_last_bb (new_bb);
8535 t = gimple_omp_target_data_arg (entry_stmt);
8536 if (t == NULL)
8538 t1 = size_zero_node;
8539 t2 = build_zero_cst (ptr_type_node);
8540 t3 = t2;
8541 t4 = t2;
8543 else
8545 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8546 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8547 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8548 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8549 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8552 gimple g;
8553 /* FIXME: This will be address of
8554 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8555 symbol, as soon as the linker plugin is able to create it for us. */
8556 tree openmp_target = build_zero_cst (ptr_type_node);
8557 if (kind == GF_OMP_TARGET_KIND_REGION)
8559 tree fnaddr = build_fold_addr_expr (child_fn);
8560 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8561 device, fnaddr, openmp_target, t1, t2, t3, t4);
8563 else
8564 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8565 device, openmp_target, t1, t2, t3, t4);
8566 gimple_set_location (g, gimple_location (entry_stmt));
8567 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8568 if (kind != GF_OMP_TARGET_KIND_REGION)
8570 g = gsi_stmt (gsi);
8571 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8572 gsi_remove (&gsi, true);
8574 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8576 gsi = gsi_last_bb (region->exit);
8577 g = gsi_stmt (gsi);
8578 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8579 gsi_remove (&gsi, true);
8584 /* Expand the parallel region tree rooted at REGION. Expansion
8585 proceeds in depth-first order. Innermost regions are expanded
8586 first. This way, parallel regions that require a new function to
8587 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8588 internal dependencies in their body. */
8590 static void
8591 expand_omp (struct omp_region *region)
8593 while (region)
8595 location_t saved_location;
8596 gimple inner_stmt = NULL;
8598 /* First, determine whether this is a combined parallel+workshare
8599 region. */
8600 if (region->type == GIMPLE_OMP_PARALLEL)
8601 determine_parallel_type (region);
8603 if (region->type == GIMPLE_OMP_FOR
8604 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8605 inner_stmt = last_stmt (region->inner->entry);
8607 if (region->inner)
8608 expand_omp (region->inner);
8610 saved_location = input_location;
8611 if (gimple_has_location (last_stmt (region->entry)))
8612 input_location = gimple_location (last_stmt (region->entry));
8614 switch (region->type)
8616 case GIMPLE_OMP_PARALLEL:
8617 case GIMPLE_OMP_TASK:
8618 expand_omp_taskreg (region);
8619 break;
8621 case GIMPLE_OMP_FOR:
8622 expand_omp_for (region, inner_stmt);
8623 break;
8625 case GIMPLE_OMP_SECTIONS:
8626 expand_omp_sections (region);
8627 break;
8629 case GIMPLE_OMP_SECTION:
8630 /* Individual omp sections are handled together with their
8631 parent GIMPLE_OMP_SECTIONS region. */
8632 break;
8634 case GIMPLE_OMP_SINGLE:
8635 expand_omp_single (region);
8636 break;
8638 case GIMPLE_OMP_MASTER:
8639 case GIMPLE_OMP_TASKGROUP:
8640 case GIMPLE_OMP_ORDERED:
8641 case GIMPLE_OMP_CRITICAL:
8642 case GIMPLE_OMP_TEAMS:
8643 expand_omp_synch (region);
8644 break;
8646 case GIMPLE_OMP_ATOMIC_LOAD:
8647 expand_omp_atomic (region);
8648 break;
8650 case GIMPLE_OMP_TARGET:
8651 expand_omp_target (region);
8652 break;
8654 default:
8655 gcc_unreachable ();
8658 input_location = saved_location;
8659 region = region->next;
8664 /* Helper for build_omp_regions. Scan the dominator tree starting at
8665 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8666 true, the function ends once a single tree is built (otherwise, whole
8667 forest of OMP constructs may be built). */
8669 static void
8670 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8671 bool single_tree)
8673 gimple_stmt_iterator gsi;
8674 gimple stmt;
8675 basic_block son;
8677 gsi = gsi_last_bb (bb);
8678 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8680 struct omp_region *region;
8681 enum gimple_code code;
8683 stmt = gsi_stmt (gsi);
8684 code = gimple_code (stmt);
8685 if (code == GIMPLE_OMP_RETURN)
8687 /* STMT is the return point out of region PARENT. Mark it
8688 as the exit point and make PARENT the immediately
8689 enclosing region. */
8690 gcc_assert (parent);
8691 region = parent;
8692 region->exit = bb;
8693 parent = parent->outer;
8695 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8697 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8698 GIMPLE_OMP_RETURN, but matches with
8699 GIMPLE_OMP_ATOMIC_LOAD. */
8700 gcc_assert (parent);
8701 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8702 region = parent;
8703 region->exit = bb;
8704 parent = parent->outer;
8707 else if (code == GIMPLE_OMP_CONTINUE)
8709 gcc_assert (parent);
8710 parent->cont = bb;
8712 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8714 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8715 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8718 else if (code == GIMPLE_OMP_TARGET
8719 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8720 new_omp_region (bb, code, parent);
8721 else
8723 /* Otherwise, this directive becomes the parent for a new
8724 region. */
8725 region = new_omp_region (bb, code, parent);
8726 parent = region;
8730 if (single_tree && !parent)
8731 return;
8733 for (son = first_dom_son (CDI_DOMINATORS, bb);
8734 son;
8735 son = next_dom_son (CDI_DOMINATORS, son))
8736 build_omp_regions_1 (son, parent, single_tree);
8739 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8740 root_omp_region. */
8742 static void
8743 build_omp_regions_root (basic_block root)
8745 gcc_assert (root_omp_region == NULL);
8746 build_omp_regions_1 (root, NULL, true);
8747 gcc_assert (root_omp_region != NULL);
8750 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8752 void
8753 omp_expand_local (basic_block head)
8755 build_omp_regions_root (head);
8756 if (dump_file && (dump_flags & TDF_DETAILS))
8758 fprintf (dump_file, "\nOMP region tree\n\n");
8759 dump_omp_region (dump_file, root_omp_region, 0);
8760 fprintf (dump_file, "\n");
8763 remove_exit_barriers (root_omp_region);
8764 expand_omp (root_omp_region);
8766 free_omp_regions ();
8769 /* Scan the CFG and build a tree of OMP regions. Return the root of
8770 the OMP region tree. */
8772 static void
8773 build_omp_regions (void)
8775 gcc_assert (root_omp_region == NULL);
8776 calculate_dominance_info (CDI_DOMINATORS);
8777 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8780 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8782 static unsigned int
8783 execute_expand_omp (void)
8785 build_omp_regions ();
8787 if (!root_omp_region)
8788 return 0;
8790 if (dump_file)
8792 fprintf (dump_file, "\nOMP region tree\n\n");
8793 dump_omp_region (dump_file, root_omp_region, 0);
8794 fprintf (dump_file, "\n");
8797 remove_exit_barriers (root_omp_region);
8799 expand_omp (root_omp_region);
8801 cleanup_tree_cfg ();
8803 free_omp_regions ();
8805 return 0;
8808 /* OMP expansion -- the default pass, run before creation of SSA form. */
8810 namespace {
8812 const pass_data pass_data_expand_omp =
8814 GIMPLE_PASS, /* type */
8815 "ompexp", /* name */
8816 OPTGROUP_NONE, /* optinfo_flags */
8817 TV_NONE, /* tv_id */
8818 PROP_gimple_any, /* properties_required */
8819 PROP_gimple_eomp, /* properties_provided */
8820 0, /* properties_destroyed */
8821 0, /* todo_flags_start */
8822 0, /* todo_flags_finish */
8825 class pass_expand_omp : public gimple_opt_pass
8827 public:
8828 pass_expand_omp (gcc::context *ctxt)
8829 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8832 /* opt_pass methods: */
8833 virtual unsigned int execute (function *)
8835 bool gate = ((flag_openmp != 0 || flag_openmp_simd != 0
8836 || flag_cilkplus != 0) && !seen_error ());
8838 /* This pass always runs, to provide PROP_gimple_eomp.
8839 But there is nothing to do unless -fopenmp is given. */
8840 if (!gate)
8841 return 0;
8843 return execute_expand_omp ();
8846 }; // class pass_expand_omp
8848 } // anon namespace
8850 gimple_opt_pass *
8851 make_pass_expand_omp (gcc::context *ctxt)
8853 return new pass_expand_omp (ctxt);
8856 namespace {
8858 const pass_data pass_data_expand_omp_ssa =
8860 GIMPLE_PASS, /* type */
8861 "ompexpssa", /* name */
8862 OPTGROUP_NONE, /* optinfo_flags */
8863 TV_NONE, /* tv_id */
8864 PROP_cfg | PROP_ssa, /* properties_required */
8865 PROP_gimple_eomp, /* properties_provided */
8866 0, /* properties_destroyed */
8867 0, /* todo_flags_start */
8868 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
8871 class pass_expand_omp_ssa : public gimple_opt_pass
8873 public:
8874 pass_expand_omp_ssa (gcc::context *ctxt)
8875 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
8878 /* opt_pass methods: */
8879 virtual bool gate (function *fun)
8881 return !(fun->curr_properties & PROP_gimple_eomp);
8883 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8885 }; // class pass_expand_omp_ssa
8887 } // anon namespace
8889 gimple_opt_pass *
8890 make_pass_expand_omp_ssa (gcc::context *ctxt)
8892 return new pass_expand_omp_ssa (ctxt);
8895 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8897 /* If ctx is a worksharing context inside of a cancellable parallel
8898 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8899 and conditional branch to parallel's cancel_label to handle
8900 cancellation in the implicit barrier. */
8902 static void
8903 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8905 gimple omp_return = gimple_seq_last_stmt (*body);
8906 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8907 if (gimple_omp_return_nowait_p (omp_return))
8908 return;
8909 if (ctx->outer
8910 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8911 && ctx->outer->cancellable)
8913 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8914 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8915 tree lhs = create_tmp_var (c_bool_type, NULL);
8916 gimple_omp_return_set_lhs (omp_return, lhs);
8917 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8918 gimple g = gimple_build_cond (NE_EXPR, lhs,
8919 fold_convert (c_bool_type,
8920 boolean_false_node),
8921 ctx->outer->cancel_label, fallthru_label);
8922 gimple_seq_add_stmt (body, g);
8923 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8927 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8928 CTX is the enclosing OMP context for the current statement. */
8930 static void
8931 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8933 tree block, control;
8934 gimple_stmt_iterator tgsi;
8935 gimple stmt, new_stmt, bind, t;
8936 gimple_seq ilist, dlist, olist, new_body;
8938 stmt = gsi_stmt (*gsi_p);
8940 push_gimplify_context ();
8942 dlist = NULL;
8943 ilist = NULL;
8944 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8945 &ilist, &dlist, ctx, NULL);
8947 new_body = gimple_omp_body (stmt);
8948 gimple_omp_set_body (stmt, NULL);
8949 tgsi = gsi_start (new_body);
8950 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8952 omp_context *sctx;
8953 gimple sec_start;
8955 sec_start = gsi_stmt (tgsi);
8956 sctx = maybe_lookup_ctx (sec_start);
8957 gcc_assert (sctx);
8959 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8960 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8961 GSI_CONTINUE_LINKING);
8962 gimple_omp_set_body (sec_start, NULL);
8964 if (gsi_one_before_end_p (tgsi))
8966 gimple_seq l = NULL;
8967 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8968 &l, ctx);
8969 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8970 gimple_omp_section_set_last (sec_start);
8973 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8974 GSI_CONTINUE_LINKING);
8977 block = make_node (BLOCK);
8978 bind = gimple_build_bind (NULL, new_body, block);
8980 olist = NULL;
8981 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8983 block = make_node (BLOCK);
8984 new_stmt = gimple_build_bind (NULL, NULL, block);
8985 gsi_replace (gsi_p, new_stmt, true);
8987 pop_gimplify_context (new_stmt);
8988 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8989 BLOCK_VARS (block) = gimple_bind_vars (bind);
8990 if (BLOCK_VARS (block))
8991 TREE_USED (block) = 1;
8993 new_body = NULL;
8994 gimple_seq_add_seq (&new_body, ilist);
8995 gimple_seq_add_stmt (&new_body, stmt);
8996 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8997 gimple_seq_add_stmt (&new_body, bind);
8999 control = create_tmp_var (unsigned_type_node, ".section");
9000 t = gimple_build_omp_continue (control, control);
9001 gimple_omp_sections_set_control (stmt, control);
9002 gimple_seq_add_stmt (&new_body, t);
9004 gimple_seq_add_seq (&new_body, olist);
9005 if (ctx->cancellable)
9006 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9007 gimple_seq_add_seq (&new_body, dlist);
9009 new_body = maybe_catch_exception (new_body);
9011 t = gimple_build_omp_return
9012 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
9013 OMP_CLAUSE_NOWAIT));
9014 gimple_seq_add_stmt (&new_body, t);
9015 maybe_add_implicit_barrier_cancel (ctx, &new_body);
9017 gimple_bind_set_body (new_stmt, new_body);
9021 /* A subroutine of lower_omp_single. Expand the simple form of
9022 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
9024 if (GOMP_single_start ())
9025 BODY;
9026 [ GOMP_barrier (); ] -> unless 'nowait' is present.
9028 FIXME. It may be better to delay expanding the logic of this until
9029 pass_expand_omp. The expanded logic may make the job more difficult
9030 to a synchronization analysis pass. */
9032 static void
9033 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
9035 location_t loc = gimple_location (single_stmt);
9036 tree tlabel = create_artificial_label (loc);
9037 tree flabel = create_artificial_label (loc);
9038 gimple call, cond;
9039 tree lhs, decl;
9041 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
9042 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
9043 call = gimple_build_call (decl, 0);
9044 gimple_call_set_lhs (call, lhs);
9045 gimple_seq_add_stmt (pre_p, call);
9047 cond = gimple_build_cond (EQ_EXPR, lhs,
9048 fold_convert_loc (loc, TREE_TYPE (lhs),
9049 boolean_true_node),
9050 tlabel, flabel);
9051 gimple_seq_add_stmt (pre_p, cond);
9052 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
9053 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9054 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
9058 /* A subroutine of lower_omp_single. Expand the simple form of
9059 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
9061 #pragma omp single copyprivate (a, b, c)
9063 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
9066 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
9068 BODY;
9069 copyout.a = a;
9070 copyout.b = b;
9071 copyout.c = c;
9072 GOMP_single_copy_end (&copyout);
9074 else
9076 a = copyout_p->a;
9077 b = copyout_p->b;
9078 c = copyout_p->c;
9080 GOMP_barrier ();
9083 FIXME. It may be better to delay expanding the logic of this until
9084 pass_expand_omp. The expanded logic may make the job more difficult
9085 to a synchronization analysis pass. */
9087 static void
9088 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
9090 tree ptr_type, t, l0, l1, l2, bfn_decl;
9091 gimple_seq copyin_seq;
9092 location_t loc = gimple_location (single_stmt);
9094 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
9096 ptr_type = build_pointer_type (ctx->record_type);
9097 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
9099 l0 = create_artificial_label (loc);
9100 l1 = create_artificial_label (loc);
9101 l2 = create_artificial_label (loc);
9103 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
9104 t = build_call_expr_loc (loc, bfn_decl, 0);
9105 t = fold_convert_loc (loc, ptr_type, t);
9106 gimplify_assign (ctx->receiver_decl, t, pre_p);
9108 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
9109 build_int_cst (ptr_type, 0));
9110 t = build3 (COND_EXPR, void_type_node, t,
9111 build_and_jump (&l0), build_and_jump (&l1));
9112 gimplify_and_add (t, pre_p);
9114 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
9116 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9118 copyin_seq = NULL;
9119 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
9120 &copyin_seq, ctx);
9122 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9123 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
9124 t = build_call_expr_loc (loc, bfn_decl, 1, t);
9125 gimplify_and_add (t, pre_p);
9127 t = build_and_jump (&l2);
9128 gimplify_and_add (t, pre_p);
9130 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
9132 gimple_seq_add_seq (pre_p, copyin_seq);
9134 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
9138 /* Expand code for an OpenMP single directive. */
9140 static void
9141 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9143 tree block;
9144 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
9145 gimple_seq bind_body, bind_body_tail = NULL, dlist;
9147 push_gimplify_context ();
9149 block = make_node (BLOCK);
9150 bind = gimple_build_bind (NULL, NULL, block);
9151 gsi_replace (gsi_p, bind, true);
9152 bind_body = NULL;
9153 dlist = NULL;
9154 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
9155 &bind_body, &dlist, ctx, NULL);
9156 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
9158 gimple_seq_add_stmt (&bind_body, single_stmt);
9160 if (ctx->record_type)
9161 lower_omp_single_copy (single_stmt, &bind_body, ctx);
9162 else
9163 lower_omp_single_simple (single_stmt, &bind_body);
9165 gimple_omp_set_body (single_stmt, NULL);
9167 gimple_seq_add_seq (&bind_body, dlist);
9169 bind_body = maybe_catch_exception (bind_body);
9171 t = gimple_build_omp_return
9172 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
9173 OMP_CLAUSE_NOWAIT));
9174 gimple_seq_add_stmt (&bind_body_tail, t);
9175 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
9176 if (ctx->record_type)
9178 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9179 tree clobber = build_constructor (ctx->record_type, NULL);
9180 TREE_THIS_VOLATILE (clobber) = 1;
9181 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9182 clobber), GSI_SAME_STMT);
9184 gimple_seq_add_seq (&bind_body, bind_body_tail);
9185 gimple_bind_set_body (bind, bind_body);
9187 pop_gimplify_context (bind);
9189 gimple_bind_append_vars (bind, ctx->block_vars);
9190 BLOCK_VARS (block) = ctx->block_vars;
9191 if (BLOCK_VARS (block))
9192 TREE_USED (block) = 1;
9196 /* Expand code for an OpenMP master directive. */
9198 static void
9199 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9201 tree block, lab = NULL, x, bfn_decl;
9202 gimple stmt = gsi_stmt (*gsi_p), bind;
9203 location_t loc = gimple_location (stmt);
9204 gimple_seq tseq;
9206 push_gimplify_context ();
9208 block = make_node (BLOCK);
9209 bind = gimple_build_bind (NULL, NULL, block);
9210 gsi_replace (gsi_p, bind, true);
9211 gimple_bind_add_stmt (bind, stmt);
9213 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9214 x = build_call_expr_loc (loc, bfn_decl, 0);
9215 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
9216 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9217 tseq = NULL;
9218 gimplify_and_add (x, &tseq);
9219 gimple_bind_add_seq (bind, tseq);
9221 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9222 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9223 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9224 gimple_omp_set_body (stmt, NULL);
9226 gimple_bind_add_stmt (bind, gimple_build_label (lab));
9228 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9230 pop_gimplify_context (bind);
9232 gimple_bind_append_vars (bind, ctx->block_vars);
9233 BLOCK_VARS (block) = ctx->block_vars;
9237 /* Expand code for an OpenMP taskgroup directive. */
9239 static void
9240 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9242 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9243 tree block = make_node (BLOCK);
9245 bind = gimple_build_bind (NULL, NULL, block);
9246 gsi_replace (gsi_p, bind, true);
9247 gimple_bind_add_stmt (bind, stmt);
9249 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9251 gimple_bind_add_stmt (bind, x);
9253 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9254 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9255 gimple_omp_set_body (stmt, NULL);
9257 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9259 gimple_bind_append_vars (bind, ctx->block_vars);
9260 BLOCK_VARS (block) = ctx->block_vars;
9264 /* Expand code for an OpenMP ordered directive. */
9266 static void
9267 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9269 tree block;
9270 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9272 push_gimplify_context ();
9274 block = make_node (BLOCK);
9275 bind = gimple_build_bind (NULL, NULL, block);
9276 gsi_replace (gsi_p, bind, true);
9277 gimple_bind_add_stmt (bind, stmt);
9279 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
9281 gimple_bind_add_stmt (bind, x);
9283 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9284 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9285 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9286 gimple_omp_set_body (stmt, NULL);
9288 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
9289 gimple_bind_add_stmt (bind, x);
9291 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9293 pop_gimplify_context (bind);
9295 gimple_bind_append_vars (bind, ctx->block_vars);
9296 BLOCK_VARS (block) = gimple_bind_vars (bind);
9300 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9301 substitution of a couple of function calls. But in the NAMED case,
9302 requires that languages coordinate a symbol name. It is therefore
9303 best put here in common code. */
9305 static GTY((param1_is (tree), param2_is (tree)))
9306 splay_tree critical_name_mutexes;
9308 static void
9309 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9311 tree block;
9312 tree name, lock, unlock;
9313 gimple stmt = gsi_stmt (*gsi_p), bind;
9314 location_t loc = gimple_location (stmt);
9315 gimple_seq tbody;
9317 name = gimple_omp_critical_name (stmt);
9318 if (name)
9320 tree decl;
9321 splay_tree_node n;
9323 if (!critical_name_mutexes)
9324 critical_name_mutexes
9325 = splay_tree_new_ggc (splay_tree_compare_pointers,
9326 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
9327 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
9329 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
9330 if (n == NULL)
9332 char *new_str;
9334 decl = create_tmp_var_raw (ptr_type_node, NULL);
9336 new_str = ACONCAT ((".gomp_critical_user_",
9337 IDENTIFIER_POINTER (name), NULL));
9338 DECL_NAME (decl) = get_identifier (new_str);
9339 TREE_PUBLIC (decl) = 1;
9340 TREE_STATIC (decl) = 1;
9341 DECL_COMMON (decl) = 1;
9342 DECL_ARTIFICIAL (decl) = 1;
9343 DECL_IGNORED_P (decl) = 1;
9345 /* If '#pragma omp critical' is inside target region, the symbol must
9346 be marked for offloading. */
9347 omp_context *octx;
9348 for (octx = ctx->outer; octx; octx = octx->outer)
9349 if (is_targetreg_ctx (octx))
9351 varpool_node::get_create (decl)->offloadable = 1;
9352 break;
9355 varpool_node::finalize_decl (decl);
9357 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
9358 (splay_tree_value) decl);
9360 else
9361 decl = (tree) n->value;
9363 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
9364 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
9366 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
9367 unlock = build_call_expr_loc (loc, unlock, 1,
9368 build_fold_addr_expr_loc (loc, decl));
9370 else
9372 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
9373 lock = build_call_expr_loc (loc, lock, 0);
9375 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
9376 unlock = build_call_expr_loc (loc, unlock, 0);
9379 push_gimplify_context ();
9381 block = make_node (BLOCK);
9382 bind = gimple_build_bind (NULL, NULL, block);
9383 gsi_replace (gsi_p, bind, true);
9384 gimple_bind_add_stmt (bind, stmt);
9386 tbody = gimple_bind_body (bind);
9387 gimplify_and_add (lock, &tbody);
9388 gimple_bind_set_body (bind, tbody);
9390 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9391 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9392 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9393 gimple_omp_set_body (stmt, NULL);
9395 tbody = gimple_bind_body (bind);
9396 gimplify_and_add (unlock, &tbody);
9397 gimple_bind_set_body (bind, tbody);
9399 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9401 pop_gimplify_context (bind);
9402 gimple_bind_append_vars (bind, ctx->block_vars);
9403 BLOCK_VARS (block) = gimple_bind_vars (bind);
9407 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9408 for a lastprivate clause. Given a loop control predicate of (V
9409 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9410 is appended to *DLIST, iterator initialization is appended to
9411 *BODY_P. */
9413 static void
9414 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
9415 gimple_seq *dlist, struct omp_context *ctx)
9417 tree clauses, cond, vinit;
9418 enum tree_code cond_code;
9419 gimple_seq stmts;
9421 cond_code = fd->loop.cond_code;
9422 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
9424 /* When possible, use a strict equality expression. This can let VRP
9425 type optimizations deduce the value and remove a copy. */
9426 if (tree_fits_shwi_p (fd->loop.step))
9428 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
9429 if (step == 1 || step == -1)
9430 cond_code = EQ_EXPR;
9433 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
9435 clauses = gimple_omp_for_clauses (fd->for_stmt);
9436 stmts = NULL;
9437 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
9438 if (!gimple_seq_empty_p (stmts))
9440 gimple_seq_add_seq (&stmts, *dlist);
9441 *dlist = stmts;
9443 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9444 vinit = fd->loop.n1;
9445 if (cond_code == EQ_EXPR
9446 && tree_fits_shwi_p (fd->loop.n2)
9447 && ! integer_zerop (fd->loop.n2))
9448 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
9449 else
9450 vinit = unshare_expr (vinit);
9452 /* Initialize the iterator variable, so that threads that don't execute
9453 any iterations don't execute the lastprivate clauses by accident. */
9454 gimplify_assign (fd->loop.v, vinit, body_p);
9459 /* Lower code for an OpenMP loop directive. */
9461 static void
9462 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9464 tree *rhs_p, block;
9465 struct omp_for_data fd, *fdp = NULL;
9466 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
9467 gimple_seq omp_for_body, body, dlist;
9468 size_t i;
9470 push_gimplify_context ();
9472 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
9474 block = make_node (BLOCK);
9475 new_stmt = gimple_build_bind (NULL, NULL, block);
9476 /* Replace at gsi right away, so that 'stmt' is no member
9477 of a sequence anymore as we're going to add to to a different
9478 one below. */
9479 gsi_replace (gsi_p, new_stmt, true);
9481 /* Move declaration of temporaries in the loop body before we make
9482 it go away. */
9483 omp_for_body = gimple_omp_body (stmt);
9484 if (!gimple_seq_empty_p (omp_for_body)
9485 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9487 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
9488 tree vars = gimple_bind_vars (inner_bind);
9489 gimple_bind_append_vars (new_stmt, vars);
9490 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9491 keep them on the inner_bind and it's block. */
9492 gimple_bind_set_vars (inner_bind, NULL_TREE);
9493 if (gimple_bind_block (inner_bind))
9494 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9497 if (gimple_omp_for_combined_into_p (stmt))
9499 extract_omp_for_data (stmt, &fd, NULL);
9500 fdp = &fd;
9502 /* We need two temporaries with fd.loop.v type (istart/iend)
9503 and then (fd.collapse - 1) temporaries with the same
9504 type for count2 ... countN-1 vars if not constant. */
9505 size_t count = 2;
9506 tree type = fd.iter_type;
9507 if (fd.collapse > 1
9508 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9509 count += fd.collapse - 1;
9510 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9511 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9512 tree clauses = *pc;
9513 if (parallel_for)
9514 outerc
9515 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9516 OMP_CLAUSE__LOOPTEMP_);
9517 for (i = 0; i < count; i++)
9519 tree temp;
9520 if (parallel_for)
9522 gcc_assert (outerc);
9523 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9524 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9525 OMP_CLAUSE__LOOPTEMP_);
9527 else
9529 temp = create_tmp_var (type, NULL);
9530 insert_decl_map (&ctx->outer->cb, temp, temp);
9532 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9533 OMP_CLAUSE_DECL (*pc) = temp;
9534 pc = &OMP_CLAUSE_CHAIN (*pc);
9536 *pc = clauses;
9539 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9540 dlist = NULL;
9541 body = NULL;
9542 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9543 fdp);
9544 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9546 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9548 /* Lower the header expressions. At this point, we can assume that
9549 the header is of the form:
9551 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9553 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9554 using the .omp_data_s mapping, if needed. */
9555 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9557 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9558 if (!is_gimple_min_invariant (*rhs_p))
9559 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9561 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9562 if (!is_gimple_min_invariant (*rhs_p))
9563 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9565 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9566 if (!is_gimple_min_invariant (*rhs_p))
9567 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9570 /* Once lowered, extract the bounds and clauses. */
9571 extract_omp_for_data (stmt, &fd, NULL);
9573 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9575 gimple_seq_add_stmt (&body, stmt);
9576 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9578 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9579 fd.loop.v));
9581 /* After the loop, add exit clauses. */
9582 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9584 if (ctx->cancellable)
9585 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9587 gimple_seq_add_seq (&body, dlist);
9589 body = maybe_catch_exception (body);
9591 /* Region exit marker goes at the end of the loop body. */
9592 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9593 maybe_add_implicit_barrier_cancel (ctx, &body);
9594 pop_gimplify_context (new_stmt);
9596 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9597 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9598 if (BLOCK_VARS (block))
9599 TREE_USED (block) = 1;
9601 gimple_bind_set_body (new_stmt, body);
9602 gimple_omp_set_body (stmt, NULL);
9603 gimple_omp_for_set_pre_body (stmt, NULL);
9606 /* Callback for walk_stmts. Check if the current statement only contains
9607 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9609 static tree
9610 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9611 bool *handled_ops_p,
9612 struct walk_stmt_info *wi)
9614 int *info = (int *) wi->info;
9615 gimple stmt = gsi_stmt (*gsi_p);
9617 *handled_ops_p = true;
9618 switch (gimple_code (stmt))
9620 WALK_SUBSTMTS;
9622 case GIMPLE_OMP_FOR:
9623 case GIMPLE_OMP_SECTIONS:
9624 *info = *info == 0 ? 1 : -1;
9625 break;
9626 default:
9627 *info = -1;
9628 break;
9630 return NULL;
9633 struct omp_taskcopy_context
9635 /* This field must be at the beginning, as we do "inheritance": Some
9636 callback functions for tree-inline.c (e.g., omp_copy_decl)
9637 receive a copy_body_data pointer that is up-casted to an
9638 omp_context pointer. */
9639 copy_body_data cb;
9640 omp_context *ctx;
9643 static tree
9644 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9646 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9648 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9649 return create_tmp_var (TREE_TYPE (var), NULL);
9651 return var;
9654 static tree
9655 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9657 tree name, new_fields = NULL, type, f;
9659 type = lang_hooks.types.make_type (RECORD_TYPE);
9660 name = DECL_NAME (TYPE_NAME (orig_type));
9661 name = build_decl (gimple_location (tcctx->ctx->stmt),
9662 TYPE_DECL, name, type);
9663 TYPE_NAME (type) = name;
9665 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9667 tree new_f = copy_node (f);
9668 DECL_CONTEXT (new_f) = type;
9669 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9670 TREE_CHAIN (new_f) = new_fields;
9671 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9672 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9673 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9674 &tcctx->cb, NULL);
9675 new_fields = new_f;
9676 tcctx->cb.decl_map->put (f, new_f);
9678 TYPE_FIELDS (type) = nreverse (new_fields);
9679 layout_type (type);
9680 return type;
9683 /* Create task copyfn. */
9685 static void
9686 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9688 struct function *child_cfun;
9689 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9690 tree record_type, srecord_type, bind, list;
9691 bool record_needs_remap = false, srecord_needs_remap = false;
9692 splay_tree_node n;
9693 struct omp_taskcopy_context tcctx;
9694 location_t loc = gimple_location (task_stmt);
9696 child_fn = gimple_omp_task_copy_fn (task_stmt);
9697 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9698 gcc_assert (child_cfun->cfg == NULL);
9699 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9701 /* Reset DECL_CONTEXT on function arguments. */
9702 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9703 DECL_CONTEXT (t) = child_fn;
9705 /* Populate the function. */
9706 push_gimplify_context ();
9707 push_cfun (child_cfun);
9709 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9710 TREE_SIDE_EFFECTS (bind) = 1;
9711 list = NULL;
9712 DECL_SAVED_TREE (child_fn) = bind;
9713 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9715 /* Remap src and dst argument types if needed. */
9716 record_type = ctx->record_type;
9717 srecord_type = ctx->srecord_type;
9718 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9719 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9721 record_needs_remap = true;
9722 break;
9724 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9725 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9727 srecord_needs_remap = true;
9728 break;
9731 if (record_needs_remap || srecord_needs_remap)
9733 memset (&tcctx, '\0', sizeof (tcctx));
9734 tcctx.cb.src_fn = ctx->cb.src_fn;
9735 tcctx.cb.dst_fn = child_fn;
9736 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
9737 gcc_checking_assert (tcctx.cb.src_node);
9738 tcctx.cb.dst_node = tcctx.cb.src_node;
9739 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9740 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9741 tcctx.cb.eh_lp_nr = 0;
9742 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9743 tcctx.cb.decl_map = new hash_map<tree, tree>;
9744 tcctx.ctx = ctx;
9746 if (record_needs_remap)
9747 record_type = task_copyfn_remap_type (&tcctx, record_type);
9748 if (srecord_needs_remap)
9749 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9751 else
9752 tcctx.cb.decl_map = NULL;
9754 arg = DECL_ARGUMENTS (child_fn);
9755 TREE_TYPE (arg) = build_pointer_type (record_type);
9756 sarg = DECL_CHAIN (arg);
9757 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9759 /* First pass: initialize temporaries used in record_type and srecord_type
9760 sizes and field offsets. */
9761 if (tcctx.cb.decl_map)
9762 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9763 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9765 tree *p;
9767 decl = OMP_CLAUSE_DECL (c);
9768 p = tcctx.cb.decl_map->get (decl);
9769 if (p == NULL)
9770 continue;
9771 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9772 sf = (tree) n->value;
9773 sf = *tcctx.cb.decl_map->get (sf);
9774 src = build_simple_mem_ref_loc (loc, sarg);
9775 src = omp_build_component_ref (src, sf);
9776 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9777 append_to_statement_list (t, &list);
9780 /* Second pass: copy shared var pointers and copy construct non-VLA
9781 firstprivate vars. */
9782 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9783 switch (OMP_CLAUSE_CODE (c))
9785 case OMP_CLAUSE_SHARED:
9786 decl = OMP_CLAUSE_DECL (c);
9787 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9788 if (n == NULL)
9789 break;
9790 f = (tree) n->value;
9791 if (tcctx.cb.decl_map)
9792 f = *tcctx.cb.decl_map->get (f);
9793 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9794 sf = (tree) n->value;
9795 if (tcctx.cb.decl_map)
9796 sf = *tcctx.cb.decl_map->get (sf);
9797 src = build_simple_mem_ref_loc (loc, sarg);
9798 src = omp_build_component_ref (src, sf);
9799 dst = build_simple_mem_ref_loc (loc, arg);
9800 dst = omp_build_component_ref (dst, f);
9801 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9802 append_to_statement_list (t, &list);
9803 break;
9804 case OMP_CLAUSE_FIRSTPRIVATE:
9805 decl = OMP_CLAUSE_DECL (c);
9806 if (is_variable_sized (decl))
9807 break;
9808 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9809 if (n == NULL)
9810 break;
9811 f = (tree) n->value;
9812 if (tcctx.cb.decl_map)
9813 f = *tcctx.cb.decl_map->get (f);
9814 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9815 if (n != NULL)
9817 sf = (tree) n->value;
9818 if (tcctx.cb.decl_map)
9819 sf = *tcctx.cb.decl_map->get (sf);
9820 src = build_simple_mem_ref_loc (loc, sarg);
9821 src = omp_build_component_ref (src, sf);
9822 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9823 src = build_simple_mem_ref_loc (loc, src);
9825 else
9826 src = decl;
9827 dst = build_simple_mem_ref_loc (loc, arg);
9828 dst = omp_build_component_ref (dst, f);
9829 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9830 append_to_statement_list (t, &list);
9831 break;
9832 case OMP_CLAUSE_PRIVATE:
9833 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9834 break;
9835 decl = OMP_CLAUSE_DECL (c);
9836 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9837 f = (tree) n->value;
9838 if (tcctx.cb.decl_map)
9839 f = *tcctx.cb.decl_map->get (f);
9840 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9841 if (n != NULL)
9843 sf = (tree) n->value;
9844 if (tcctx.cb.decl_map)
9845 sf = *tcctx.cb.decl_map->get (sf);
9846 src = build_simple_mem_ref_loc (loc, sarg);
9847 src = omp_build_component_ref (src, sf);
9848 if (use_pointer_for_field (decl, NULL))
9849 src = build_simple_mem_ref_loc (loc, src);
9851 else
9852 src = decl;
9853 dst = build_simple_mem_ref_loc (loc, arg);
9854 dst = omp_build_component_ref (dst, f);
9855 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9856 append_to_statement_list (t, &list);
9857 break;
9858 default:
9859 break;
9862 /* Last pass: handle VLA firstprivates. */
9863 if (tcctx.cb.decl_map)
9864 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9865 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9867 tree ind, ptr, df;
9869 decl = OMP_CLAUSE_DECL (c);
9870 if (!is_variable_sized (decl))
9871 continue;
9872 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9873 if (n == NULL)
9874 continue;
9875 f = (tree) n->value;
9876 f = *tcctx.cb.decl_map->get (f);
9877 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9878 ind = DECL_VALUE_EXPR (decl);
9879 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9880 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9881 n = splay_tree_lookup (ctx->sfield_map,
9882 (splay_tree_key) TREE_OPERAND (ind, 0));
9883 sf = (tree) n->value;
9884 sf = *tcctx.cb.decl_map->get (sf);
9885 src = build_simple_mem_ref_loc (loc, sarg);
9886 src = omp_build_component_ref (src, sf);
9887 src = build_simple_mem_ref_loc (loc, src);
9888 dst = build_simple_mem_ref_loc (loc, arg);
9889 dst = omp_build_component_ref (dst, f);
9890 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9891 append_to_statement_list (t, &list);
9892 n = splay_tree_lookup (ctx->field_map,
9893 (splay_tree_key) TREE_OPERAND (ind, 0));
9894 df = (tree) n->value;
9895 df = *tcctx.cb.decl_map->get (df);
9896 ptr = build_simple_mem_ref_loc (loc, arg);
9897 ptr = omp_build_component_ref (ptr, df);
9898 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9899 build_fold_addr_expr_loc (loc, dst));
9900 append_to_statement_list (t, &list);
9903 t = build1 (RETURN_EXPR, void_type_node, NULL);
9904 append_to_statement_list (t, &list);
9906 if (tcctx.cb.decl_map)
9907 delete tcctx.cb.decl_map;
9908 pop_gimplify_context (NULL);
9909 BIND_EXPR_BODY (bind) = list;
9910 pop_cfun ();
9913 static void
9914 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9916 tree c, clauses;
9917 gimple g;
9918 size_t n_in = 0, n_out = 0, idx = 2, i;
9920 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9921 OMP_CLAUSE_DEPEND);
9922 gcc_assert (clauses);
9923 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9924 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9925 switch (OMP_CLAUSE_DEPEND_KIND (c))
9927 case OMP_CLAUSE_DEPEND_IN:
9928 n_in++;
9929 break;
9930 case OMP_CLAUSE_DEPEND_OUT:
9931 case OMP_CLAUSE_DEPEND_INOUT:
9932 n_out++;
9933 break;
9934 default:
9935 gcc_unreachable ();
9937 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9938 tree array = create_tmp_var (type, NULL);
9939 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9940 NULL_TREE);
9941 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9942 gimple_seq_add_stmt (iseq, g);
9943 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9944 NULL_TREE);
9945 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9946 gimple_seq_add_stmt (iseq, g);
9947 for (i = 0; i < 2; i++)
9949 if ((i ? n_in : n_out) == 0)
9950 continue;
9951 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9952 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9953 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9955 tree t = OMP_CLAUSE_DECL (c);
9956 t = fold_convert (ptr_type_node, t);
9957 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9958 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9959 NULL_TREE, NULL_TREE);
9960 g = gimple_build_assign (r, t);
9961 gimple_seq_add_stmt (iseq, g);
9964 tree *p = gimple_omp_task_clauses_ptr (stmt);
9965 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9966 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9967 OMP_CLAUSE_CHAIN (c) = *p;
9968 *p = c;
9969 tree clobber = build_constructor (type, NULL);
9970 TREE_THIS_VOLATILE (clobber) = 1;
9971 g = gimple_build_assign (array, clobber);
9972 gimple_seq_add_stmt (oseq, g);
9975 /* Lower the OpenMP parallel or task directive in the current statement
9976 in GSI_P. CTX holds context information for the directive. */
9978 static void
9979 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9981 tree clauses;
9982 tree child_fn, t;
9983 gimple stmt = gsi_stmt (*gsi_p);
9984 gimple par_bind, bind, dep_bind = NULL;
9985 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9986 location_t loc = gimple_location (stmt);
9988 clauses = gimple_omp_taskreg_clauses (stmt);
9989 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9990 par_body = gimple_bind_body (par_bind);
9991 child_fn = ctx->cb.dst_fn;
9992 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9993 && !gimple_omp_parallel_combined_p (stmt))
9995 struct walk_stmt_info wi;
9996 int ws_num = 0;
9998 memset (&wi, 0, sizeof (wi));
9999 wi.info = &ws_num;
10000 wi.val_only = true;
10001 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
10002 if (ws_num == 1)
10003 gimple_omp_parallel_set_combined_p (stmt, true);
10005 gimple_seq dep_ilist = NULL;
10006 gimple_seq dep_olist = NULL;
10007 if (gimple_code (stmt) == GIMPLE_OMP_TASK
10008 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
10010 push_gimplify_context ();
10011 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
10012 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
10015 if (ctx->srecord_type)
10016 create_task_copyfn (stmt, ctx);
10018 push_gimplify_context ();
10020 par_olist = NULL;
10021 par_ilist = NULL;
10022 par_rlist = NULL;
10023 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
10024 lower_omp (&par_body, ctx);
10025 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
10026 lower_reduction_clauses (clauses, &par_rlist, ctx);
10028 /* Declare all the variables created by mapping and the variables
10029 declared in the scope of the parallel body. */
10030 record_vars_into (ctx->block_vars, child_fn);
10031 record_vars_into (gimple_bind_vars (par_bind), child_fn);
10033 if (ctx->record_type)
10035 ctx->sender_decl
10036 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
10037 : ctx->record_type, ".omp_data_o");
10038 DECL_NAMELESS (ctx->sender_decl) = 1;
10039 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10040 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
10043 olist = NULL;
10044 ilist = NULL;
10045 lower_send_clauses (clauses, &ilist, &olist, ctx);
10046 lower_send_shared_vars (&ilist, &olist, ctx);
10048 if (ctx->record_type)
10050 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
10051 TREE_THIS_VOLATILE (clobber) = 1;
10052 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10053 clobber));
10056 /* Once all the expansions are done, sequence all the different
10057 fragments inside gimple_omp_body. */
10059 new_body = NULL;
10061 if (ctx->record_type)
10063 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10064 /* fixup_child_record_type might have changed receiver_decl's type. */
10065 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10066 gimple_seq_add_stmt (&new_body,
10067 gimple_build_assign (ctx->receiver_decl, t));
10070 gimple_seq_add_seq (&new_body, par_ilist);
10071 gimple_seq_add_seq (&new_body, par_body);
10072 gimple_seq_add_seq (&new_body, par_rlist);
10073 if (ctx->cancellable)
10074 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10075 gimple_seq_add_seq (&new_body, par_olist);
10076 new_body = maybe_catch_exception (new_body);
10077 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10078 gimple_omp_set_body (stmt, new_body);
10080 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
10081 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
10082 gimple_bind_add_seq (bind, ilist);
10083 gimple_bind_add_stmt (bind, stmt);
10084 gimple_bind_add_seq (bind, olist);
10086 pop_gimplify_context (NULL);
10088 if (dep_bind)
10090 gimple_bind_add_seq (dep_bind, dep_ilist);
10091 gimple_bind_add_stmt (dep_bind, bind);
10092 gimple_bind_add_seq (dep_bind, dep_olist);
10093 pop_gimplify_context (dep_bind);
10097 /* Lower the OpenMP target directive in the current statement
10098 in GSI_P. CTX holds context information for the directive. */
10100 static void
10101 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10103 tree clauses;
10104 tree child_fn, t, c;
10105 gimple stmt = gsi_stmt (*gsi_p);
10106 gimple tgt_bind = NULL, bind;
10107 gimple_seq tgt_body = NULL, olist, ilist, new_body;
10108 location_t loc = gimple_location (stmt);
10109 int kind = gimple_omp_target_kind (stmt);
10110 unsigned int map_cnt = 0;
10112 clauses = gimple_omp_target_clauses (stmt);
10113 if (kind == GF_OMP_TARGET_KIND_REGION)
10115 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
10116 tgt_body = gimple_bind_body (tgt_bind);
10118 else if (kind == GF_OMP_TARGET_KIND_DATA)
10119 tgt_body = gimple_omp_body (stmt);
10120 child_fn = ctx->cb.dst_fn;
10122 push_gimplify_context ();
10124 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10125 switch (OMP_CLAUSE_CODE (c))
10127 tree var, x;
10129 default:
10130 break;
10131 case OMP_CLAUSE_MAP:
10132 case OMP_CLAUSE_TO:
10133 case OMP_CLAUSE_FROM:
10134 var = OMP_CLAUSE_DECL (c);
10135 if (!DECL_P (var))
10137 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10138 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10139 map_cnt++;
10140 continue;
10143 if (DECL_SIZE (var)
10144 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
10146 tree var2 = DECL_VALUE_EXPR (var);
10147 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
10148 var2 = TREE_OPERAND (var2, 0);
10149 gcc_assert (DECL_P (var2));
10150 var = var2;
10153 if (!maybe_lookup_field (var, ctx))
10154 continue;
10156 if (kind == GF_OMP_TARGET_KIND_REGION)
10158 x = build_receiver_ref (var, true, ctx);
10159 tree new_var = lookup_decl (var, ctx);
10160 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10161 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10162 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10163 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
10164 x = build_simple_mem_ref (x);
10165 SET_DECL_VALUE_EXPR (new_var, x);
10166 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
10168 map_cnt++;
10171 if (kind == GF_OMP_TARGET_KIND_REGION)
10173 target_nesting_level++;
10174 lower_omp (&tgt_body, ctx);
10175 target_nesting_level--;
10177 else if (kind == GF_OMP_TARGET_KIND_DATA)
10178 lower_omp (&tgt_body, ctx);
10180 if (kind == GF_OMP_TARGET_KIND_REGION)
10182 /* Declare all the variables created by mapping and the variables
10183 declared in the scope of the target body. */
10184 record_vars_into (ctx->block_vars, child_fn);
10185 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
10188 olist = NULL;
10189 ilist = NULL;
10190 if (ctx->record_type)
10192 ctx->sender_decl
10193 = create_tmp_var (ctx->record_type, ".omp_data_arr");
10194 DECL_NAMELESS (ctx->sender_decl) = 1;
10195 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10196 t = make_tree_vec (3);
10197 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
10198 TREE_VEC_ELT (t, 1)
10199 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
10200 ".omp_data_sizes");
10201 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
10202 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
10203 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
10204 TREE_VEC_ELT (t, 2)
10205 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
10206 map_cnt),
10207 ".omp_data_kinds");
10208 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
10209 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
10210 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
10211 gimple_omp_target_set_data_arg (stmt, t);
10213 vec<constructor_elt, va_gc> *vsize;
10214 vec<constructor_elt, va_gc> *vkind;
10215 vec_alloc (vsize, map_cnt);
10216 vec_alloc (vkind, map_cnt);
10217 unsigned int map_idx = 0;
10219 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10220 switch (OMP_CLAUSE_CODE (c))
10222 tree ovar, nc;
10224 default:
10225 break;
10226 case OMP_CLAUSE_MAP:
10227 case OMP_CLAUSE_TO:
10228 case OMP_CLAUSE_FROM:
10229 nc = c;
10230 ovar = OMP_CLAUSE_DECL (c);
10231 if (!DECL_P (ovar))
10233 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10234 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10236 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
10237 == get_base_address (ovar));
10238 nc = OMP_CLAUSE_CHAIN (c);
10239 ovar = OMP_CLAUSE_DECL (nc);
10241 else
10243 tree x = build_sender_ref (ovar, ctx);
10244 tree v
10245 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
10246 gimplify_assign (x, v, &ilist);
10247 nc = NULL_TREE;
10250 else
10252 if (DECL_SIZE (ovar)
10253 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
10255 tree ovar2 = DECL_VALUE_EXPR (ovar);
10256 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
10257 ovar2 = TREE_OPERAND (ovar2, 0);
10258 gcc_assert (DECL_P (ovar2));
10259 ovar = ovar2;
10261 if (!maybe_lookup_field (ovar, ctx))
10262 continue;
10265 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
10266 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
10267 talign = DECL_ALIGN_UNIT (ovar);
10268 if (nc)
10270 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
10271 tree x = build_sender_ref (ovar, ctx);
10272 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10273 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10274 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10275 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
10277 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10278 tree avar
10279 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
10280 mark_addressable (avar);
10281 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
10282 talign = DECL_ALIGN_UNIT (avar);
10283 avar = build_fold_addr_expr (avar);
10284 gimplify_assign (x, avar, &ilist);
10286 else if (is_gimple_reg (var))
10288 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10289 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
10290 mark_addressable (avar);
10291 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
10292 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
10293 gimplify_assign (avar, var, &ilist);
10294 avar = build_fold_addr_expr (avar);
10295 gimplify_assign (x, avar, &ilist);
10296 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
10297 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
10298 && !TYPE_READONLY (TREE_TYPE (var)))
10300 x = build_sender_ref (ovar, ctx);
10301 x = build_simple_mem_ref (x);
10302 gimplify_assign (var, x, &olist);
10305 else
10307 var = build_fold_addr_expr (var);
10308 gimplify_assign (x, var, &ilist);
10311 tree s = OMP_CLAUSE_SIZE (c);
10312 if (s == NULL_TREE)
10313 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
10314 s = fold_convert (size_type_node, s);
10315 tree purpose = size_int (map_idx++);
10316 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
10317 if (TREE_CODE (s) != INTEGER_CST)
10318 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
10320 unsigned char tkind = 0;
10321 switch (OMP_CLAUSE_CODE (c))
10323 case OMP_CLAUSE_MAP:
10324 tkind = OMP_CLAUSE_MAP_KIND (c);
10325 break;
10326 case OMP_CLAUSE_TO:
10327 tkind = OMP_CLAUSE_MAP_TO;
10328 break;
10329 case OMP_CLAUSE_FROM:
10330 tkind = OMP_CLAUSE_MAP_FROM;
10331 break;
10332 default:
10333 gcc_unreachable ();
10335 talign = ceil_log2 (talign);
10336 tkind |= talign << 3;
10337 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
10338 build_int_cst (unsigned_char_type_node,
10339 tkind));
10340 if (nc && nc != c)
10341 c = nc;
10344 gcc_assert (map_idx == map_cnt);
10346 DECL_INITIAL (TREE_VEC_ELT (t, 1))
10347 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
10348 DECL_INITIAL (TREE_VEC_ELT (t, 2))
10349 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
10350 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
10352 gimple_seq initlist = NULL;
10353 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
10354 TREE_VEC_ELT (t, 1)),
10355 &initlist, true, NULL_TREE);
10356 gimple_seq_add_seq (&ilist, initlist);
10358 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
10359 NULL);
10360 TREE_THIS_VOLATILE (clobber) = 1;
10361 gimple_seq_add_stmt (&olist,
10362 gimple_build_assign (TREE_VEC_ELT (t, 1),
10363 clobber));
10366 tree clobber = build_constructor (ctx->record_type, NULL);
10367 TREE_THIS_VOLATILE (clobber) = 1;
10368 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10369 clobber));
10372 /* Once all the expansions are done, sequence all the different
10373 fragments inside gimple_omp_body. */
10375 new_body = NULL;
10377 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
10379 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10380 /* fixup_child_record_type might have changed receiver_decl's type. */
10381 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10382 gimple_seq_add_stmt (&new_body,
10383 gimple_build_assign (ctx->receiver_decl, t));
10386 if (kind == GF_OMP_TARGET_KIND_REGION)
10388 gimple_seq_add_seq (&new_body, tgt_body);
10389 new_body = maybe_catch_exception (new_body);
10391 else if (kind == GF_OMP_TARGET_KIND_DATA)
10392 new_body = tgt_body;
10393 if (kind != GF_OMP_TARGET_KIND_UPDATE)
10395 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10396 gimple_omp_set_body (stmt, new_body);
10399 bind = gimple_build_bind (NULL, NULL,
10400 tgt_bind ? gimple_bind_block (tgt_bind)
10401 : NULL_TREE);
10402 gsi_replace (gsi_p, bind, true);
10403 gimple_bind_add_seq (bind, ilist);
10404 gimple_bind_add_stmt (bind, stmt);
10405 gimple_bind_add_seq (bind, olist);
10407 pop_gimplify_context (NULL);
10410 /* Expand code for an OpenMP teams directive. */
10412 static void
10413 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10415 gimple teams_stmt = gsi_stmt (*gsi_p);
10416 push_gimplify_context ();
10418 tree block = make_node (BLOCK);
10419 gimple bind = gimple_build_bind (NULL, NULL, block);
10420 gsi_replace (gsi_p, bind, true);
10421 gimple_seq bind_body = NULL;
10422 gimple_seq dlist = NULL;
10423 gimple_seq olist = NULL;
10425 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10426 OMP_CLAUSE_NUM_TEAMS);
10427 if (num_teams == NULL_TREE)
10428 num_teams = build_int_cst (unsigned_type_node, 0);
10429 else
10431 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
10432 num_teams = fold_convert (unsigned_type_node, num_teams);
10433 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
10435 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10436 OMP_CLAUSE_THREAD_LIMIT);
10437 if (thread_limit == NULL_TREE)
10438 thread_limit = build_int_cst (unsigned_type_node, 0);
10439 else
10441 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10442 thread_limit = fold_convert (unsigned_type_node, thread_limit);
10443 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
10444 fb_rvalue);
10447 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
10448 &bind_body, &dlist, ctx, NULL);
10449 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
10450 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
10451 gimple_seq_add_stmt (&bind_body, teams_stmt);
10453 location_t loc = gimple_location (teams_stmt);
10454 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
10455 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10456 gimple_set_location (call, loc);
10457 gimple_seq_add_stmt (&bind_body, call);
10459 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10460 gimple_omp_set_body (teams_stmt, NULL);
10461 gimple_seq_add_seq (&bind_body, olist);
10462 gimple_seq_add_seq (&bind_body, dlist);
10463 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10464 gimple_bind_set_body (bind, bind_body);
10466 pop_gimplify_context (bind);
10468 gimple_bind_append_vars (bind, ctx->block_vars);
10469 BLOCK_VARS (block) = ctx->block_vars;
10470 if (BLOCK_VARS (block))
10471 TREE_USED (block) = 1;
10475 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10476 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10477 of OpenMP context, but with task_shared_vars set. */
10479 static tree
10480 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10481 void *data)
10483 tree t = *tp;
10485 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10486 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
10487 return t;
10489 if (task_shared_vars
10490 && DECL_P (t)
10491 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10492 return t;
10494 /* If a global variable has been privatized, TREE_CONSTANT on
10495 ADDR_EXPR might be wrong. */
10496 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10497 recompute_tree_invariant_for_addr_expr (t);
10499 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10500 return NULL_TREE;
10503 static void
10504 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10506 gimple stmt = gsi_stmt (*gsi_p);
10507 struct walk_stmt_info wi;
10509 if (gimple_has_location (stmt))
10510 input_location = gimple_location (stmt);
10512 if (task_shared_vars)
10513 memset (&wi, '\0', sizeof (wi));
10515 /* If we have issued syntax errors, avoid doing any heavy lifting.
10516 Just replace the OpenMP directives with a NOP to avoid
10517 confusing RTL expansion. */
10518 if (seen_error () && is_gimple_omp (stmt))
10520 gsi_replace (gsi_p, gimple_build_nop (), true);
10521 return;
10524 switch (gimple_code (stmt))
10526 case GIMPLE_COND:
10527 if ((ctx || task_shared_vars)
10528 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
10529 ctx ? NULL : &wi, NULL)
10530 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
10531 ctx ? NULL : &wi, NULL)))
10532 gimple_regimplify_operands (stmt, gsi_p);
10533 break;
10534 case GIMPLE_CATCH:
10535 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
10536 break;
10537 case GIMPLE_EH_FILTER:
10538 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10539 break;
10540 case GIMPLE_TRY:
10541 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10542 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10543 break;
10544 case GIMPLE_TRANSACTION:
10545 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
10546 break;
10547 case GIMPLE_BIND:
10548 lower_omp (gimple_bind_body_ptr (stmt), ctx);
10549 break;
10550 case GIMPLE_OMP_PARALLEL:
10551 case GIMPLE_OMP_TASK:
10552 ctx = maybe_lookup_ctx (stmt);
10553 gcc_assert (ctx);
10554 if (ctx->cancellable)
10555 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10556 lower_omp_taskreg (gsi_p, ctx);
10557 break;
10558 case GIMPLE_OMP_FOR:
10559 ctx = maybe_lookup_ctx (stmt);
10560 gcc_assert (ctx);
10561 if (ctx->cancellable)
10562 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10563 lower_omp_for (gsi_p, ctx);
10564 break;
10565 case GIMPLE_OMP_SECTIONS:
10566 ctx = maybe_lookup_ctx (stmt);
10567 gcc_assert (ctx);
10568 if (ctx->cancellable)
10569 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10570 lower_omp_sections (gsi_p, ctx);
10571 break;
10572 case GIMPLE_OMP_SINGLE:
10573 ctx = maybe_lookup_ctx (stmt);
10574 gcc_assert (ctx);
10575 lower_omp_single (gsi_p, ctx);
10576 break;
10577 case GIMPLE_OMP_MASTER:
10578 ctx = maybe_lookup_ctx (stmt);
10579 gcc_assert (ctx);
10580 lower_omp_master (gsi_p, ctx);
10581 break;
10582 case GIMPLE_OMP_TASKGROUP:
10583 ctx = maybe_lookup_ctx (stmt);
10584 gcc_assert (ctx);
10585 lower_omp_taskgroup (gsi_p, ctx);
10586 break;
10587 case GIMPLE_OMP_ORDERED:
10588 ctx = maybe_lookup_ctx (stmt);
10589 gcc_assert (ctx);
10590 lower_omp_ordered (gsi_p, ctx);
10591 break;
10592 case GIMPLE_OMP_CRITICAL:
10593 ctx = maybe_lookup_ctx (stmt);
10594 gcc_assert (ctx);
10595 lower_omp_critical (gsi_p, ctx);
10596 break;
10597 case GIMPLE_OMP_ATOMIC_LOAD:
10598 if ((ctx || task_shared_vars)
10599 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
10600 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10601 gimple_regimplify_operands (stmt, gsi_p);
10602 break;
10603 case GIMPLE_OMP_TARGET:
10604 ctx = maybe_lookup_ctx (stmt);
10605 gcc_assert (ctx);
10606 lower_omp_target (gsi_p, ctx);
10607 break;
10608 case GIMPLE_OMP_TEAMS:
10609 ctx = maybe_lookup_ctx (stmt);
10610 gcc_assert (ctx);
10611 lower_omp_teams (gsi_p, ctx);
10612 break;
10613 case GIMPLE_CALL:
10614 tree fndecl;
10615 fndecl = gimple_call_fndecl (stmt);
10616 if (fndecl
10617 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10618 switch (DECL_FUNCTION_CODE (fndecl))
10620 case BUILT_IN_GOMP_BARRIER:
10621 if (ctx == NULL)
10622 break;
10623 /* FALLTHRU */
10624 case BUILT_IN_GOMP_CANCEL:
10625 case BUILT_IN_GOMP_CANCELLATION_POINT:
10626 omp_context *cctx;
10627 cctx = ctx;
10628 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10629 cctx = cctx->outer;
10630 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10631 if (!cctx->cancellable)
10633 if (DECL_FUNCTION_CODE (fndecl)
10634 == BUILT_IN_GOMP_CANCELLATION_POINT)
10636 stmt = gimple_build_nop ();
10637 gsi_replace (gsi_p, stmt, false);
10639 break;
10641 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10643 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10644 gimple_call_set_fndecl (stmt, fndecl);
10645 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10647 tree lhs;
10648 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
10649 gimple_call_set_lhs (stmt, lhs);
10650 tree fallthru_label;
10651 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10652 gimple g;
10653 g = gimple_build_label (fallthru_label);
10654 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10655 g = gimple_build_cond (NE_EXPR, lhs,
10656 fold_convert (TREE_TYPE (lhs),
10657 boolean_false_node),
10658 cctx->cancel_label, fallthru_label);
10659 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10660 break;
10661 default:
10662 break;
10664 /* FALLTHRU */
10665 default:
10666 if ((ctx || task_shared_vars)
10667 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10668 ctx ? NULL : &wi))
10670 /* Just remove clobbers, this should happen only if we have
10671 "privatized" local addressable variables in SIMD regions,
10672 the clobber isn't needed in that case and gimplifying address
10673 of the ARRAY_REF into a pointer and creating MEM_REF based
10674 clobber would create worse code than we get with the clobber
10675 dropped. */
10676 if (gimple_clobber_p (stmt))
10678 gsi_replace (gsi_p, gimple_build_nop (), true);
10679 break;
10681 gimple_regimplify_operands (stmt, gsi_p);
10683 break;
10687 static void
10688 lower_omp (gimple_seq *body, omp_context *ctx)
10690 location_t saved_location = input_location;
10691 gimple_stmt_iterator gsi;
10692 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10693 lower_omp_1 (&gsi, ctx);
10694 /* During gimplification, we have not always invoked fold_stmt
10695 (gimplify.c:maybe_fold_stmt); call it now. */
10696 if (target_nesting_level)
10697 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10698 fold_stmt (&gsi);
10699 input_location = saved_location;
10702 /* Main entry point. */
10704 static unsigned int
10705 execute_lower_omp (void)
10707 gimple_seq body;
10708 int i;
10709 omp_context *ctx;
10711 /* This pass always runs, to provide PROP_gimple_lomp.
10712 But there is nothing to do unless -fopenmp is given. */
10713 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10714 return 0;
10716 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10717 delete_omp_context);
10719 body = gimple_body (current_function_decl);
10720 scan_omp (&body, NULL);
10721 gcc_assert (taskreg_nesting_level == 0);
10722 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
10723 finish_taskreg_scan (ctx);
10724 taskreg_contexts.release ();
10726 if (all_contexts->root)
10728 if (task_shared_vars)
10729 push_gimplify_context ();
10730 lower_omp (&body, NULL);
10731 if (task_shared_vars)
10732 pop_gimplify_context (NULL);
10735 if (all_contexts)
10737 splay_tree_delete (all_contexts);
10738 all_contexts = NULL;
10740 BITMAP_FREE (task_shared_vars);
10741 return 0;
10744 namespace {
10746 const pass_data pass_data_lower_omp =
10748 GIMPLE_PASS, /* type */
10749 "omplower", /* name */
10750 OPTGROUP_NONE, /* optinfo_flags */
10751 TV_NONE, /* tv_id */
10752 PROP_gimple_any, /* properties_required */
10753 PROP_gimple_lomp, /* properties_provided */
10754 0, /* properties_destroyed */
10755 0, /* todo_flags_start */
10756 0, /* todo_flags_finish */
10759 class pass_lower_omp : public gimple_opt_pass
10761 public:
10762 pass_lower_omp (gcc::context *ctxt)
10763 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10766 /* opt_pass methods: */
10767 virtual unsigned int execute (function *) { return execute_lower_omp (); }
10769 }; // class pass_lower_omp
10771 } // anon namespace
10773 gimple_opt_pass *
10774 make_pass_lower_omp (gcc::context *ctxt)
10776 return new pass_lower_omp (ctxt);
10779 /* The following is a utility to diagnose OpenMP structured block violations.
10780 It is not part of the "omplower" pass, as that's invoked too late. It
10781 should be invoked by the respective front ends after gimplification. */
10783 static splay_tree all_labels;
10785 /* Check for mismatched contexts and generate an error if needed. Return
10786 true if an error is detected. */
10788 static bool
10789 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10790 gimple branch_ctx, gimple label_ctx)
10792 if (label_ctx == branch_ctx)
10793 return false;
10797 Previously we kept track of the label's entire context in diagnose_sb_[12]
10798 so we could traverse it and issue a correct "exit" or "enter" error
10799 message upon a structured block violation.
10801 We built the context by building a list with tree_cons'ing, but there is
10802 no easy counterpart in gimple tuples. It seems like far too much work
10803 for issuing exit/enter error messages. If someone really misses the
10804 distinct error message... patches welcome.
10807 #if 0
10808 /* Try to avoid confusing the user by producing and error message
10809 with correct "exit" or "enter" verbiage. We prefer "exit"
10810 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10811 if (branch_ctx == NULL)
10812 exit_p = false;
10813 else
10815 while (label_ctx)
10817 if (TREE_VALUE (label_ctx) == branch_ctx)
10819 exit_p = false;
10820 break;
10822 label_ctx = TREE_CHAIN (label_ctx);
10826 if (exit_p)
10827 error ("invalid exit from OpenMP structured block");
10828 else
10829 error ("invalid entry to OpenMP structured block");
10830 #endif
10832 bool cilkplus_block = false;
10833 if (flag_cilkplus)
10835 if ((branch_ctx
10836 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10837 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10838 || (label_ctx
10839 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10840 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10841 cilkplus_block = true;
10844 /* If it's obvious we have an invalid entry, be specific about the error. */
10845 if (branch_ctx == NULL)
10847 if (cilkplus_block)
10848 error ("invalid entry to Cilk Plus structured block");
10849 else
10850 error ("invalid entry to OpenMP structured block");
10852 else
10854 /* Otherwise, be vague and lazy, but efficient. */
10855 if (cilkplus_block)
10856 error ("invalid branch to/from a Cilk Plus structured block");
10857 else
10858 error ("invalid branch to/from an OpenMP structured block");
10861 gsi_replace (gsi_p, gimple_build_nop (), false);
10862 return true;
10865 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10866 where each label is found. */
10868 static tree
10869 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10870 struct walk_stmt_info *wi)
10872 gimple context = (gimple) wi->info;
10873 gimple inner_context;
10874 gimple stmt = gsi_stmt (*gsi_p);
10876 *handled_ops_p = true;
10878 switch (gimple_code (stmt))
10880 WALK_SUBSTMTS;
10882 case GIMPLE_OMP_PARALLEL:
10883 case GIMPLE_OMP_TASK:
10884 case GIMPLE_OMP_SECTIONS:
10885 case GIMPLE_OMP_SINGLE:
10886 case GIMPLE_OMP_SECTION:
10887 case GIMPLE_OMP_MASTER:
10888 case GIMPLE_OMP_ORDERED:
10889 case GIMPLE_OMP_CRITICAL:
10890 case GIMPLE_OMP_TARGET:
10891 case GIMPLE_OMP_TEAMS:
10892 case GIMPLE_OMP_TASKGROUP:
10893 /* The minimal context here is just the current OMP construct. */
10894 inner_context = stmt;
10895 wi->info = inner_context;
10896 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10897 wi->info = context;
10898 break;
10900 case GIMPLE_OMP_FOR:
10901 inner_context = stmt;
10902 wi->info = inner_context;
10903 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10904 walk them. */
10905 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10906 diagnose_sb_1, NULL, wi);
10907 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10908 wi->info = context;
10909 break;
10911 case GIMPLE_LABEL:
10912 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10913 (splay_tree_value) context);
10914 break;
10916 default:
10917 break;
10920 return NULL_TREE;
10923 /* Pass 2: Check each branch and see if its context differs from that of
10924 the destination label's context. */
10926 static tree
10927 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10928 struct walk_stmt_info *wi)
10930 gimple context = (gimple) wi->info;
10931 splay_tree_node n;
10932 gimple stmt = gsi_stmt (*gsi_p);
10934 *handled_ops_p = true;
10936 switch (gimple_code (stmt))
10938 WALK_SUBSTMTS;
10940 case GIMPLE_OMP_PARALLEL:
10941 case GIMPLE_OMP_TASK:
10942 case GIMPLE_OMP_SECTIONS:
10943 case GIMPLE_OMP_SINGLE:
10944 case GIMPLE_OMP_SECTION:
10945 case GIMPLE_OMP_MASTER:
10946 case GIMPLE_OMP_ORDERED:
10947 case GIMPLE_OMP_CRITICAL:
10948 case GIMPLE_OMP_TARGET:
10949 case GIMPLE_OMP_TEAMS:
10950 case GIMPLE_OMP_TASKGROUP:
10951 wi->info = stmt;
10952 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10953 wi->info = context;
10954 break;
10956 case GIMPLE_OMP_FOR:
10957 wi->info = stmt;
10958 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10959 walk them. */
10960 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10961 diagnose_sb_2, NULL, wi);
10962 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10963 wi->info = context;
10964 break;
10966 case GIMPLE_COND:
10968 tree lab = gimple_cond_true_label (stmt);
10969 if (lab)
10971 n = splay_tree_lookup (all_labels,
10972 (splay_tree_key) lab);
10973 diagnose_sb_0 (gsi_p, context,
10974 n ? (gimple) n->value : NULL);
10976 lab = gimple_cond_false_label (stmt);
10977 if (lab)
10979 n = splay_tree_lookup (all_labels,
10980 (splay_tree_key) lab);
10981 diagnose_sb_0 (gsi_p, context,
10982 n ? (gimple) n->value : NULL);
10985 break;
10987 case GIMPLE_GOTO:
10989 tree lab = gimple_goto_dest (stmt);
10990 if (TREE_CODE (lab) != LABEL_DECL)
10991 break;
10993 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10994 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10996 break;
10998 case GIMPLE_SWITCH:
11000 unsigned int i;
11001 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
11003 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
11004 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
11005 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
11006 break;
11009 break;
11011 case GIMPLE_RETURN:
11012 diagnose_sb_0 (gsi_p, context, NULL);
11013 break;
11015 default:
11016 break;
11019 return NULL_TREE;
11022 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
11023 codes. */
11024 bool
11025 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
11026 int *region_idx)
11028 gimple last = last_stmt (bb);
11029 enum gimple_code code = gimple_code (last);
11030 struct omp_region *cur_region = *region;
11031 bool fallthru = false;
11033 switch (code)
11035 case GIMPLE_OMP_PARALLEL:
11036 case GIMPLE_OMP_TASK:
11037 case GIMPLE_OMP_FOR:
11038 case GIMPLE_OMP_SINGLE:
11039 case GIMPLE_OMP_TEAMS:
11040 case GIMPLE_OMP_MASTER:
11041 case GIMPLE_OMP_TASKGROUP:
11042 case GIMPLE_OMP_ORDERED:
11043 case GIMPLE_OMP_CRITICAL:
11044 case GIMPLE_OMP_SECTION:
11045 cur_region = new_omp_region (bb, code, cur_region);
11046 fallthru = true;
11047 break;
11049 case GIMPLE_OMP_TARGET:
11050 cur_region = new_omp_region (bb, code, cur_region);
11051 fallthru = true;
11052 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
11053 cur_region = cur_region->outer;
11054 break;
11056 case GIMPLE_OMP_SECTIONS:
11057 cur_region = new_omp_region (bb, code, cur_region);
11058 fallthru = true;
11059 break;
11061 case GIMPLE_OMP_SECTIONS_SWITCH:
11062 fallthru = false;
11063 break;
11065 case GIMPLE_OMP_ATOMIC_LOAD:
11066 case GIMPLE_OMP_ATOMIC_STORE:
11067 fallthru = true;
11068 break;
11070 case GIMPLE_OMP_RETURN:
11071 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
11072 somewhere other than the next block. This will be
11073 created later. */
11074 cur_region->exit = bb;
11075 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
11076 cur_region = cur_region->outer;
11077 break;
11079 case GIMPLE_OMP_CONTINUE:
11080 cur_region->cont = bb;
11081 switch (cur_region->type)
11083 case GIMPLE_OMP_FOR:
11084 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11085 succs edges as abnormal to prevent splitting
11086 them. */
11087 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
11088 /* Make the loopback edge. */
11089 make_edge (bb, single_succ (cur_region->entry),
11090 EDGE_ABNORMAL);
11092 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11093 corresponds to the case that the body of the loop
11094 is not executed at all. */
11095 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
11096 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
11097 fallthru = false;
11098 break;
11100 case GIMPLE_OMP_SECTIONS:
11101 /* Wire up the edges into and out of the nested sections. */
11103 basic_block switch_bb = single_succ (cur_region->entry);
11105 struct omp_region *i;
11106 for (i = cur_region->inner; i ; i = i->next)
11108 gcc_assert (i->type == GIMPLE_OMP_SECTION);
11109 make_edge (switch_bb, i->entry, 0);
11110 make_edge (i->exit, bb, EDGE_FALLTHRU);
11113 /* Make the loopback edge to the block with
11114 GIMPLE_OMP_SECTIONS_SWITCH. */
11115 make_edge (bb, switch_bb, 0);
11117 /* Make the edge from the switch to exit. */
11118 make_edge (switch_bb, bb->next_bb, 0);
11119 fallthru = false;
11121 break;
11123 default:
11124 gcc_unreachable ();
11126 break;
11128 default:
11129 gcc_unreachable ();
11132 if (*region != cur_region)
11134 *region = cur_region;
11135 if (cur_region)
11136 *region_idx = cur_region->entry->index;
11137 else
11138 *region_idx = 0;
11141 return fallthru;
11144 static unsigned int
11145 diagnose_omp_structured_block_errors (void)
11147 struct walk_stmt_info wi;
11148 gimple_seq body = gimple_body (current_function_decl);
11150 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
11152 memset (&wi, 0, sizeof (wi));
11153 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
11155 memset (&wi, 0, sizeof (wi));
11156 wi.want_locations = true;
11157 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
11159 gimple_set_body (current_function_decl, body);
11161 splay_tree_delete (all_labels);
11162 all_labels = NULL;
11164 return 0;
11167 namespace {
11169 const pass_data pass_data_diagnose_omp_blocks =
11171 GIMPLE_PASS, /* type */
11172 "*diagnose_omp_blocks", /* name */
11173 OPTGROUP_NONE, /* optinfo_flags */
11174 TV_NONE, /* tv_id */
11175 PROP_gimple_any, /* properties_required */
11176 0, /* properties_provided */
11177 0, /* properties_destroyed */
11178 0, /* todo_flags_start */
11179 0, /* todo_flags_finish */
11182 class pass_diagnose_omp_blocks : public gimple_opt_pass
11184 public:
11185 pass_diagnose_omp_blocks (gcc::context *ctxt)
11186 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
11189 /* opt_pass methods: */
11190 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
11191 virtual unsigned int execute (function *)
11193 return diagnose_omp_structured_block_errors ();
11196 }; // class pass_diagnose_omp_blocks
11198 } // anon namespace
11200 gimple_opt_pass *
11201 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
11203 return new pass_diagnose_omp_blocks (ctxt);
11206 /* SIMD clone supporting code. */
11208 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11209 of arguments to reserve space for. */
11211 static struct cgraph_simd_clone *
11212 simd_clone_struct_alloc (int nargs)
11214 struct cgraph_simd_clone *clone_info;
11215 size_t len = (sizeof (struct cgraph_simd_clone)
11216 + nargs * sizeof (struct cgraph_simd_clone_arg));
11217 clone_info = (struct cgraph_simd_clone *)
11218 ggc_internal_cleared_alloc (len);
11219 return clone_info;
11222 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11224 static inline void
11225 simd_clone_struct_copy (struct cgraph_simd_clone *to,
11226 struct cgraph_simd_clone *from)
11228 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
11229 + ((from->nargs - from->inbranch)
11230 * sizeof (struct cgraph_simd_clone_arg))));
11233 /* Return vector of parameter types of function FNDECL. This uses
11234 TYPE_ARG_TYPES if available, otherwise falls back to types of
11235 DECL_ARGUMENTS types. */
11237 vec<tree>
11238 simd_clone_vector_of_formal_parm_types (tree fndecl)
11240 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
11241 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
11242 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
11243 unsigned int i;
11244 tree arg;
11245 FOR_EACH_VEC_ELT (args, i, arg)
11246 args[i] = TREE_TYPE (args[i]);
11247 return args;
11250 /* Given a simd function in NODE, extract the simd specific
11251 information from the OMP clauses passed in CLAUSES, and return
11252 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11253 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11254 otherwise set to FALSE. */
11256 static struct cgraph_simd_clone *
11257 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
11258 bool *inbranch_specified)
11260 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
11261 tree t;
11262 int n;
11263 *inbranch_specified = false;
11265 n = args.length ();
11266 if (n > 0 && args.last () == void_type_node)
11267 n--;
11269 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11270 be cloned have a distinctive artificial label in addition to "omp
11271 declare simd". */
11272 bool cilk_clone
11273 = (flag_cilkplus
11274 && lookup_attribute ("cilk simd function",
11275 DECL_ATTRIBUTES (node->decl)));
11277 /* Allocate one more than needed just in case this is an in-branch
11278 clone which will require a mask argument. */
11279 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
11280 clone_info->nargs = n;
11281 clone_info->cilk_elemental = cilk_clone;
11283 if (!clauses)
11285 args.release ();
11286 return clone_info;
11288 clauses = TREE_VALUE (clauses);
11289 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
11290 return clone_info;
11292 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
11294 switch (OMP_CLAUSE_CODE (t))
11296 case OMP_CLAUSE_INBRANCH:
11297 clone_info->inbranch = 1;
11298 *inbranch_specified = true;
11299 break;
11300 case OMP_CLAUSE_NOTINBRANCH:
11301 clone_info->inbranch = 0;
11302 *inbranch_specified = true;
11303 break;
11304 case OMP_CLAUSE_SIMDLEN:
11305 clone_info->simdlen
11306 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
11307 break;
11308 case OMP_CLAUSE_LINEAR:
11310 tree decl = OMP_CLAUSE_DECL (t);
11311 tree step = OMP_CLAUSE_LINEAR_STEP (t);
11312 int argno = TREE_INT_CST_LOW (decl);
11313 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
11315 clone_info->args[argno].arg_type
11316 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
11317 clone_info->args[argno].linear_step = tree_to_shwi (step);
11318 gcc_assert (clone_info->args[argno].linear_step >= 0
11319 && clone_info->args[argno].linear_step < n);
11321 else
11323 if (POINTER_TYPE_P (args[argno]))
11324 step = fold_convert (ssizetype, step);
11325 if (!tree_fits_shwi_p (step))
11327 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11328 "ignoring large linear step");
11329 args.release ();
11330 return NULL;
11332 else if (integer_zerop (step))
11334 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11335 "ignoring zero linear step");
11336 args.release ();
11337 return NULL;
11339 else
11341 clone_info->args[argno].arg_type
11342 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
11343 clone_info->args[argno].linear_step = tree_to_shwi (step);
11346 break;
11348 case OMP_CLAUSE_UNIFORM:
11350 tree decl = OMP_CLAUSE_DECL (t);
11351 int argno = tree_to_uhwi (decl);
11352 clone_info->args[argno].arg_type
11353 = SIMD_CLONE_ARG_TYPE_UNIFORM;
11354 break;
11356 case OMP_CLAUSE_ALIGNED:
11358 tree decl = OMP_CLAUSE_DECL (t);
11359 int argno = tree_to_uhwi (decl);
11360 clone_info->args[argno].alignment
11361 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
11362 break;
11364 default:
11365 break;
11368 args.release ();
11369 return clone_info;
11372 /* Given a SIMD clone in NODE, calculate the characteristic data
11373 type and return the coresponding type. The characteristic data
11374 type is computed as described in the Intel Vector ABI. */
11376 static tree
11377 simd_clone_compute_base_data_type (struct cgraph_node *node,
11378 struct cgraph_simd_clone *clone_info)
11380 tree type = integer_type_node;
11381 tree fndecl = node->decl;
11383 /* a) For non-void function, the characteristic data type is the
11384 return type. */
11385 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
11386 type = TREE_TYPE (TREE_TYPE (fndecl));
11388 /* b) If the function has any non-uniform, non-linear parameters,
11389 then the characteristic data type is the type of the first
11390 such parameter. */
11391 else
11393 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
11394 for (unsigned int i = 0; i < clone_info->nargs; ++i)
11395 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
11397 type = map[i];
11398 break;
11400 map.release ();
11403 /* c) If the characteristic data type determined by a) or b) above
11404 is struct, union, or class type which is pass-by-value (except
11405 for the type that maps to the built-in complex data type), the
11406 characteristic data type is int. */
11407 if (RECORD_OR_UNION_TYPE_P (type)
11408 && !aggregate_value_p (type, NULL)
11409 && TREE_CODE (type) != COMPLEX_TYPE)
11410 return integer_type_node;
11412 /* d) If none of the above three classes is applicable, the
11413 characteristic data type is int. */
11415 return type;
11417 /* e) For Intel Xeon Phi native and offload compilation, if the
11418 resulting characteristic data type is 8-bit or 16-bit integer
11419 data type, the characteristic data type is int. */
11420 /* Well, we don't handle Xeon Phi yet. */
11423 static tree
11424 simd_clone_mangle (struct cgraph_node *node,
11425 struct cgraph_simd_clone *clone_info)
11427 char vecsize_mangle = clone_info->vecsize_mangle;
11428 char mask = clone_info->inbranch ? 'M' : 'N';
11429 unsigned int simdlen = clone_info->simdlen;
11430 unsigned int n;
11431 pretty_printer pp;
11433 gcc_assert (vecsize_mangle && simdlen);
11435 pp_string (&pp, "_ZGV");
11436 pp_character (&pp, vecsize_mangle);
11437 pp_character (&pp, mask);
11438 pp_decimal_int (&pp, simdlen);
11440 for (n = 0; n < clone_info->nargs; ++n)
11442 struct cgraph_simd_clone_arg arg = clone_info->args[n];
11444 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
11445 pp_character (&pp, 'u');
11446 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11448 gcc_assert (arg.linear_step != 0);
11449 pp_character (&pp, 'l');
11450 if (arg.linear_step > 1)
11451 pp_unsigned_wide_integer (&pp, arg.linear_step);
11452 else if (arg.linear_step < 0)
11454 pp_character (&pp, 'n');
11455 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
11456 arg.linear_step));
11459 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11461 pp_character (&pp, 's');
11462 pp_unsigned_wide_integer (&pp, arg.linear_step);
11464 else
11465 pp_character (&pp, 'v');
11466 if (arg.alignment)
11468 pp_character (&pp, 'a');
11469 pp_decimal_int (&pp, arg.alignment);
11473 pp_underscore (&pp);
11474 pp_string (&pp,
11475 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11476 const char *str = pp_formatted_text (&pp);
11478 /* If there already is a SIMD clone with the same mangled name, don't
11479 add another one. This can happen e.g. for
11480 #pragma omp declare simd
11481 #pragma omp declare simd simdlen(8)
11482 int foo (int, int);
11483 if the simdlen is assumed to be 8 for the first one, etc. */
11484 for (struct cgraph_node *clone = node->simd_clones; clone;
11485 clone = clone->simdclone->next_clone)
11486 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11487 str) == 0)
11488 return NULL_TREE;
11490 return get_identifier (str);
11493 /* Create a simd clone of OLD_NODE and return it. */
11495 static struct cgraph_node *
11496 simd_clone_create (struct cgraph_node *old_node)
11498 struct cgraph_node *new_node;
11499 if (old_node->definition)
11501 if (!old_node->has_gimple_body_p ())
11502 return NULL;
11503 old_node->get_body ();
11504 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
11505 false, NULL, NULL,
11506 "simdclone");
11508 else
11510 tree old_decl = old_node->decl;
11511 tree new_decl = copy_node (old_node->decl);
11512 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11513 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11514 SET_DECL_RTL (new_decl, NULL);
11515 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11516 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11517 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
11518 symtab->call_cgraph_insertion_hooks (new_node);
11520 if (new_node == NULL)
11521 return new_node;
11523 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11525 /* The function cgraph_function_versioning () will force the new
11526 symbol local. Undo this, and inherit external visability from
11527 the old node. */
11528 new_node->local.local = old_node->local.local;
11529 new_node->externally_visible = old_node->externally_visible;
11531 return new_node;
11534 /* Adjust the return type of the given function to its appropriate
11535 vector counterpart. Returns a simd array to be used throughout the
11536 function as a return value. */
11538 static tree
11539 simd_clone_adjust_return_type (struct cgraph_node *node)
11541 tree fndecl = node->decl;
11542 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11543 unsigned int veclen;
11544 tree t;
11546 /* Adjust the function return type. */
11547 if (orig_rettype == void_type_node)
11548 return NULL_TREE;
11549 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11550 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11551 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11552 veclen = node->simdclone->vecsize_int;
11553 else
11554 veclen = node->simdclone->vecsize_float;
11555 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11556 if (veclen > node->simdclone->simdlen)
11557 veclen = node->simdclone->simdlen;
11558 if (veclen == node->simdclone->simdlen)
11559 TREE_TYPE (TREE_TYPE (fndecl))
11560 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11561 node->simdclone->simdlen);
11562 else
11564 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11565 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11566 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11568 if (!node->definition)
11569 return NULL_TREE;
11571 t = DECL_RESULT (fndecl);
11572 /* Adjust the DECL_RESULT. */
11573 gcc_assert (TREE_TYPE (t) != void_type_node);
11574 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11575 relayout_decl (t);
11577 tree atype = build_array_type_nelts (orig_rettype,
11578 node->simdclone->simdlen);
11579 if (veclen != node->simdclone->simdlen)
11580 return build1 (VIEW_CONVERT_EXPR, atype, t);
11582 /* Set up a SIMD array to use as the return value. */
11583 tree retval = create_tmp_var_raw (atype, "retval");
11584 gimple_add_tmp_var (retval);
11585 return retval;
11588 /* Each vector argument has a corresponding array to be used locally
11589 as part of the eventual loop. Create such temporary array and
11590 return it.
11592 PREFIX is the prefix to be used for the temporary.
11594 TYPE is the inner element type.
11596 SIMDLEN is the number of elements. */
11598 static tree
11599 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11601 tree atype = build_array_type_nelts (type, simdlen);
11602 tree avar = create_tmp_var_raw (atype, prefix);
11603 gimple_add_tmp_var (avar);
11604 return avar;
11607 /* Modify the function argument types to their corresponding vector
11608 counterparts if appropriate. Also, create one array for each simd
11609 argument to be used locally when using the function arguments as
11610 part of the loop.
11612 NODE is the function whose arguments are to be adjusted.
11614 Returns an adjustment vector that will be filled describing how the
11615 argument types will be adjusted. */
11617 static ipa_parm_adjustment_vec
11618 simd_clone_adjust_argument_types (struct cgraph_node *node)
11620 vec<tree> args;
11621 ipa_parm_adjustment_vec adjustments;
11623 if (node->definition)
11624 args = ipa_get_vector_of_formal_parms (node->decl);
11625 else
11626 args = simd_clone_vector_of_formal_parm_types (node->decl);
11627 adjustments.create (args.length ());
11628 unsigned i, j, veclen;
11629 struct ipa_parm_adjustment adj;
11630 for (i = 0; i < node->simdclone->nargs; ++i)
11632 memset (&adj, 0, sizeof (adj));
11633 tree parm = args[i];
11634 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11635 adj.base_index = i;
11636 adj.base = parm;
11638 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11639 node->simdclone->args[i].orig_type = parm_type;
11641 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11643 /* No adjustment necessary for scalar arguments. */
11644 adj.op = IPA_PARM_OP_COPY;
11646 else
11648 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11649 veclen = node->simdclone->vecsize_int;
11650 else
11651 veclen = node->simdclone->vecsize_float;
11652 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11653 if (veclen > node->simdclone->simdlen)
11654 veclen = node->simdclone->simdlen;
11655 adj.arg_prefix = "simd";
11656 adj.type = build_vector_type (parm_type, veclen);
11657 node->simdclone->args[i].vector_type = adj.type;
11658 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11660 adjustments.safe_push (adj);
11661 if (j == veclen)
11663 memset (&adj, 0, sizeof (adj));
11664 adj.op = IPA_PARM_OP_NEW;
11665 adj.arg_prefix = "simd";
11666 adj.base_index = i;
11667 adj.type = node->simdclone->args[i].vector_type;
11671 if (node->definition)
11672 node->simdclone->args[i].simd_array
11673 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11674 parm_type, node->simdclone->simdlen);
11676 adjustments.safe_push (adj);
11679 if (node->simdclone->inbranch)
11681 tree base_type
11682 = simd_clone_compute_base_data_type (node->simdclone->origin,
11683 node->simdclone);
11685 memset (&adj, 0, sizeof (adj));
11686 adj.op = IPA_PARM_OP_NEW;
11687 adj.arg_prefix = "mask";
11689 adj.base_index = i;
11690 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11691 veclen = node->simdclone->vecsize_int;
11692 else
11693 veclen = node->simdclone->vecsize_float;
11694 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11695 if (veclen > node->simdclone->simdlen)
11696 veclen = node->simdclone->simdlen;
11697 adj.type = build_vector_type (base_type, veclen);
11698 adjustments.safe_push (adj);
11700 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11701 adjustments.safe_push (adj);
11703 /* We have previously allocated one extra entry for the mask. Use
11704 it and fill it. */
11705 struct cgraph_simd_clone *sc = node->simdclone;
11706 sc->nargs++;
11707 if (node->definition)
11709 sc->args[i].orig_arg
11710 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11711 sc->args[i].simd_array
11712 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11714 sc->args[i].orig_type = base_type;
11715 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11718 if (node->definition)
11719 ipa_modify_formal_parameters (node->decl, adjustments);
11720 else
11722 tree new_arg_types = NULL_TREE, new_reversed;
11723 bool last_parm_void = false;
11724 if (args.length () > 0 && args.last () == void_type_node)
11725 last_parm_void = true;
11727 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11728 j = adjustments.length ();
11729 for (i = 0; i < j; i++)
11731 struct ipa_parm_adjustment *adj = &adjustments[i];
11732 tree ptype;
11733 if (adj->op == IPA_PARM_OP_COPY)
11734 ptype = args[adj->base_index];
11735 else
11736 ptype = adj->type;
11737 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11739 new_reversed = nreverse (new_arg_types);
11740 if (last_parm_void)
11742 if (new_reversed)
11743 TREE_CHAIN (new_arg_types) = void_list_node;
11744 else
11745 new_reversed = void_list_node;
11748 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11749 TYPE_ARG_TYPES (new_type) = new_reversed;
11750 TREE_TYPE (node->decl) = new_type;
11752 adjustments.release ();
11754 args.release ();
11755 return adjustments;
11758 /* Initialize and copy the function arguments in NODE to their
11759 corresponding local simd arrays. Returns a fresh gimple_seq with
11760 the instruction sequence generated. */
11762 static gimple_seq
11763 simd_clone_init_simd_arrays (struct cgraph_node *node,
11764 ipa_parm_adjustment_vec adjustments)
11766 gimple_seq seq = NULL;
11767 unsigned i = 0, j = 0, k;
11769 for (tree arg = DECL_ARGUMENTS (node->decl);
11770 arg;
11771 arg = DECL_CHAIN (arg), i++, j++)
11773 if (adjustments[j].op == IPA_PARM_OP_COPY)
11774 continue;
11776 node->simdclone->args[i].vector_arg = arg;
11778 tree array = node->simdclone->args[i].simd_array;
11779 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11781 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11782 tree ptr = build_fold_addr_expr (array);
11783 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11784 build_int_cst (ptype, 0));
11785 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11786 gimplify_and_add (t, &seq);
11788 else
11790 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11791 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11792 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11794 tree ptr = build_fold_addr_expr (array);
11795 int elemsize;
11796 if (k)
11798 arg = DECL_CHAIN (arg);
11799 j++;
11801 elemsize
11802 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11803 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11804 build_int_cst (ptype, k * elemsize));
11805 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11806 gimplify_and_add (t, &seq);
11810 return seq;
11813 /* Callback info for ipa_simd_modify_stmt_ops below. */
11815 struct modify_stmt_info {
11816 ipa_parm_adjustment_vec adjustments;
11817 gimple stmt;
11818 /* True if the parent statement was modified by
11819 ipa_simd_modify_stmt_ops. */
11820 bool modified;
11823 /* Callback for walk_gimple_op.
11825 Adjust operands from a given statement as specified in the
11826 adjustments vector in the callback data. */
11828 static tree
11829 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11831 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11832 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11833 tree *orig_tp = tp;
11834 if (TREE_CODE (*tp) == ADDR_EXPR)
11835 tp = &TREE_OPERAND (*tp, 0);
11836 struct ipa_parm_adjustment *cand = NULL;
11837 if (TREE_CODE (*tp) == PARM_DECL)
11838 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11839 else
11841 if (TYPE_P (*tp))
11842 *walk_subtrees = 0;
11845 tree repl = NULL_TREE;
11846 if (cand)
11847 repl = unshare_expr (cand->new_decl);
11848 else
11850 if (tp != orig_tp)
11852 *walk_subtrees = 0;
11853 bool modified = info->modified;
11854 info->modified = false;
11855 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11856 if (!info->modified)
11858 info->modified = modified;
11859 return NULL_TREE;
11861 info->modified = modified;
11862 repl = *tp;
11864 else
11865 return NULL_TREE;
11868 if (tp != orig_tp)
11870 repl = build_fold_addr_expr (repl);
11871 gimple stmt;
11872 if (is_gimple_debug (info->stmt))
11874 tree vexpr = make_node (DEBUG_EXPR_DECL);
11875 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
11876 DECL_ARTIFICIAL (vexpr) = 1;
11877 TREE_TYPE (vexpr) = TREE_TYPE (repl);
11878 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
11879 repl = vexpr;
11881 else
11883 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl),
11884 NULL), repl);
11885 repl = gimple_assign_lhs (stmt);
11887 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11888 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11889 *orig_tp = repl;
11891 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11893 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11894 *tp = vce;
11896 else
11897 *tp = repl;
11899 info->modified = true;
11900 return NULL_TREE;
11903 /* Traverse the function body and perform all modifications as
11904 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11905 modified such that the replacement/reduction value will now be an
11906 offset into the corresponding simd_array.
11908 This function will replace all function argument uses with their
11909 corresponding simd array elements, and ajust the return values
11910 accordingly. */
11912 static void
11913 ipa_simd_modify_function_body (struct cgraph_node *node,
11914 ipa_parm_adjustment_vec adjustments,
11915 tree retval_array, tree iter)
11917 basic_block bb;
11918 unsigned int i, j, l;
11920 /* Re-use the adjustments array, but this time use it to replace
11921 every function argument use to an offset into the corresponding
11922 simd_array. */
11923 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11925 if (!node->simdclone->args[i].vector_arg)
11926 continue;
11928 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11929 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11930 adjustments[j].new_decl
11931 = build4 (ARRAY_REF,
11932 basetype,
11933 node->simdclone->args[i].simd_array,
11934 iter,
11935 NULL_TREE, NULL_TREE);
11936 if (adjustments[j].op == IPA_PARM_OP_NONE
11937 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11938 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11941 l = adjustments.length ();
11942 for (i = 1; i < num_ssa_names; i++)
11944 tree name = ssa_name (i);
11945 if (name
11946 && SSA_NAME_VAR (name)
11947 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11949 for (j = 0; j < l; j++)
11950 if (SSA_NAME_VAR (name) == adjustments[j].base
11951 && adjustments[j].new_decl)
11953 tree base_var;
11954 if (adjustments[j].new_ssa_base == NULL_TREE)
11956 base_var
11957 = copy_var_decl (adjustments[j].base,
11958 DECL_NAME (adjustments[j].base),
11959 TREE_TYPE (adjustments[j].base));
11960 adjustments[j].new_ssa_base = base_var;
11962 else
11963 base_var = adjustments[j].new_ssa_base;
11964 if (SSA_NAME_IS_DEFAULT_DEF (name))
11966 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11967 gimple_stmt_iterator gsi = gsi_after_labels (bb);
11968 tree new_decl = unshare_expr (adjustments[j].new_decl);
11969 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
11970 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11971 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
11972 gimple stmt = gimple_build_assign (name, new_decl);
11973 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11975 else
11976 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11981 struct modify_stmt_info info;
11982 info.adjustments = adjustments;
11984 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
11986 gimple_stmt_iterator gsi;
11988 gsi = gsi_start_bb (bb);
11989 while (!gsi_end_p (gsi))
11991 gimple stmt = gsi_stmt (gsi);
11992 info.stmt = stmt;
11993 struct walk_stmt_info wi;
11995 memset (&wi, 0, sizeof (wi));
11996 info.modified = false;
11997 wi.info = &info;
11998 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
12000 if (gimple_code (stmt) == GIMPLE_RETURN)
12002 tree retval = gimple_return_retval (stmt);
12003 if (!retval)
12005 gsi_remove (&gsi, true);
12006 continue;
12009 /* Replace `return foo' with `retval_array[iter] = foo'. */
12010 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
12011 retval_array, iter, NULL, NULL);
12012 stmt = gimple_build_assign (ref, retval);
12013 gsi_replace (&gsi, stmt, true);
12014 info.modified = true;
12017 if (info.modified)
12019 update_stmt (stmt);
12020 if (maybe_clean_eh_stmt (stmt))
12021 gimple_purge_dead_eh_edges (gimple_bb (stmt));
12023 gsi_next (&gsi);
12028 /* Adjust the argument types in NODE to their appropriate vector
12029 counterparts. */
12031 static void
12032 simd_clone_adjust (struct cgraph_node *node)
12034 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
12036 targetm.simd_clone.adjust (node);
12038 tree retval = simd_clone_adjust_return_type (node);
12039 ipa_parm_adjustment_vec adjustments
12040 = simd_clone_adjust_argument_types (node);
12042 push_gimplify_context ();
12044 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
12046 /* Adjust all uses of vector arguments accordingly. Adjust all
12047 return values accordingly. */
12048 tree iter = create_tmp_var (unsigned_type_node, "iter");
12049 tree iter1 = make_ssa_name (iter, NULL);
12050 tree iter2 = make_ssa_name (iter, NULL);
12051 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
12053 /* Initialize the iteration variable. */
12054 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12055 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
12056 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
12057 /* Insert the SIMD array and iv initialization at function
12058 entry. */
12059 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
12061 pop_gimplify_context (NULL);
12063 /* Create a new BB right before the original exit BB, to hold the
12064 iteration increment and the condition/branch. */
12065 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
12066 basic_block incr_bb = create_empty_bb (orig_exit);
12067 add_bb_to_loop (incr_bb, body_bb->loop_father);
12068 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
12069 flag. Set it now to be a FALLTHRU_EDGE. */
12070 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
12071 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
12072 for (unsigned i = 0;
12073 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
12075 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
12076 redirect_edge_succ (e, incr_bb);
12078 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
12079 e->probability = REG_BR_PROB_BASE;
12080 gsi = gsi_last_bb (incr_bb);
12081 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
12082 build_int_cst (unsigned_type_node,
12083 1));
12084 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12086 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12087 struct loop *loop = alloc_loop ();
12088 cfun->has_force_vectorize_loops = true;
12089 loop->safelen = node->simdclone->simdlen;
12090 loop->force_vectorize = true;
12091 loop->header = body_bb;
12093 /* Branch around the body if the mask applies. */
12094 if (node->simdclone->inbranch)
12096 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
12097 tree mask_array
12098 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
12099 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
12100 tree aref = build4 (ARRAY_REF,
12101 TREE_TYPE (TREE_TYPE (mask_array)),
12102 mask_array, iter1,
12103 NULL, NULL);
12104 g = gimple_build_assign (mask, aref);
12105 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12106 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
12107 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
12109 aref = build1 (VIEW_CONVERT_EXPR,
12110 build_nonstandard_integer_type (bitsize, 0), mask);
12111 mask = make_ssa_name (TREE_TYPE (aref), NULL);
12112 g = gimple_build_assign (mask, aref);
12113 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12116 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
12117 NULL, NULL);
12118 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12119 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
12120 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
12123 /* Generate the condition. */
12124 g = gimple_build_cond (LT_EXPR,
12125 iter2,
12126 build_int_cst (unsigned_type_node,
12127 node->simdclone->simdlen),
12128 NULL, NULL);
12129 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12130 e = split_block (incr_bb, gsi_stmt (gsi));
12131 basic_block latch_bb = e->dest;
12132 basic_block new_exit_bb;
12133 new_exit_bb = split_block (latch_bb, NULL)->dest;
12134 loop->latch = latch_bb;
12136 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
12138 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
12139 /* The successor of incr_bb is already pointing to latch_bb; just
12140 change the flags.
12141 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12142 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
12144 gimple phi = create_phi_node (iter1, body_bb);
12145 edge preheader_edge = find_edge (entry_bb, body_bb);
12146 edge latch_edge = single_succ_edge (latch_bb);
12147 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
12148 UNKNOWN_LOCATION);
12149 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12151 /* Generate the new return. */
12152 gsi = gsi_last_bb (new_exit_bb);
12153 if (retval
12154 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
12155 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
12156 retval = TREE_OPERAND (retval, 0);
12157 else if (retval)
12159 retval = build1 (VIEW_CONVERT_EXPR,
12160 TREE_TYPE (TREE_TYPE (node->decl)),
12161 retval);
12162 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
12163 false, GSI_CONTINUE_LINKING);
12165 g = gimple_build_return (retval);
12166 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12168 /* Handle aligned clauses by replacing default defs of the aligned
12169 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12170 lhs. Handle linear by adding PHIs. */
12171 for (unsigned i = 0; i < node->simdclone->nargs; i++)
12172 if (node->simdclone->args[i].alignment
12173 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
12174 && (node->simdclone->args[i].alignment
12175 & (node->simdclone->args[i].alignment - 1)) == 0
12176 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
12177 == POINTER_TYPE)
12179 unsigned int alignment = node->simdclone->args[i].alignment;
12180 tree orig_arg = node->simdclone->args[i].orig_arg;
12181 tree def = ssa_default_def (cfun, orig_arg);
12182 if (def && !has_zero_uses (def))
12184 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
12185 gimple_seq seq = NULL;
12186 bool need_cvt = false;
12187 gimple call
12188 = gimple_build_call (fn, 2, def, size_int (alignment));
12189 g = call;
12190 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
12191 ptr_type_node))
12192 need_cvt = true;
12193 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
12194 gimple_call_set_lhs (g, t);
12195 gimple_seq_add_stmt_without_update (&seq, g);
12196 if (need_cvt)
12198 t = make_ssa_name (orig_arg, NULL);
12199 g = gimple_build_assign_with_ops (NOP_EXPR, t,
12200 gimple_call_lhs (g),
12201 NULL_TREE);
12202 gimple_seq_add_stmt_without_update (&seq, g);
12204 gsi_insert_seq_on_edge_immediate
12205 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
12207 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12208 int freq = compute_call_stmt_bb_frequency (current_function_decl,
12209 entry_bb);
12210 node->create_edge (cgraph_node::get_create (fn),
12211 call, entry_bb->count, freq);
12213 imm_use_iterator iter;
12214 use_operand_p use_p;
12215 gimple use_stmt;
12216 tree repl = gimple_get_lhs (g);
12217 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12218 if (is_gimple_debug (use_stmt) || use_stmt == call)
12219 continue;
12220 else
12221 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12222 SET_USE (use_p, repl);
12225 else if (node->simdclone->args[i].arg_type
12226 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12228 tree orig_arg = node->simdclone->args[i].orig_arg;
12229 tree def = ssa_default_def (cfun, orig_arg);
12230 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12231 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
12232 if (def && !has_zero_uses (def))
12234 iter1 = make_ssa_name (orig_arg, NULL);
12235 iter2 = make_ssa_name (orig_arg, NULL);
12236 phi = create_phi_node (iter1, body_bb);
12237 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
12238 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12239 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12240 ? PLUS_EXPR : POINTER_PLUS_EXPR;
12241 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12242 ? TREE_TYPE (orig_arg) : sizetype;
12243 tree addcst
12244 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
12245 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
12246 gsi = gsi_last_bb (incr_bb);
12247 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12249 imm_use_iterator iter;
12250 use_operand_p use_p;
12251 gimple use_stmt;
12252 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12253 if (use_stmt == phi)
12254 continue;
12255 else
12256 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12257 SET_USE (use_p, iter1);
12261 calculate_dominance_info (CDI_DOMINATORS);
12262 add_loop (loop, loop->header->loop_father);
12263 update_ssa (TODO_update_ssa);
12265 pop_cfun ();
12268 /* If the function in NODE is tagged as an elemental SIMD function,
12269 create the appropriate SIMD clones. */
12271 static void
12272 expand_simd_clones (struct cgraph_node *node)
12274 tree attr = lookup_attribute ("omp declare simd",
12275 DECL_ATTRIBUTES (node->decl));
12276 if (attr == NULL_TREE
12277 || node->global.inlined_to
12278 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
12279 return;
12281 /* Ignore
12282 #pragma omp declare simd
12283 extern int foo ();
12284 in C, there we don't know the argument types at all. */
12285 if (!node->definition
12286 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
12287 return;
12291 /* Start with parsing the "omp declare simd" attribute(s). */
12292 bool inbranch_clause_specified;
12293 struct cgraph_simd_clone *clone_info
12294 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
12295 &inbranch_clause_specified);
12296 if (clone_info == NULL)
12297 continue;
12299 int orig_simdlen = clone_info->simdlen;
12300 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
12301 /* The target can return 0 (no simd clones should be created),
12302 1 (just one ISA of simd clones should be created) or higher
12303 count of ISA variants. In that case, clone_info is initialized
12304 for the first ISA variant. */
12305 int count
12306 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
12307 base_type, 0);
12308 if (count == 0)
12309 continue;
12311 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12312 also create one inbranch and one !inbranch clone of it. */
12313 for (int i = 0; i < count * 2; i++)
12315 struct cgraph_simd_clone *clone = clone_info;
12316 if (inbranch_clause_specified && (i & 1) != 0)
12317 continue;
12319 if (i != 0)
12321 clone = simd_clone_struct_alloc (clone_info->nargs
12322 + ((i & 1) != 0));
12323 simd_clone_struct_copy (clone, clone_info);
12324 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12325 and simd_clone_adjust_argument_types did to the first
12326 clone's info. */
12327 clone->nargs -= clone_info->inbranch;
12328 clone->simdlen = orig_simdlen;
12329 /* And call the target hook again to get the right ISA. */
12330 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
12331 base_type,
12332 i / 2);
12333 if ((i & 1) != 0)
12334 clone->inbranch = 1;
12337 /* simd_clone_mangle might fail if such a clone has been created
12338 already. */
12339 tree id = simd_clone_mangle (node, clone);
12340 if (id == NULL_TREE)
12341 continue;
12343 /* Only when we are sure we want to create the clone actually
12344 clone the function (or definitions) or create another
12345 extern FUNCTION_DECL (for prototypes without definitions). */
12346 struct cgraph_node *n = simd_clone_create (node);
12347 if (n == NULL)
12348 continue;
12350 n->simdclone = clone;
12351 clone->origin = node;
12352 clone->next_clone = NULL;
12353 if (node->simd_clones == NULL)
12355 clone->prev_clone = n;
12356 node->simd_clones = n;
12358 else
12360 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
12361 clone->prev_clone->simdclone->next_clone = n;
12362 node->simd_clones->simdclone->prev_clone = n;
12364 symtab->change_decl_assembler_name (n->decl, id);
12365 /* And finally adjust the return type, parameters and for
12366 definitions also function body. */
12367 if (node->definition)
12368 simd_clone_adjust (n);
12369 else
12371 simd_clone_adjust_return_type (n);
12372 simd_clone_adjust_argument_types (n);
12376 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
12379 /* Entry point for IPA simd clone creation pass. */
12381 static unsigned int
12382 ipa_omp_simd_clone (void)
12384 struct cgraph_node *node;
12385 FOR_EACH_FUNCTION (node)
12386 expand_simd_clones (node);
12387 return 0;
12390 namespace {
12392 const pass_data pass_data_omp_simd_clone =
12394 SIMPLE_IPA_PASS, /* type */
12395 "simdclone", /* name */
12396 OPTGROUP_NONE, /* optinfo_flags */
12397 TV_NONE, /* tv_id */
12398 ( PROP_ssa | PROP_cfg ), /* properties_required */
12399 0, /* properties_provided */
12400 0, /* properties_destroyed */
12401 0, /* todo_flags_start */
12402 0, /* todo_flags_finish */
12405 class pass_omp_simd_clone : public simple_ipa_opt_pass
12407 public:
12408 pass_omp_simd_clone(gcc::context *ctxt)
12409 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
12412 /* opt_pass methods: */
12413 virtual bool gate (function *);
12414 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
12417 bool
12418 pass_omp_simd_clone::gate (function *)
12420 return ((flag_openmp || flag_openmp_simd
12421 || flag_cilkplus
12422 || (in_lto_p && !flag_wpa))
12423 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
12426 } // anon namespace
12428 simple_ipa_opt_pass *
12429 make_pass_omp_simd_clone (gcc::context *ctxt)
12431 return new pass_omp_simd_clone (ctxt);
12434 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
12435 adds their addresses and sizes to constructor-vector V_CTOR. */
12436 static void
12437 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
12438 vec<constructor_elt, va_gc> *v_ctor)
12440 unsigned len = vec_safe_length (v_decls);
12441 for (unsigned i = 0; i < len; i++)
12443 tree it = (*v_decls)[i];
12444 bool is_function = TREE_CODE (it) != VAR_DECL;
12446 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
12447 if (!is_function)
12448 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
12449 fold_convert (const_ptr_type_node,
12450 DECL_SIZE_UNIT (it)));
12454 /* Create new symbols containing (address, size) pairs for global variables,
12455 marked with "omp declare target" attribute, as well as addresses for the
12456 functions, which are outlined target regions. */
12457 void
12458 omp_finish_file (void)
12460 unsigned num_funcs = vec_safe_length (offload_funcs);
12461 unsigned num_vars = vec_safe_length (offload_vars);
12463 if (num_funcs == 0 && num_vars == 0)
12464 return;
12466 if (targetm_common.have_named_sections)
12468 vec<constructor_elt, va_gc> *v_f, *v_v;
12469 vec_alloc (v_f, num_funcs);
12470 vec_alloc (v_v, num_vars * 2);
12472 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
12473 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
12475 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
12476 num_vars * 2);
12477 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
12478 num_funcs);
12479 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
12480 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
12481 tree ctor_v = build_constructor (vars_decl_type, v_v);
12482 tree ctor_f = build_constructor (funcs_decl_type, v_f);
12483 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
12484 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
12485 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
12486 get_identifier (".offload_func_table"),
12487 funcs_decl_type);
12488 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
12489 get_identifier (".offload_var_table"),
12490 vars_decl_type);
12491 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
12492 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
12493 otherwise a joint table in a binary will contain padding between
12494 tables from multiple object files. */
12495 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
12496 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
12497 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
12498 DECL_INITIAL (funcs_decl) = ctor_f;
12499 DECL_INITIAL (vars_decl) = ctor_v;
12500 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
12501 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
12503 varpool_node::finalize_decl (vars_decl);
12504 varpool_node::finalize_decl (funcs_decl);
12506 else
12508 for (unsigned i = 0; i < num_funcs; i++)
12510 tree it = (*offload_funcs)[i];
12511 targetm.record_offload_symbol (it);
12513 for (unsigned i = 0; i < num_vars; i++)
12515 tree it = (*offload_vars)[i];
12516 targetm.record_offload_symbol (it);
12521 #include "gt-omp-low.h"