* combine.c (try_combine): Prefer to delete dead SETs inside
[official-gcc.git] / gcc / omp-low.c
blob15aa140770cf02da74551d95a105029439a5aa8f
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 gomp_for *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 (gomp_for *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 (as_a <gomp_for *> (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 (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
707 struct omp_for_data fd;
708 tree n1, n2;
710 extract_omp_for_data (for_stmt, &fd, NULL);
711 n1 = fd.loop.n1;
712 n2 = fd.loop.n2;
714 if (gimple_omp_for_combined_into_p (for_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 (gomp_task *task_stmt)
1408 struct function *child_cfun;
1409 tree child_fn;
1410 gimple_seq seq = NULL, new_seq;
1411 gbind *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 (as_a <gomp_task *> (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)
1521 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1524 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1525 specified by CLAUSES. */
1527 static void
1528 scan_sharing_clauses (tree clauses, omp_context *ctx)
1530 tree c, decl;
1531 bool scan_array_reductions = false;
1533 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1535 bool by_ref;
1537 switch (OMP_CLAUSE_CODE (c))
1539 case OMP_CLAUSE_PRIVATE:
1540 decl = OMP_CLAUSE_DECL (c);
1541 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1542 goto do_private;
1543 else if (!is_variable_sized (decl))
1544 install_var_local (decl, ctx);
1545 break;
1547 case OMP_CLAUSE_SHARED:
1548 decl = OMP_CLAUSE_DECL (c);
1549 /* Ignore shared directives in teams construct. */
1550 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1552 /* Global variables don't need to be copied,
1553 the receiver side will use them directly. */
1554 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1555 if (is_global_var (odecl))
1556 break;
1557 insert_decl_map (&ctx->cb, decl, odecl);
1558 break;
1560 gcc_assert (is_taskreg_ctx (ctx));
1561 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1562 || !is_variable_sized (decl));
1563 /* Global variables don't need to be copied,
1564 the receiver side will use them directly. */
1565 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1566 break;
1567 by_ref = use_pointer_for_field (decl, ctx);
1568 if (! TREE_READONLY (decl)
1569 || TREE_ADDRESSABLE (decl)
1570 || by_ref
1571 || is_reference (decl))
1573 install_var_field (decl, by_ref, 3, ctx);
1574 install_var_local (decl, ctx);
1575 break;
1577 /* We don't need to copy const scalar vars back. */
1578 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1579 goto do_private;
1581 case OMP_CLAUSE_LASTPRIVATE:
1582 /* Let the corresponding firstprivate clause create
1583 the variable. */
1584 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1585 break;
1586 /* FALLTHRU */
1588 case OMP_CLAUSE_FIRSTPRIVATE:
1589 case OMP_CLAUSE_REDUCTION:
1590 case OMP_CLAUSE_LINEAR:
1591 decl = OMP_CLAUSE_DECL (c);
1592 do_private:
1593 if (is_variable_sized (decl))
1595 if (is_task_ctx (ctx))
1596 install_var_field (decl, false, 1, ctx);
1597 break;
1599 else if (is_taskreg_ctx (ctx))
1601 bool global
1602 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1603 by_ref = use_pointer_for_field (decl, NULL);
1605 if (is_task_ctx (ctx)
1606 && (global || by_ref || is_reference (decl)))
1608 install_var_field (decl, false, 1, ctx);
1609 if (!global)
1610 install_var_field (decl, by_ref, 2, ctx);
1612 else if (!global)
1613 install_var_field (decl, by_ref, 3, ctx);
1615 install_var_local (decl, ctx);
1616 break;
1618 case OMP_CLAUSE__LOOPTEMP_:
1619 gcc_assert (is_parallel_ctx (ctx));
1620 decl = OMP_CLAUSE_DECL (c);
1621 install_var_field (decl, false, 3, ctx);
1622 install_var_local (decl, ctx);
1623 break;
1625 case OMP_CLAUSE_COPYPRIVATE:
1626 case OMP_CLAUSE_COPYIN:
1627 decl = OMP_CLAUSE_DECL (c);
1628 by_ref = use_pointer_for_field (decl, NULL);
1629 install_var_field (decl, by_ref, 3, ctx);
1630 break;
1632 case OMP_CLAUSE_DEFAULT:
1633 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1634 break;
1636 case OMP_CLAUSE_FINAL:
1637 case OMP_CLAUSE_IF:
1638 case OMP_CLAUSE_NUM_THREADS:
1639 case OMP_CLAUSE_NUM_TEAMS:
1640 case OMP_CLAUSE_THREAD_LIMIT:
1641 case OMP_CLAUSE_DEVICE:
1642 case OMP_CLAUSE_SCHEDULE:
1643 case OMP_CLAUSE_DIST_SCHEDULE:
1644 case OMP_CLAUSE_DEPEND:
1645 case OMP_CLAUSE__CILK_FOR_COUNT_:
1646 if (ctx->outer)
1647 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1648 break;
1650 case OMP_CLAUSE_TO:
1651 case OMP_CLAUSE_FROM:
1652 case OMP_CLAUSE_MAP:
1653 if (ctx->outer)
1654 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1655 decl = OMP_CLAUSE_DECL (c);
1656 /* Global variables with "omp declare target" attribute
1657 don't need to be copied, the receiver side will use them
1658 directly. */
1659 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1660 && DECL_P (decl)
1661 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1662 && varpool_node::get_create (decl)->offloadable)
1663 break;
1664 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1665 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1667 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1668 #pragma omp target data, there is nothing to map for
1669 those. */
1670 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1671 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1672 break;
1674 if (DECL_P (decl))
1676 if (DECL_SIZE (decl)
1677 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1679 tree decl2 = DECL_VALUE_EXPR (decl);
1680 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1681 decl2 = TREE_OPERAND (decl2, 0);
1682 gcc_assert (DECL_P (decl2));
1683 install_var_field (decl2, true, 3, ctx);
1684 install_var_local (decl2, ctx);
1685 install_var_local (decl, ctx);
1687 else
1689 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1690 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1691 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1692 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1693 install_var_field (decl, true, 7, ctx);
1694 else
1695 install_var_field (decl, true, 3, ctx);
1696 if (gimple_omp_target_kind (ctx->stmt)
1697 == GF_OMP_TARGET_KIND_REGION)
1698 install_var_local (decl, ctx);
1701 else
1703 tree base = get_base_address (decl);
1704 tree nc = OMP_CLAUSE_CHAIN (c);
1705 if (DECL_P (base)
1706 && nc != NULL_TREE
1707 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1708 && OMP_CLAUSE_DECL (nc) == base
1709 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1710 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1712 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1713 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1715 else
1717 if (ctx->outer)
1719 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1720 decl = OMP_CLAUSE_DECL (c);
1722 gcc_assert (!splay_tree_lookup (ctx->field_map,
1723 (splay_tree_key) decl));
1724 tree field
1725 = build_decl (OMP_CLAUSE_LOCATION (c),
1726 FIELD_DECL, NULL_TREE, ptr_type_node);
1727 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1728 insert_field_into_struct (ctx->record_type, field);
1729 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1730 (splay_tree_value) field);
1733 break;
1735 case OMP_CLAUSE_NOWAIT:
1736 case OMP_CLAUSE_ORDERED:
1737 case OMP_CLAUSE_COLLAPSE:
1738 case OMP_CLAUSE_UNTIED:
1739 case OMP_CLAUSE_MERGEABLE:
1740 case OMP_CLAUSE_PROC_BIND:
1741 case OMP_CLAUSE_SAFELEN:
1742 break;
1744 case OMP_CLAUSE_ALIGNED:
1745 decl = OMP_CLAUSE_DECL (c);
1746 if (is_global_var (decl)
1747 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1748 install_var_local (decl, ctx);
1749 break;
1751 default:
1752 gcc_unreachable ();
1756 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1758 switch (OMP_CLAUSE_CODE (c))
1760 case OMP_CLAUSE_LASTPRIVATE:
1761 /* Let the corresponding firstprivate clause create
1762 the variable. */
1763 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1764 scan_array_reductions = true;
1765 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1766 break;
1767 /* FALLTHRU */
1769 case OMP_CLAUSE_PRIVATE:
1770 case OMP_CLAUSE_FIRSTPRIVATE:
1771 case OMP_CLAUSE_REDUCTION:
1772 case OMP_CLAUSE_LINEAR:
1773 decl = OMP_CLAUSE_DECL (c);
1774 if (is_variable_sized (decl))
1775 install_var_local (decl, ctx);
1776 fixup_remapped_decl (decl, ctx,
1777 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1778 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1779 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1780 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1781 scan_array_reductions = true;
1782 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1783 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1784 scan_array_reductions = true;
1785 break;
1787 case OMP_CLAUSE_SHARED:
1788 /* Ignore shared directives in teams construct. */
1789 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1790 break;
1791 decl = OMP_CLAUSE_DECL (c);
1792 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1793 fixup_remapped_decl (decl, ctx, false);
1794 break;
1796 case OMP_CLAUSE_MAP:
1797 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1798 break;
1799 decl = OMP_CLAUSE_DECL (c);
1800 if (DECL_P (decl)
1801 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1802 && varpool_node::get_create (decl)->offloadable)
1803 break;
1804 if (DECL_P (decl))
1806 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1807 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1808 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1810 tree new_decl = lookup_decl (decl, ctx);
1811 TREE_TYPE (new_decl)
1812 = remap_type (TREE_TYPE (decl), &ctx->cb);
1814 else if (DECL_SIZE (decl)
1815 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1817 tree decl2 = DECL_VALUE_EXPR (decl);
1818 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1819 decl2 = TREE_OPERAND (decl2, 0);
1820 gcc_assert (DECL_P (decl2));
1821 fixup_remapped_decl (decl2, ctx, false);
1822 fixup_remapped_decl (decl, ctx, true);
1824 else
1825 fixup_remapped_decl (decl, ctx, false);
1827 break;
1829 case OMP_CLAUSE_COPYPRIVATE:
1830 case OMP_CLAUSE_COPYIN:
1831 case OMP_CLAUSE_DEFAULT:
1832 case OMP_CLAUSE_IF:
1833 case OMP_CLAUSE_NUM_THREADS:
1834 case OMP_CLAUSE_NUM_TEAMS:
1835 case OMP_CLAUSE_THREAD_LIMIT:
1836 case OMP_CLAUSE_DEVICE:
1837 case OMP_CLAUSE_SCHEDULE:
1838 case OMP_CLAUSE_DIST_SCHEDULE:
1839 case OMP_CLAUSE_NOWAIT:
1840 case OMP_CLAUSE_ORDERED:
1841 case OMP_CLAUSE_COLLAPSE:
1842 case OMP_CLAUSE_UNTIED:
1843 case OMP_CLAUSE_FINAL:
1844 case OMP_CLAUSE_MERGEABLE:
1845 case OMP_CLAUSE_PROC_BIND:
1846 case OMP_CLAUSE_SAFELEN:
1847 case OMP_CLAUSE_ALIGNED:
1848 case OMP_CLAUSE_DEPEND:
1849 case OMP_CLAUSE__LOOPTEMP_:
1850 case OMP_CLAUSE_TO:
1851 case OMP_CLAUSE_FROM:
1852 case OMP_CLAUSE__CILK_FOR_COUNT_:
1853 break;
1855 default:
1856 gcc_unreachable ();
1860 if (scan_array_reductions)
1861 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1862 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1863 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1865 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1866 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1868 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1869 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1870 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1871 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1872 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1873 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1876 /* Create a new name for omp child function. Returns an identifier. If
1877 IS_CILK_FOR is true then the suffix for the child function is
1878 "_cilk_for_fn." */
1880 static tree
1881 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1883 if (is_cilk_for)
1884 return clone_function_name (current_function_decl, "_cilk_for_fn");
1885 return clone_function_name (current_function_decl,
1886 task_copy ? "_omp_cpyfn" : "_omp_fn");
1889 /* Returns the type of the induction variable for the child function for
1890 _Cilk_for and the types for _high and _low variables based on TYPE. */
1892 static tree
1893 cilk_for_check_loop_diff_type (tree type)
1895 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
1897 if (TYPE_UNSIGNED (type))
1898 return uint32_type_node;
1899 else
1900 return integer_type_node;
1902 else
1904 if (TYPE_UNSIGNED (type))
1905 return uint64_type_node;
1906 else
1907 return long_long_integer_type_node;
1911 /* Build a decl for the omp child function. It'll not contain a body
1912 yet, just the bare decl. */
1914 static void
1915 create_omp_child_function (omp_context *ctx, bool task_copy)
1917 tree decl, type, name, t;
1919 tree cilk_for_count
1920 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
1921 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1922 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
1923 tree cilk_var_type = NULL_TREE;
1925 name = create_omp_child_function_name (task_copy,
1926 cilk_for_count != NULL_TREE);
1927 if (task_copy)
1928 type = build_function_type_list (void_type_node, ptr_type_node,
1929 ptr_type_node, NULL_TREE);
1930 else if (cilk_for_count)
1932 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
1933 cilk_var_type = cilk_for_check_loop_diff_type (type);
1934 type = build_function_type_list (void_type_node, ptr_type_node,
1935 cilk_var_type, cilk_var_type, NULL_TREE);
1937 else
1938 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1940 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1942 if (!task_copy)
1943 ctx->cb.dst_fn = decl;
1944 else
1945 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1947 TREE_STATIC (decl) = 1;
1948 TREE_USED (decl) = 1;
1949 DECL_ARTIFICIAL (decl) = 1;
1950 DECL_IGNORED_P (decl) = 0;
1951 TREE_PUBLIC (decl) = 0;
1952 DECL_UNINLINABLE (decl) = 1;
1953 DECL_EXTERNAL (decl) = 0;
1954 DECL_CONTEXT (decl) = NULL_TREE;
1955 DECL_INITIAL (decl) = make_node (BLOCK);
1956 if (cgraph_node::get (current_function_decl)->offloadable)
1957 cgraph_node::get_create (decl)->offloadable = 1;
1958 else
1960 omp_context *octx;
1961 for (octx = ctx; octx; octx = octx->outer)
1962 if (is_targetreg_ctx (octx))
1964 cgraph_node::get_create (decl)->offloadable = 1;
1965 #ifdef ENABLE_OFFLOADING
1966 g->have_offload = true;
1967 #endif
1968 break;
1972 t = build_decl (DECL_SOURCE_LOCATION (decl),
1973 RESULT_DECL, NULL_TREE, void_type_node);
1974 DECL_ARTIFICIAL (t) = 1;
1975 DECL_IGNORED_P (t) = 1;
1976 DECL_CONTEXT (t) = decl;
1977 DECL_RESULT (decl) = t;
1979 /* _Cilk_for's child function requires two extra parameters called
1980 __low and __high that are set the by Cilk runtime when it calls this
1981 function. */
1982 if (cilk_for_count)
1984 t = build_decl (DECL_SOURCE_LOCATION (decl),
1985 PARM_DECL, get_identifier ("__high"), cilk_var_type);
1986 DECL_ARTIFICIAL (t) = 1;
1987 DECL_NAMELESS (t) = 1;
1988 DECL_ARG_TYPE (t) = ptr_type_node;
1989 DECL_CONTEXT (t) = current_function_decl;
1990 TREE_USED (t) = 1;
1991 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1992 DECL_ARGUMENTS (decl) = t;
1994 t = build_decl (DECL_SOURCE_LOCATION (decl),
1995 PARM_DECL, get_identifier ("__low"), cilk_var_type);
1996 DECL_ARTIFICIAL (t) = 1;
1997 DECL_NAMELESS (t) = 1;
1998 DECL_ARG_TYPE (t) = ptr_type_node;
1999 DECL_CONTEXT (t) = current_function_decl;
2000 TREE_USED (t) = 1;
2001 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2002 DECL_ARGUMENTS (decl) = t;
2005 tree data_name = get_identifier (".omp_data_i");
2006 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2007 ptr_type_node);
2008 DECL_ARTIFICIAL (t) = 1;
2009 DECL_NAMELESS (t) = 1;
2010 DECL_ARG_TYPE (t) = ptr_type_node;
2011 DECL_CONTEXT (t) = current_function_decl;
2012 TREE_USED (t) = 1;
2013 if (cilk_for_count)
2014 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2015 DECL_ARGUMENTS (decl) = t;
2016 if (!task_copy)
2017 ctx->receiver_decl = t;
2018 else
2020 t = build_decl (DECL_SOURCE_LOCATION (decl),
2021 PARM_DECL, get_identifier (".omp_data_o"),
2022 ptr_type_node);
2023 DECL_ARTIFICIAL (t) = 1;
2024 DECL_NAMELESS (t) = 1;
2025 DECL_ARG_TYPE (t) = ptr_type_node;
2026 DECL_CONTEXT (t) = current_function_decl;
2027 TREE_USED (t) = 1;
2028 TREE_ADDRESSABLE (t) = 1;
2029 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2030 DECL_ARGUMENTS (decl) = t;
2033 /* Allocate memory for the function structure. The call to
2034 allocate_struct_function clobbers CFUN, so we need to restore
2035 it afterward. */
2036 push_struct_function (decl);
2037 cfun->function_end_locus = gimple_location (ctx->stmt);
2038 pop_cfun ();
2041 /* Callback for walk_gimple_seq. Check if combined parallel
2042 contains gimple_omp_for_combined_into_p OMP_FOR. */
2044 static tree
2045 find_combined_for (gimple_stmt_iterator *gsi_p,
2046 bool *handled_ops_p,
2047 struct walk_stmt_info *wi)
2049 gimple stmt = gsi_stmt (*gsi_p);
2051 *handled_ops_p = true;
2052 switch (gimple_code (stmt))
2054 WALK_SUBSTMTS;
2056 case GIMPLE_OMP_FOR:
2057 if (gimple_omp_for_combined_into_p (stmt)
2058 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2060 wi->info = stmt;
2061 return integer_zero_node;
2063 break;
2064 default:
2065 break;
2067 return NULL;
2070 /* Scan an OpenMP parallel directive. */
2072 static void
2073 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2075 omp_context *ctx;
2076 tree name;
2077 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2079 /* Ignore parallel directives with empty bodies, unless there
2080 are copyin clauses. */
2081 if (optimize > 0
2082 && empty_body_p (gimple_omp_body (stmt))
2083 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2084 OMP_CLAUSE_COPYIN) == NULL)
2086 gsi_replace (gsi, gimple_build_nop (), false);
2087 return;
2090 if (gimple_omp_parallel_combined_p (stmt))
2092 struct walk_stmt_info wi;
2094 memset (&wi, 0, sizeof (wi));
2095 wi.val_only = true;
2096 walk_gimple_seq (gimple_omp_body (stmt),
2097 find_combined_for, NULL, &wi);
2098 if (wi.info)
2100 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2101 struct omp_for_data fd;
2102 extract_omp_for_data (for_stmt, &fd, NULL);
2103 /* We need two temporaries with fd.loop.v type (istart/iend)
2104 and then (fd.collapse - 1) temporaries with the same
2105 type for count2 ... countN-1 vars if not constant. */
2106 size_t count = 2, i;
2107 tree type = fd.iter_type;
2108 if (fd.collapse > 1
2109 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2110 count += fd.collapse - 1;
2111 for (i = 0; i < count; i++)
2113 tree temp = create_tmp_var (type, NULL);
2114 tree c = build_omp_clause (UNKNOWN_LOCATION,
2115 OMP_CLAUSE__LOOPTEMP_);
2116 insert_decl_map (&outer_ctx->cb, temp, temp);
2117 OMP_CLAUSE_DECL (c) = temp;
2118 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2119 gimple_omp_parallel_set_clauses (stmt, c);
2124 ctx = new_omp_context (stmt, outer_ctx);
2125 taskreg_contexts.safe_push (ctx);
2126 if (taskreg_nesting_level > 1)
2127 ctx->is_nested = true;
2128 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2129 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2130 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2131 name = create_tmp_var_name (".omp_data_s");
2132 name = build_decl (gimple_location (stmt),
2133 TYPE_DECL, name, ctx->record_type);
2134 DECL_ARTIFICIAL (name) = 1;
2135 DECL_NAMELESS (name) = 1;
2136 TYPE_NAME (ctx->record_type) = name;
2137 create_omp_child_function (ctx, false);
2138 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2140 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2141 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2143 if (TYPE_FIELDS (ctx->record_type) == NULL)
2144 ctx->record_type = ctx->receiver_decl = NULL;
2147 /* Scan an OpenMP task directive. */
2149 static void
2150 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2152 omp_context *ctx;
2153 tree name, t;
2154 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2156 /* Ignore task directives with empty bodies. */
2157 if (optimize > 0
2158 && empty_body_p (gimple_omp_body (stmt)))
2160 gsi_replace (gsi, gimple_build_nop (), false);
2161 return;
2164 ctx = new_omp_context (stmt, outer_ctx);
2165 taskreg_contexts.safe_push (ctx);
2166 if (taskreg_nesting_level > 1)
2167 ctx->is_nested = true;
2168 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2169 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2170 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2171 name = create_tmp_var_name (".omp_data_s");
2172 name = build_decl (gimple_location (stmt),
2173 TYPE_DECL, name, ctx->record_type);
2174 DECL_ARTIFICIAL (name) = 1;
2175 DECL_NAMELESS (name) = 1;
2176 TYPE_NAME (ctx->record_type) = name;
2177 create_omp_child_function (ctx, false);
2178 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2180 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2182 if (ctx->srecord_type)
2184 name = create_tmp_var_name (".omp_data_a");
2185 name = build_decl (gimple_location (stmt),
2186 TYPE_DECL, name, ctx->srecord_type);
2187 DECL_ARTIFICIAL (name) = 1;
2188 DECL_NAMELESS (name) = 1;
2189 TYPE_NAME (ctx->srecord_type) = name;
2190 create_omp_child_function (ctx, true);
2193 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2195 if (TYPE_FIELDS (ctx->record_type) == NULL)
2197 ctx->record_type = ctx->receiver_decl = NULL;
2198 t = build_int_cst (long_integer_type_node, 0);
2199 gimple_omp_task_set_arg_size (stmt, t);
2200 t = build_int_cst (long_integer_type_node, 1);
2201 gimple_omp_task_set_arg_align (stmt, t);
2206 /* If any decls have been made addressable during scan_omp,
2207 adjust their fields if needed, and layout record types
2208 of parallel/task constructs. */
2210 static void
2211 finish_taskreg_scan (omp_context *ctx)
2213 if (ctx->record_type == NULL_TREE)
2214 return;
2216 /* If any task_shared_vars were needed, verify all
2217 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2218 statements if use_pointer_for_field hasn't changed
2219 because of that. If it did, update field types now. */
2220 if (task_shared_vars)
2222 tree c;
2224 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2225 c; c = OMP_CLAUSE_CHAIN (c))
2226 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2228 tree decl = OMP_CLAUSE_DECL (c);
2230 /* Global variables don't need to be copied,
2231 the receiver side will use them directly. */
2232 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2233 continue;
2234 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2235 || !use_pointer_for_field (decl, ctx))
2236 continue;
2237 tree field = lookup_field (decl, ctx);
2238 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2239 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2240 continue;
2241 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2242 TREE_THIS_VOLATILE (field) = 0;
2243 DECL_USER_ALIGN (field) = 0;
2244 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2245 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2246 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2247 if (ctx->srecord_type)
2249 tree sfield = lookup_sfield (decl, ctx);
2250 TREE_TYPE (sfield) = TREE_TYPE (field);
2251 TREE_THIS_VOLATILE (sfield) = 0;
2252 DECL_USER_ALIGN (sfield) = 0;
2253 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2254 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2255 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2260 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2262 layout_type (ctx->record_type);
2263 fixup_child_record_type (ctx);
2265 else
2267 location_t loc = gimple_location (ctx->stmt);
2268 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2269 /* Move VLA fields to the end. */
2270 p = &TYPE_FIELDS (ctx->record_type);
2271 while (*p)
2272 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2273 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2275 *q = *p;
2276 *p = TREE_CHAIN (*p);
2277 TREE_CHAIN (*q) = NULL_TREE;
2278 q = &TREE_CHAIN (*q);
2280 else
2281 p = &DECL_CHAIN (*p);
2282 *p = vla_fields;
2283 layout_type (ctx->record_type);
2284 fixup_child_record_type (ctx);
2285 if (ctx->srecord_type)
2286 layout_type (ctx->srecord_type);
2287 tree t = fold_convert_loc (loc, long_integer_type_node,
2288 TYPE_SIZE_UNIT (ctx->record_type));
2289 gimple_omp_task_set_arg_size (ctx->stmt, t);
2290 t = build_int_cst (long_integer_type_node,
2291 TYPE_ALIGN_UNIT (ctx->record_type));
2292 gimple_omp_task_set_arg_align (ctx->stmt, t);
2297 /* Scan an OpenMP loop directive. */
2299 static void
2300 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2302 omp_context *ctx;
2303 size_t i;
2305 ctx = new_omp_context (stmt, outer_ctx);
2307 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2309 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2310 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2312 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2313 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2314 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2315 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2317 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2320 /* Scan an OpenMP sections directive. */
2322 static void
2323 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2325 omp_context *ctx;
2327 ctx = new_omp_context (stmt, outer_ctx);
2328 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2329 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2332 /* Scan an OpenMP single directive. */
2334 static void
2335 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2337 omp_context *ctx;
2338 tree name;
2340 ctx = new_omp_context (stmt, outer_ctx);
2341 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2342 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2343 name = create_tmp_var_name (".omp_copy_s");
2344 name = build_decl (gimple_location (stmt),
2345 TYPE_DECL, name, ctx->record_type);
2346 TYPE_NAME (ctx->record_type) = name;
2348 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2349 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2351 if (TYPE_FIELDS (ctx->record_type) == NULL)
2352 ctx->record_type = NULL;
2353 else
2354 layout_type (ctx->record_type);
2357 /* Scan an OpenMP target{, data, update} directive. */
2359 static void
2360 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2362 omp_context *ctx;
2363 tree name;
2364 int kind = gimple_omp_target_kind (stmt);
2366 ctx = new_omp_context (stmt, outer_ctx);
2367 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2368 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2369 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2370 name = create_tmp_var_name (".omp_data_t");
2371 name = build_decl (gimple_location (stmt),
2372 TYPE_DECL, name, ctx->record_type);
2373 DECL_ARTIFICIAL (name) = 1;
2374 DECL_NAMELESS (name) = 1;
2375 TYPE_NAME (ctx->record_type) = name;
2376 if (kind == GF_OMP_TARGET_KIND_REGION)
2378 create_omp_child_function (ctx, false);
2379 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2382 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2383 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2385 if (TYPE_FIELDS (ctx->record_type) == NULL)
2386 ctx->record_type = ctx->receiver_decl = NULL;
2387 else
2389 TYPE_FIELDS (ctx->record_type)
2390 = nreverse (TYPE_FIELDS (ctx->record_type));
2391 #ifdef ENABLE_CHECKING
2392 tree field;
2393 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2394 for (field = TYPE_FIELDS (ctx->record_type);
2395 field;
2396 field = DECL_CHAIN (field))
2397 gcc_assert (DECL_ALIGN (field) == align);
2398 #endif
2399 layout_type (ctx->record_type);
2400 if (kind == GF_OMP_TARGET_KIND_REGION)
2401 fixup_child_record_type (ctx);
2405 /* Scan an OpenMP teams directive. */
2407 static void
2408 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2410 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2411 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2412 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2415 /* Check OpenMP nesting restrictions. */
2416 static bool
2417 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2419 if (ctx != NULL)
2421 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2422 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2424 error_at (gimple_location (stmt),
2425 "OpenMP constructs may not be nested inside simd region");
2426 return false;
2428 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2430 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2431 || (gimple_omp_for_kind (stmt)
2432 != GF_OMP_FOR_KIND_DISTRIBUTE))
2433 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2435 error_at (gimple_location (stmt),
2436 "only distribute or parallel constructs are allowed to "
2437 "be closely nested inside teams construct");
2438 return false;
2442 switch (gimple_code (stmt))
2444 case GIMPLE_OMP_FOR:
2445 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2446 return true;
2447 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2449 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2451 error_at (gimple_location (stmt),
2452 "distribute construct must be closely nested inside "
2453 "teams construct");
2454 return false;
2456 return true;
2458 /* FALLTHRU */
2459 case GIMPLE_CALL:
2460 if (is_gimple_call (stmt)
2461 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2462 == BUILT_IN_GOMP_CANCEL
2463 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2464 == BUILT_IN_GOMP_CANCELLATION_POINT))
2466 const char *bad = NULL;
2467 const char *kind = NULL;
2468 if (ctx == NULL)
2470 error_at (gimple_location (stmt), "orphaned %qs construct",
2471 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2472 == BUILT_IN_GOMP_CANCEL
2473 ? "#pragma omp cancel"
2474 : "#pragma omp cancellation point");
2475 return false;
2477 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2478 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2479 : 0)
2481 case 1:
2482 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2483 bad = "#pragma omp parallel";
2484 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2485 == BUILT_IN_GOMP_CANCEL
2486 && !integer_zerop (gimple_call_arg (stmt, 1)))
2487 ctx->cancellable = true;
2488 kind = "parallel";
2489 break;
2490 case 2:
2491 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2492 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2493 bad = "#pragma omp for";
2494 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2495 == BUILT_IN_GOMP_CANCEL
2496 && !integer_zerop (gimple_call_arg (stmt, 1)))
2498 ctx->cancellable = true;
2499 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2500 OMP_CLAUSE_NOWAIT))
2501 warning_at (gimple_location (stmt), 0,
2502 "%<#pragma omp cancel for%> inside "
2503 "%<nowait%> for construct");
2504 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2505 OMP_CLAUSE_ORDERED))
2506 warning_at (gimple_location (stmt), 0,
2507 "%<#pragma omp cancel for%> inside "
2508 "%<ordered%> for construct");
2510 kind = "for";
2511 break;
2512 case 4:
2513 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2514 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2515 bad = "#pragma omp sections";
2516 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2517 == BUILT_IN_GOMP_CANCEL
2518 && !integer_zerop (gimple_call_arg (stmt, 1)))
2520 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2522 ctx->cancellable = true;
2523 if (find_omp_clause (gimple_omp_sections_clauses
2524 (ctx->stmt),
2525 OMP_CLAUSE_NOWAIT))
2526 warning_at (gimple_location (stmt), 0,
2527 "%<#pragma omp cancel sections%> inside "
2528 "%<nowait%> sections construct");
2530 else
2532 gcc_assert (ctx->outer
2533 && gimple_code (ctx->outer->stmt)
2534 == GIMPLE_OMP_SECTIONS);
2535 ctx->outer->cancellable = true;
2536 if (find_omp_clause (gimple_omp_sections_clauses
2537 (ctx->outer->stmt),
2538 OMP_CLAUSE_NOWAIT))
2539 warning_at (gimple_location (stmt), 0,
2540 "%<#pragma omp cancel sections%> inside "
2541 "%<nowait%> sections construct");
2544 kind = "sections";
2545 break;
2546 case 8:
2547 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2548 bad = "#pragma omp task";
2549 else
2550 ctx->cancellable = true;
2551 kind = "taskgroup";
2552 break;
2553 default:
2554 error_at (gimple_location (stmt), "invalid arguments");
2555 return false;
2557 if (bad)
2559 error_at (gimple_location (stmt),
2560 "%<%s %s%> construct not closely nested inside of %qs",
2561 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2562 == BUILT_IN_GOMP_CANCEL
2563 ? "#pragma omp cancel"
2564 : "#pragma omp cancellation point", kind, bad);
2565 return false;
2568 /* FALLTHRU */
2569 case GIMPLE_OMP_SECTIONS:
2570 case GIMPLE_OMP_SINGLE:
2571 for (; ctx != NULL; ctx = ctx->outer)
2572 switch (gimple_code (ctx->stmt))
2574 case GIMPLE_OMP_FOR:
2575 case GIMPLE_OMP_SECTIONS:
2576 case GIMPLE_OMP_SINGLE:
2577 case GIMPLE_OMP_ORDERED:
2578 case GIMPLE_OMP_MASTER:
2579 case GIMPLE_OMP_TASK:
2580 case GIMPLE_OMP_CRITICAL:
2581 if (is_gimple_call (stmt))
2583 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2584 != BUILT_IN_GOMP_BARRIER)
2585 return true;
2586 error_at (gimple_location (stmt),
2587 "barrier region may not be closely nested inside "
2588 "of work-sharing, critical, ordered, master or "
2589 "explicit task region");
2590 return false;
2592 error_at (gimple_location (stmt),
2593 "work-sharing region may not be closely nested inside "
2594 "of work-sharing, critical, ordered, master or explicit "
2595 "task region");
2596 return false;
2597 case GIMPLE_OMP_PARALLEL:
2598 return true;
2599 default:
2600 break;
2602 break;
2603 case GIMPLE_OMP_MASTER:
2604 for (; ctx != NULL; ctx = ctx->outer)
2605 switch (gimple_code (ctx->stmt))
2607 case GIMPLE_OMP_FOR:
2608 case GIMPLE_OMP_SECTIONS:
2609 case GIMPLE_OMP_SINGLE:
2610 case GIMPLE_OMP_TASK:
2611 error_at (gimple_location (stmt),
2612 "master region may not be closely nested inside "
2613 "of work-sharing or explicit task region");
2614 return false;
2615 case GIMPLE_OMP_PARALLEL:
2616 return true;
2617 default:
2618 break;
2620 break;
2621 case GIMPLE_OMP_ORDERED:
2622 for (; ctx != NULL; ctx = ctx->outer)
2623 switch (gimple_code (ctx->stmt))
2625 case GIMPLE_OMP_CRITICAL:
2626 case GIMPLE_OMP_TASK:
2627 error_at (gimple_location (stmt),
2628 "ordered region may not be closely nested inside "
2629 "of critical or explicit task region");
2630 return false;
2631 case GIMPLE_OMP_FOR:
2632 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2633 OMP_CLAUSE_ORDERED) == NULL)
2635 error_at (gimple_location (stmt),
2636 "ordered region must be closely nested inside "
2637 "a loop region with an ordered clause");
2638 return false;
2640 return true;
2641 case GIMPLE_OMP_PARALLEL:
2642 error_at (gimple_location (stmt),
2643 "ordered region must be closely nested inside "
2644 "a loop region with an ordered clause");
2645 return false;
2646 default:
2647 break;
2649 break;
2650 case GIMPLE_OMP_CRITICAL:
2652 tree this_stmt_name
2653 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2654 for (; ctx != NULL; ctx = ctx->outer)
2655 if (gomp_critical *other_crit
2656 = dyn_cast <gomp_critical *> (ctx->stmt))
2657 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2659 error_at (gimple_location (stmt),
2660 "critical region may not be nested inside a critical "
2661 "region with the same name");
2662 return false;
2665 break;
2666 case GIMPLE_OMP_TEAMS:
2667 if (ctx == NULL
2668 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2669 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2671 error_at (gimple_location (stmt),
2672 "teams construct not closely nested inside of target "
2673 "region");
2674 return false;
2676 break;
2677 case GIMPLE_OMP_TARGET:
2678 for (; ctx != NULL; ctx = ctx->outer)
2679 if (is_targetreg_ctx (ctx))
2681 const char *name;
2682 switch (gimple_omp_target_kind (stmt))
2684 case GF_OMP_TARGET_KIND_REGION: name = "target"; break;
2685 case GF_OMP_TARGET_KIND_DATA: name = "target data"; break;
2686 case GF_OMP_TARGET_KIND_UPDATE: name = "target update"; break;
2687 default: gcc_unreachable ();
2689 warning_at (gimple_location (stmt), 0,
2690 "%s construct inside of target region", name);
2692 break;
2693 default:
2694 break;
2696 return true;
2700 /* Helper function scan_omp.
2702 Callback for walk_tree or operators in walk_gimple_stmt used to
2703 scan for OpenMP directives in TP. */
2705 static tree
2706 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2708 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2709 omp_context *ctx = (omp_context *) wi->info;
2710 tree t = *tp;
2712 switch (TREE_CODE (t))
2714 case VAR_DECL:
2715 case PARM_DECL:
2716 case LABEL_DECL:
2717 case RESULT_DECL:
2718 if (ctx)
2719 *tp = remap_decl (t, &ctx->cb);
2720 break;
2722 default:
2723 if (ctx && TYPE_P (t))
2724 *tp = remap_type (t, &ctx->cb);
2725 else if (!DECL_P (t))
2727 *walk_subtrees = 1;
2728 if (ctx)
2730 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2731 if (tem != TREE_TYPE (t))
2733 if (TREE_CODE (t) == INTEGER_CST)
2734 *tp = wide_int_to_tree (tem, t);
2735 else
2736 TREE_TYPE (t) = tem;
2740 break;
2743 return NULL_TREE;
2746 /* Return true if FNDECL is a setjmp or a longjmp. */
2748 static bool
2749 setjmp_or_longjmp_p (const_tree fndecl)
2751 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2752 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2753 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2754 return true;
2756 tree declname = DECL_NAME (fndecl);
2757 if (!declname)
2758 return false;
2759 const char *name = IDENTIFIER_POINTER (declname);
2760 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2764 /* Helper function for scan_omp.
2766 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2767 the current statement in GSI. */
2769 static tree
2770 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2771 struct walk_stmt_info *wi)
2773 gimple stmt = gsi_stmt (*gsi);
2774 omp_context *ctx = (omp_context *) wi->info;
2776 if (gimple_has_location (stmt))
2777 input_location = gimple_location (stmt);
2779 /* Check the OpenMP nesting restrictions. */
2780 bool remove = false;
2781 if (is_gimple_omp (stmt))
2782 remove = !check_omp_nesting_restrictions (stmt, ctx);
2783 else if (is_gimple_call (stmt))
2785 tree fndecl = gimple_call_fndecl (stmt);
2786 if (fndecl)
2788 if (setjmp_or_longjmp_p (fndecl)
2789 && ctx
2790 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2791 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2793 remove = true;
2794 error_at (gimple_location (stmt),
2795 "setjmp/longjmp inside simd construct");
2797 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2798 switch (DECL_FUNCTION_CODE (fndecl))
2800 case BUILT_IN_GOMP_BARRIER:
2801 case BUILT_IN_GOMP_CANCEL:
2802 case BUILT_IN_GOMP_CANCELLATION_POINT:
2803 case BUILT_IN_GOMP_TASKYIELD:
2804 case BUILT_IN_GOMP_TASKWAIT:
2805 case BUILT_IN_GOMP_TASKGROUP_START:
2806 case BUILT_IN_GOMP_TASKGROUP_END:
2807 remove = !check_omp_nesting_restrictions (stmt, ctx);
2808 break;
2809 default:
2810 break;
2814 if (remove)
2816 stmt = gimple_build_nop ();
2817 gsi_replace (gsi, stmt, false);
2820 *handled_ops_p = true;
2822 switch (gimple_code (stmt))
2824 case GIMPLE_OMP_PARALLEL:
2825 taskreg_nesting_level++;
2826 scan_omp_parallel (gsi, ctx);
2827 taskreg_nesting_level--;
2828 break;
2830 case GIMPLE_OMP_TASK:
2831 taskreg_nesting_level++;
2832 scan_omp_task (gsi, ctx);
2833 taskreg_nesting_level--;
2834 break;
2836 case GIMPLE_OMP_FOR:
2837 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
2838 break;
2840 case GIMPLE_OMP_SECTIONS:
2841 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
2842 break;
2844 case GIMPLE_OMP_SINGLE:
2845 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
2846 break;
2848 case GIMPLE_OMP_SECTION:
2849 case GIMPLE_OMP_MASTER:
2850 case GIMPLE_OMP_TASKGROUP:
2851 case GIMPLE_OMP_ORDERED:
2852 case GIMPLE_OMP_CRITICAL:
2853 ctx = new_omp_context (stmt, ctx);
2854 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2855 break;
2857 case GIMPLE_OMP_TARGET:
2858 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
2859 break;
2861 case GIMPLE_OMP_TEAMS:
2862 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
2863 break;
2865 case GIMPLE_BIND:
2867 tree var;
2869 *handled_ops_p = false;
2870 if (ctx)
2871 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
2872 var ;
2873 var = DECL_CHAIN (var))
2874 insert_decl_map (&ctx->cb, var, var);
2876 break;
2877 default:
2878 *handled_ops_p = false;
2879 break;
2882 return NULL_TREE;
2886 /* Scan all the statements starting at the current statement. CTX
2887 contains context information about the OpenMP directives and
2888 clauses found during the scan. */
2890 static void
2891 scan_omp (gimple_seq *body_p, omp_context *ctx)
2893 location_t saved_location;
2894 struct walk_stmt_info wi;
2896 memset (&wi, 0, sizeof (wi));
2897 wi.info = ctx;
2898 wi.want_locations = true;
2900 saved_location = input_location;
2901 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2902 input_location = saved_location;
2905 /* Re-gimplification and code generation routines. */
2907 /* Build a call to GOMP_barrier. */
2909 static gimple
2910 build_omp_barrier (tree lhs)
2912 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2913 : BUILT_IN_GOMP_BARRIER);
2914 gcall *g = gimple_build_call (fndecl, 0);
2915 if (lhs)
2916 gimple_call_set_lhs (g, lhs);
2917 return g;
2920 /* If a context was created for STMT when it was scanned, return it. */
2922 static omp_context *
2923 maybe_lookup_ctx (gimple stmt)
2925 splay_tree_node n;
2926 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2927 return n ? (omp_context *) n->value : NULL;
2931 /* Find the mapping for DECL in CTX or the immediately enclosing
2932 context that has a mapping for DECL.
2934 If CTX is a nested parallel directive, we may have to use the decl
2935 mappings created in CTX's parent context. Suppose that we have the
2936 following parallel nesting (variable UIDs showed for clarity):
2938 iD.1562 = 0;
2939 #omp parallel shared(iD.1562) -> outer parallel
2940 iD.1562 = iD.1562 + 1;
2942 #omp parallel shared (iD.1562) -> inner parallel
2943 iD.1562 = iD.1562 - 1;
2945 Each parallel structure will create a distinct .omp_data_s structure
2946 for copying iD.1562 in/out of the directive:
2948 outer parallel .omp_data_s.1.i -> iD.1562
2949 inner parallel .omp_data_s.2.i -> iD.1562
2951 A shared variable mapping will produce a copy-out operation before
2952 the parallel directive and a copy-in operation after it. So, in
2953 this case we would have:
2955 iD.1562 = 0;
2956 .omp_data_o.1.i = iD.1562;
2957 #omp parallel shared(iD.1562) -> outer parallel
2958 .omp_data_i.1 = &.omp_data_o.1
2959 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2961 .omp_data_o.2.i = iD.1562; -> **
2962 #omp parallel shared(iD.1562) -> inner parallel
2963 .omp_data_i.2 = &.omp_data_o.2
2964 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2967 ** This is a problem. The symbol iD.1562 cannot be referenced
2968 inside the body of the outer parallel region. But since we are
2969 emitting this copy operation while expanding the inner parallel
2970 directive, we need to access the CTX structure of the outer
2971 parallel directive to get the correct mapping:
2973 .omp_data_o.2.i = .omp_data_i.1->i
2975 Since there may be other workshare or parallel directives enclosing
2976 the parallel directive, it may be necessary to walk up the context
2977 parent chain. This is not a problem in general because nested
2978 parallelism happens only rarely. */
2980 static tree
2981 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2983 tree t;
2984 omp_context *up;
2986 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2987 t = maybe_lookup_decl (decl, up);
2989 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2991 return t ? t : decl;
2995 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2996 in outer contexts. */
2998 static tree
2999 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3001 tree t = NULL;
3002 omp_context *up;
3004 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3005 t = maybe_lookup_decl (decl, up);
3007 return t ? t : decl;
3011 /* Construct the initialization value for reduction CLAUSE. */
3013 tree
3014 omp_reduction_init (tree clause, tree type)
3016 location_t loc = OMP_CLAUSE_LOCATION (clause);
3017 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3019 case PLUS_EXPR:
3020 case MINUS_EXPR:
3021 case BIT_IOR_EXPR:
3022 case BIT_XOR_EXPR:
3023 case TRUTH_OR_EXPR:
3024 case TRUTH_ORIF_EXPR:
3025 case TRUTH_XOR_EXPR:
3026 case NE_EXPR:
3027 return build_zero_cst (type);
3029 case MULT_EXPR:
3030 case TRUTH_AND_EXPR:
3031 case TRUTH_ANDIF_EXPR:
3032 case EQ_EXPR:
3033 return fold_convert_loc (loc, type, integer_one_node);
3035 case BIT_AND_EXPR:
3036 return fold_convert_loc (loc, type, integer_minus_one_node);
3038 case MAX_EXPR:
3039 if (SCALAR_FLOAT_TYPE_P (type))
3041 REAL_VALUE_TYPE max, min;
3042 if (HONOR_INFINITIES (TYPE_MODE (type)))
3044 real_inf (&max);
3045 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3047 else
3048 real_maxval (&min, 1, TYPE_MODE (type));
3049 return build_real (type, min);
3051 else
3053 gcc_assert (INTEGRAL_TYPE_P (type));
3054 return TYPE_MIN_VALUE (type);
3057 case MIN_EXPR:
3058 if (SCALAR_FLOAT_TYPE_P (type))
3060 REAL_VALUE_TYPE max;
3061 if (HONOR_INFINITIES (TYPE_MODE (type)))
3062 real_inf (&max);
3063 else
3064 real_maxval (&max, 0, TYPE_MODE (type));
3065 return build_real (type, max);
3067 else
3069 gcc_assert (INTEGRAL_TYPE_P (type));
3070 return TYPE_MAX_VALUE (type);
3073 default:
3074 gcc_unreachable ();
3078 /* Return alignment to be assumed for var in CLAUSE, which should be
3079 OMP_CLAUSE_ALIGNED. */
3081 static tree
3082 omp_clause_aligned_alignment (tree clause)
3084 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3085 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3087 /* Otherwise return implementation defined alignment. */
3088 unsigned int al = 1;
3089 machine_mode mode, vmode;
3090 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3091 if (vs)
3092 vs = 1 << floor_log2 (vs);
3093 static enum mode_class classes[]
3094 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3095 for (int i = 0; i < 4; i += 2)
3096 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3097 mode != VOIDmode;
3098 mode = GET_MODE_WIDER_MODE (mode))
3100 vmode = targetm.vectorize.preferred_simd_mode (mode);
3101 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3102 continue;
3103 while (vs
3104 && GET_MODE_SIZE (vmode) < vs
3105 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3106 vmode = GET_MODE_2XWIDER_MODE (vmode);
3108 tree type = lang_hooks.types.type_for_mode (mode, 1);
3109 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3110 continue;
3111 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3112 / GET_MODE_SIZE (mode));
3113 if (TYPE_MODE (type) != vmode)
3114 continue;
3115 if (TYPE_ALIGN_UNIT (type) > al)
3116 al = TYPE_ALIGN_UNIT (type);
3118 return build_int_cst (integer_type_node, al);
3121 /* Return maximum possible vectorization factor for the target. */
3123 static int
3124 omp_max_vf (void)
3126 if (!optimize
3127 || optimize_debug
3128 || !flag_tree_loop_optimize
3129 || (!flag_tree_loop_vectorize
3130 && (global_options_set.x_flag_tree_loop_vectorize
3131 || global_options_set.x_flag_tree_vectorize)))
3132 return 1;
3134 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3135 if (vs)
3137 vs = 1 << floor_log2 (vs);
3138 return vs;
3140 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3141 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3142 return GET_MODE_NUNITS (vqimode);
3143 return 1;
3146 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3147 privatization. */
3149 static bool
3150 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3151 tree &idx, tree &lane, tree &ivar, tree &lvar)
3153 if (max_vf == 0)
3155 max_vf = omp_max_vf ();
3156 if (max_vf > 1)
3158 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3159 OMP_CLAUSE_SAFELEN);
3160 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3161 max_vf = 1;
3162 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3163 max_vf) == -1)
3164 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3166 if (max_vf > 1)
3168 idx = create_tmp_var (unsigned_type_node, NULL);
3169 lane = create_tmp_var (unsigned_type_node, NULL);
3172 if (max_vf == 1)
3173 return false;
3175 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3176 tree avar = create_tmp_var_raw (atype, NULL);
3177 if (TREE_ADDRESSABLE (new_var))
3178 TREE_ADDRESSABLE (avar) = 1;
3179 DECL_ATTRIBUTES (avar)
3180 = tree_cons (get_identifier ("omp simd array"), NULL,
3181 DECL_ATTRIBUTES (avar));
3182 gimple_add_tmp_var (avar);
3183 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3184 NULL_TREE, NULL_TREE);
3185 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3186 NULL_TREE, NULL_TREE);
3187 if (DECL_P (new_var))
3189 SET_DECL_VALUE_EXPR (new_var, lvar);
3190 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3192 return true;
3195 /* Helper function of lower_rec_input_clauses. For a reference
3196 in simd reduction, add an underlying variable it will reference. */
3198 static void
3199 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3201 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3202 if (TREE_CONSTANT (z))
3204 const char *name = NULL;
3205 if (DECL_NAME (new_vard))
3206 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3208 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3209 gimple_add_tmp_var (z);
3210 TREE_ADDRESSABLE (z) = 1;
3211 z = build_fold_addr_expr_loc (loc, z);
3212 gimplify_assign (new_vard, z, ilist);
3216 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3217 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3218 private variables. Initialization statements go in ILIST, while calls
3219 to destructors go in DLIST. */
3221 static void
3222 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3223 omp_context *ctx, struct omp_for_data *fd)
3225 tree c, dtor, copyin_seq, x, ptr;
3226 bool copyin_by_ref = false;
3227 bool lastprivate_firstprivate = false;
3228 bool reduction_omp_orig_ref = false;
3229 int pass;
3230 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3231 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3232 int max_vf = 0;
3233 tree lane = NULL_TREE, idx = NULL_TREE;
3234 tree ivar = NULL_TREE, lvar = NULL_TREE;
3235 gimple_seq llist[2] = { NULL, NULL };
3237 copyin_seq = NULL;
3239 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3240 with data sharing clauses referencing variable sized vars. That
3241 is unnecessarily hard to support and very unlikely to result in
3242 vectorized code anyway. */
3243 if (is_simd)
3244 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3245 switch (OMP_CLAUSE_CODE (c))
3247 case OMP_CLAUSE_LINEAR:
3248 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3249 max_vf = 1;
3250 /* FALLTHRU */
3251 case OMP_CLAUSE_REDUCTION:
3252 case OMP_CLAUSE_PRIVATE:
3253 case OMP_CLAUSE_FIRSTPRIVATE:
3254 case OMP_CLAUSE_LASTPRIVATE:
3255 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3256 max_vf = 1;
3257 break;
3258 default:
3259 continue;
3262 /* Do all the fixed sized types in the first pass, and the variable sized
3263 types in the second pass. This makes sure that the scalar arguments to
3264 the variable sized types are processed before we use them in the
3265 variable sized operations. */
3266 for (pass = 0; pass < 2; ++pass)
3268 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3270 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3271 tree var, new_var;
3272 bool by_ref;
3273 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3275 switch (c_kind)
3277 case OMP_CLAUSE_PRIVATE:
3278 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3279 continue;
3280 break;
3281 case OMP_CLAUSE_SHARED:
3282 /* Ignore shared directives in teams construct. */
3283 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3284 continue;
3285 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3287 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3288 continue;
3290 case OMP_CLAUSE_FIRSTPRIVATE:
3291 case OMP_CLAUSE_COPYIN:
3292 case OMP_CLAUSE_LINEAR:
3293 break;
3294 case OMP_CLAUSE_REDUCTION:
3295 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3296 reduction_omp_orig_ref = true;
3297 break;
3298 case OMP_CLAUSE__LOOPTEMP_:
3299 /* Handle _looptemp_ clauses only on parallel. */
3300 if (fd)
3301 continue;
3302 break;
3303 case OMP_CLAUSE_LASTPRIVATE:
3304 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3306 lastprivate_firstprivate = true;
3307 if (pass != 0)
3308 continue;
3310 /* Even without corresponding firstprivate, if
3311 decl is Fortran allocatable, it needs outer var
3312 reference. */
3313 else if (pass == 0
3314 && lang_hooks.decls.omp_private_outer_ref
3315 (OMP_CLAUSE_DECL (c)))
3316 lastprivate_firstprivate = true;
3317 break;
3318 case OMP_CLAUSE_ALIGNED:
3319 if (pass == 0)
3320 continue;
3321 var = OMP_CLAUSE_DECL (c);
3322 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3323 && !is_global_var (var))
3325 new_var = maybe_lookup_decl (var, ctx);
3326 if (new_var == NULL_TREE)
3327 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3328 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3329 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3330 omp_clause_aligned_alignment (c));
3331 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3332 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3333 gimplify_and_add (x, ilist);
3335 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3336 && is_global_var (var))
3338 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3339 new_var = lookup_decl (var, ctx);
3340 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3341 t = build_fold_addr_expr_loc (clause_loc, t);
3342 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3343 t = build_call_expr_loc (clause_loc, t2, 2, t,
3344 omp_clause_aligned_alignment (c));
3345 t = fold_convert_loc (clause_loc, ptype, t);
3346 x = create_tmp_var (ptype, NULL);
3347 t = build2 (MODIFY_EXPR, ptype, x, t);
3348 gimplify_and_add (t, ilist);
3349 t = build_simple_mem_ref_loc (clause_loc, x);
3350 SET_DECL_VALUE_EXPR (new_var, t);
3351 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3353 continue;
3354 default:
3355 continue;
3358 new_var = var = OMP_CLAUSE_DECL (c);
3359 if (c_kind != OMP_CLAUSE_COPYIN)
3360 new_var = lookup_decl (var, ctx);
3362 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3364 if (pass != 0)
3365 continue;
3367 else if (is_variable_sized (var))
3369 /* For variable sized types, we need to allocate the
3370 actual storage here. Call alloca and store the
3371 result in the pointer decl that we created elsewhere. */
3372 if (pass == 0)
3373 continue;
3375 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3377 gcall *stmt;
3378 tree tmp, atmp;
3380 ptr = DECL_VALUE_EXPR (new_var);
3381 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3382 ptr = TREE_OPERAND (ptr, 0);
3383 gcc_assert (DECL_P (ptr));
3384 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3386 /* void *tmp = __builtin_alloca */
3387 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3388 stmt = gimple_build_call (atmp, 1, x);
3389 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3390 gimple_add_tmp_var (tmp);
3391 gimple_call_set_lhs (stmt, tmp);
3393 gimple_seq_add_stmt (ilist, stmt);
3395 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3396 gimplify_assign (ptr, x, ilist);
3399 else if (is_reference (var))
3401 /* For references that are being privatized for Fortran,
3402 allocate new backing storage for the new pointer
3403 variable. This allows us to avoid changing all the
3404 code that expects a pointer to something that expects
3405 a direct variable. */
3406 if (pass == 0)
3407 continue;
3409 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3410 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3412 x = build_receiver_ref (var, false, ctx);
3413 x = build_fold_addr_expr_loc (clause_loc, x);
3415 else if (TREE_CONSTANT (x))
3417 /* For reduction in SIMD loop, defer adding the
3418 initialization of the reference, because if we decide
3419 to use SIMD array for it, the initilization could cause
3420 expansion ICE. */
3421 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3422 x = NULL_TREE;
3423 else
3425 const char *name = NULL;
3426 if (DECL_NAME (var))
3427 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3429 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3430 name);
3431 gimple_add_tmp_var (x);
3432 TREE_ADDRESSABLE (x) = 1;
3433 x = build_fold_addr_expr_loc (clause_loc, x);
3436 else
3438 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3439 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3442 if (x)
3444 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3445 gimplify_assign (new_var, x, ilist);
3448 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3450 else if (c_kind == OMP_CLAUSE_REDUCTION
3451 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3453 if (pass == 0)
3454 continue;
3456 else if (pass != 0)
3457 continue;
3459 switch (OMP_CLAUSE_CODE (c))
3461 case OMP_CLAUSE_SHARED:
3462 /* Ignore shared directives in teams construct. */
3463 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3464 continue;
3465 /* Shared global vars are just accessed directly. */
3466 if (is_global_var (new_var))
3467 break;
3468 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3469 needs to be delayed until after fixup_child_record_type so
3470 that we get the correct type during the dereference. */
3471 by_ref = use_pointer_for_field (var, ctx);
3472 x = build_receiver_ref (var, by_ref, ctx);
3473 SET_DECL_VALUE_EXPR (new_var, x);
3474 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3476 /* ??? If VAR is not passed by reference, and the variable
3477 hasn't been initialized yet, then we'll get a warning for
3478 the store into the omp_data_s structure. Ideally, we'd be
3479 able to notice this and not store anything at all, but
3480 we're generating code too early. Suppress the warning. */
3481 if (!by_ref)
3482 TREE_NO_WARNING (var) = 1;
3483 break;
3485 case OMP_CLAUSE_LASTPRIVATE:
3486 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3487 break;
3488 /* FALLTHRU */
3490 case OMP_CLAUSE_PRIVATE:
3491 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3492 x = build_outer_var_ref (var, ctx);
3493 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3495 if (is_task_ctx (ctx))
3496 x = build_receiver_ref (var, false, ctx);
3497 else
3498 x = build_outer_var_ref (var, ctx);
3500 else
3501 x = NULL;
3502 do_private:
3503 tree nx;
3504 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3505 if (is_simd)
3507 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3508 if ((TREE_ADDRESSABLE (new_var) || nx || y
3509 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3510 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3511 idx, lane, ivar, lvar))
3513 if (nx)
3514 x = lang_hooks.decls.omp_clause_default_ctor
3515 (c, unshare_expr (ivar), x);
3516 if (nx && x)
3517 gimplify_and_add (x, &llist[0]);
3518 if (y)
3520 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3521 if (y)
3523 gimple_seq tseq = NULL;
3525 dtor = y;
3526 gimplify_stmt (&dtor, &tseq);
3527 gimple_seq_add_seq (&llist[1], tseq);
3530 break;
3533 if (nx)
3534 gimplify_and_add (nx, ilist);
3535 /* FALLTHRU */
3537 do_dtor:
3538 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3539 if (x)
3541 gimple_seq tseq = NULL;
3543 dtor = x;
3544 gimplify_stmt (&dtor, &tseq);
3545 gimple_seq_add_seq (dlist, tseq);
3547 break;
3549 case OMP_CLAUSE_LINEAR:
3550 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3551 goto do_firstprivate;
3552 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3553 x = NULL;
3554 else
3555 x = build_outer_var_ref (var, ctx);
3556 goto do_private;
3558 case OMP_CLAUSE_FIRSTPRIVATE:
3559 if (is_task_ctx (ctx))
3561 if (is_reference (var) || is_variable_sized (var))
3562 goto do_dtor;
3563 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3564 ctx))
3565 || use_pointer_for_field (var, NULL))
3567 x = build_receiver_ref (var, false, ctx);
3568 SET_DECL_VALUE_EXPR (new_var, x);
3569 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3570 goto do_dtor;
3573 do_firstprivate:
3574 x = build_outer_var_ref (var, ctx);
3575 if (is_simd)
3577 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3578 && gimple_omp_for_combined_into_p (ctx->stmt))
3580 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3581 tree stept = TREE_TYPE (t);
3582 tree ct = find_omp_clause (clauses,
3583 OMP_CLAUSE__LOOPTEMP_);
3584 gcc_assert (ct);
3585 tree l = OMP_CLAUSE_DECL (ct);
3586 tree n1 = fd->loop.n1;
3587 tree step = fd->loop.step;
3588 tree itype = TREE_TYPE (l);
3589 if (POINTER_TYPE_P (itype))
3590 itype = signed_type_for (itype);
3591 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3592 if (TYPE_UNSIGNED (itype)
3593 && fd->loop.cond_code == GT_EXPR)
3594 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3595 fold_build1 (NEGATE_EXPR, itype, l),
3596 fold_build1 (NEGATE_EXPR,
3597 itype, step));
3598 else
3599 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3600 t = fold_build2 (MULT_EXPR, stept,
3601 fold_convert (stept, l), t);
3603 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3605 x = lang_hooks.decls.omp_clause_linear_ctor
3606 (c, new_var, x, t);
3607 gimplify_and_add (x, ilist);
3608 goto do_dtor;
3611 if (POINTER_TYPE_P (TREE_TYPE (x)))
3612 x = fold_build2 (POINTER_PLUS_EXPR,
3613 TREE_TYPE (x), x, t);
3614 else
3615 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3618 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3619 || TREE_ADDRESSABLE (new_var))
3620 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3621 idx, lane, ivar, lvar))
3623 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3625 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3626 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3627 gimplify_and_add (x, ilist);
3628 gimple_stmt_iterator gsi
3629 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3630 gassign *g
3631 = gimple_build_assign (unshare_expr (lvar), iv);
3632 gsi_insert_before_without_update (&gsi, g,
3633 GSI_SAME_STMT);
3634 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3635 enum tree_code code = PLUS_EXPR;
3636 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3637 code = POINTER_PLUS_EXPR;
3638 g = gimple_build_assign_with_ops (code, iv, iv, t);
3639 gsi_insert_before_without_update (&gsi, g,
3640 GSI_SAME_STMT);
3641 break;
3643 x = lang_hooks.decls.omp_clause_copy_ctor
3644 (c, unshare_expr (ivar), x);
3645 gimplify_and_add (x, &llist[0]);
3646 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3647 if (x)
3649 gimple_seq tseq = NULL;
3651 dtor = x;
3652 gimplify_stmt (&dtor, &tseq);
3653 gimple_seq_add_seq (&llist[1], tseq);
3655 break;
3658 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3659 gimplify_and_add (x, ilist);
3660 goto do_dtor;
3662 case OMP_CLAUSE__LOOPTEMP_:
3663 gcc_assert (is_parallel_ctx (ctx));
3664 x = build_outer_var_ref (var, ctx);
3665 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3666 gimplify_and_add (x, ilist);
3667 break;
3669 case OMP_CLAUSE_COPYIN:
3670 by_ref = use_pointer_for_field (var, NULL);
3671 x = build_receiver_ref (var, by_ref, ctx);
3672 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3673 append_to_statement_list (x, &copyin_seq);
3674 copyin_by_ref |= by_ref;
3675 break;
3677 case OMP_CLAUSE_REDUCTION:
3678 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3680 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3681 gimple tseq;
3682 x = build_outer_var_ref (var, ctx);
3684 if (is_reference (var)
3685 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3686 TREE_TYPE (x)))
3687 x = build_fold_addr_expr_loc (clause_loc, x);
3688 SET_DECL_VALUE_EXPR (placeholder, x);
3689 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3690 tree new_vard = new_var;
3691 if (is_reference (var))
3693 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3694 new_vard = TREE_OPERAND (new_var, 0);
3695 gcc_assert (DECL_P (new_vard));
3697 if (is_simd
3698 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3699 idx, lane, ivar, lvar))
3701 if (new_vard == new_var)
3703 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3704 SET_DECL_VALUE_EXPR (new_var, ivar);
3706 else
3708 SET_DECL_VALUE_EXPR (new_vard,
3709 build_fold_addr_expr (ivar));
3710 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3712 x = lang_hooks.decls.omp_clause_default_ctor
3713 (c, unshare_expr (ivar),
3714 build_outer_var_ref (var, ctx));
3715 if (x)
3716 gimplify_and_add (x, &llist[0]);
3717 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3719 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3720 lower_omp (&tseq, ctx);
3721 gimple_seq_add_seq (&llist[0], tseq);
3723 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3724 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3725 lower_omp (&tseq, ctx);
3726 gimple_seq_add_seq (&llist[1], tseq);
3727 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3728 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3729 if (new_vard == new_var)
3730 SET_DECL_VALUE_EXPR (new_var, lvar);
3731 else
3732 SET_DECL_VALUE_EXPR (new_vard,
3733 build_fold_addr_expr (lvar));
3734 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3735 if (x)
3737 tseq = NULL;
3738 dtor = x;
3739 gimplify_stmt (&dtor, &tseq);
3740 gimple_seq_add_seq (&llist[1], tseq);
3742 break;
3744 /* If this is a reference to constant size reduction var
3745 with placeholder, we haven't emitted the initializer
3746 for it because it is undesirable if SIMD arrays are used.
3747 But if they aren't used, we need to emit the deferred
3748 initialization now. */
3749 else if (is_reference (var) && is_simd)
3750 handle_simd_reference (clause_loc, new_vard, ilist);
3751 x = lang_hooks.decls.omp_clause_default_ctor
3752 (c, unshare_expr (new_var),
3753 build_outer_var_ref (var, ctx));
3754 if (x)
3755 gimplify_and_add (x, ilist);
3756 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3758 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3759 lower_omp (&tseq, ctx);
3760 gimple_seq_add_seq (ilist, tseq);
3762 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3763 if (is_simd)
3765 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3766 lower_omp (&tseq, ctx);
3767 gimple_seq_add_seq (dlist, tseq);
3768 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3770 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3771 goto do_dtor;
3773 else
3775 x = omp_reduction_init (c, TREE_TYPE (new_var));
3776 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3777 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3779 /* reduction(-:var) sums up the partial results, so it
3780 acts identically to reduction(+:var). */
3781 if (code == MINUS_EXPR)
3782 code = PLUS_EXPR;
3784 tree new_vard = new_var;
3785 if (is_simd && is_reference (var))
3787 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3788 new_vard = TREE_OPERAND (new_var, 0);
3789 gcc_assert (DECL_P (new_vard));
3791 if (is_simd
3792 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3793 idx, lane, ivar, lvar))
3795 tree ref = build_outer_var_ref (var, ctx);
3797 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3799 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3800 ref = build_outer_var_ref (var, ctx);
3801 gimplify_assign (ref, x, &llist[1]);
3803 if (new_vard != new_var)
3805 SET_DECL_VALUE_EXPR (new_vard,
3806 build_fold_addr_expr (lvar));
3807 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3810 else
3812 if (is_reference (var) && is_simd)
3813 handle_simd_reference (clause_loc, new_vard, ilist);
3814 gimplify_assign (new_var, x, ilist);
3815 if (is_simd)
3817 tree ref = build_outer_var_ref (var, ctx);
3819 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3820 ref = build_outer_var_ref (var, ctx);
3821 gimplify_assign (ref, x, dlist);
3825 break;
3827 default:
3828 gcc_unreachable ();
3833 if (lane)
3835 tree uid = create_tmp_var (ptr_type_node, "simduid");
3836 /* Don't want uninit warnings on simduid, it is always uninitialized,
3837 but we use it not for the value, but for the DECL_UID only. */
3838 TREE_NO_WARNING (uid) = 1;
3839 gimple g
3840 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3841 gimple_call_set_lhs (g, lane);
3842 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3843 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3844 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3845 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3846 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3847 gimple_omp_for_set_clauses (ctx->stmt, c);
3848 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3849 build_int_cst (unsigned_type_node, 0));
3850 gimple_seq_add_stmt (ilist, g);
3851 for (int i = 0; i < 2; i++)
3852 if (llist[i])
3854 tree vf = create_tmp_var (unsigned_type_node, NULL);
3855 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3856 gimple_call_set_lhs (g, vf);
3857 gimple_seq *seq = i == 0 ? ilist : dlist;
3858 gimple_seq_add_stmt (seq, g);
3859 tree t = build_int_cst (unsigned_type_node, 0);
3860 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t);
3861 gimple_seq_add_stmt (seq, g);
3862 tree body = create_artificial_label (UNKNOWN_LOCATION);
3863 tree header = create_artificial_label (UNKNOWN_LOCATION);
3864 tree end = create_artificial_label (UNKNOWN_LOCATION);
3865 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3866 gimple_seq_add_stmt (seq, gimple_build_label (body));
3867 gimple_seq_add_seq (seq, llist[i]);
3868 t = build_int_cst (unsigned_type_node, 1);
3869 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3870 gimple_seq_add_stmt (seq, g);
3871 gimple_seq_add_stmt (seq, gimple_build_label (header));
3872 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3873 gimple_seq_add_stmt (seq, g);
3874 gimple_seq_add_stmt (seq, gimple_build_label (end));
3878 /* The copyin sequence is not to be executed by the main thread, since
3879 that would result in self-copies. Perhaps not visible to scalars,
3880 but it certainly is to C++ operator=. */
3881 if (copyin_seq)
3883 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3885 x = build2 (NE_EXPR, boolean_type_node, x,
3886 build_int_cst (TREE_TYPE (x), 0));
3887 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3888 gimplify_and_add (x, ilist);
3891 /* If any copyin variable is passed by reference, we must ensure the
3892 master thread doesn't modify it before it is copied over in all
3893 threads. Similarly for variables in both firstprivate and
3894 lastprivate clauses we need to ensure the lastprivate copying
3895 happens after firstprivate copying in all threads. And similarly
3896 for UDRs if initializer expression refers to omp_orig. */
3897 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3899 /* Don't add any barrier for #pragma omp simd or
3900 #pragma omp distribute. */
3901 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3902 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3903 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3906 /* If max_vf is non-zero, then we can use only a vectorization factor
3907 up to the max_vf we chose. So stick it into the safelen clause. */
3908 if (max_vf)
3910 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3911 OMP_CLAUSE_SAFELEN);
3912 if (c == NULL_TREE
3913 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
3914 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3915 max_vf) == 1))
3917 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3918 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3919 max_vf);
3920 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3921 gimple_omp_for_set_clauses (ctx->stmt, c);
3927 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3928 both parallel and workshare constructs. PREDICATE may be NULL if it's
3929 always true. */
3931 static void
3932 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3933 omp_context *ctx)
3935 tree x, c, label = NULL, orig_clauses = clauses;
3936 bool par_clauses = false;
3937 tree simduid = NULL, lastlane = NULL;
3939 /* Early exit if there are no lastprivate or linear clauses. */
3940 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3941 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3942 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3943 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3944 break;
3945 if (clauses == NULL)
3947 /* If this was a workshare clause, see if it had been combined
3948 with its parallel. In that case, look for the clauses on the
3949 parallel statement itself. */
3950 if (is_parallel_ctx (ctx))
3951 return;
3953 ctx = ctx->outer;
3954 if (ctx == NULL || !is_parallel_ctx (ctx))
3955 return;
3957 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3958 OMP_CLAUSE_LASTPRIVATE);
3959 if (clauses == NULL)
3960 return;
3961 par_clauses = true;
3964 if (predicate)
3966 gcond *stmt;
3967 tree label_true, arm1, arm2;
3969 label = create_artificial_label (UNKNOWN_LOCATION);
3970 label_true = create_artificial_label (UNKNOWN_LOCATION);
3971 arm1 = TREE_OPERAND (predicate, 0);
3972 arm2 = TREE_OPERAND (predicate, 1);
3973 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3974 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3975 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3976 label_true, label);
3977 gimple_seq_add_stmt (stmt_list, stmt);
3978 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3981 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3982 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3984 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3985 if (simduid)
3986 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3989 for (c = clauses; c ;)
3991 tree var, new_var;
3992 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3994 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3995 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3996 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3998 var = OMP_CLAUSE_DECL (c);
3999 new_var = lookup_decl (var, ctx);
4001 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4003 tree val = DECL_VALUE_EXPR (new_var);
4004 if (TREE_CODE (val) == ARRAY_REF
4005 && VAR_P (TREE_OPERAND (val, 0))
4006 && lookup_attribute ("omp simd array",
4007 DECL_ATTRIBUTES (TREE_OPERAND (val,
4008 0))))
4010 if (lastlane == NULL)
4012 lastlane = create_tmp_var (unsigned_type_node, NULL);
4013 gcall *g
4014 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4015 2, simduid,
4016 TREE_OPERAND (val, 1));
4017 gimple_call_set_lhs (g, lastlane);
4018 gimple_seq_add_stmt (stmt_list, g);
4020 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4021 TREE_OPERAND (val, 0), lastlane,
4022 NULL_TREE, NULL_TREE);
4026 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4027 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4029 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4030 gimple_seq_add_seq (stmt_list,
4031 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4032 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4034 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4035 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4037 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4038 gimple_seq_add_seq (stmt_list,
4039 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4040 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4043 x = build_outer_var_ref (var, ctx);
4044 if (is_reference (var))
4045 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4046 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4047 gimplify_and_add (x, stmt_list);
4049 c = OMP_CLAUSE_CHAIN (c);
4050 if (c == NULL && !par_clauses)
4052 /* If this was a workshare clause, see if it had been combined
4053 with its parallel. In that case, continue looking for the
4054 clauses also on the parallel statement itself. */
4055 if (is_parallel_ctx (ctx))
4056 break;
4058 ctx = ctx->outer;
4059 if (ctx == NULL || !is_parallel_ctx (ctx))
4060 break;
4062 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4063 OMP_CLAUSE_LASTPRIVATE);
4064 par_clauses = true;
4068 if (label)
4069 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4073 /* Generate code to implement the REDUCTION clauses. */
4075 static void
4076 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4078 gimple_seq sub_seq = NULL;
4079 gimple stmt;
4080 tree x, c;
4081 int count = 0;
4083 /* SIMD reductions are handled in lower_rec_input_clauses. */
4084 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4085 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4086 return;
4088 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4089 update in that case, otherwise use a lock. */
4090 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4091 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4093 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4095 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4096 count = -1;
4097 break;
4099 count++;
4102 if (count == 0)
4103 return;
4105 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4107 tree var, ref, new_var;
4108 enum tree_code code;
4109 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4111 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4112 continue;
4114 var = OMP_CLAUSE_DECL (c);
4115 new_var = lookup_decl (var, ctx);
4116 if (is_reference (var))
4117 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4118 ref = build_outer_var_ref (var, ctx);
4119 code = OMP_CLAUSE_REDUCTION_CODE (c);
4121 /* reduction(-:var) sums up the partial results, so it acts
4122 identically to reduction(+:var). */
4123 if (code == MINUS_EXPR)
4124 code = PLUS_EXPR;
4126 if (count == 1)
4128 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4130 addr = save_expr (addr);
4131 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4132 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4133 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4134 gimplify_and_add (x, stmt_seqp);
4135 return;
4138 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4140 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4142 if (is_reference (var)
4143 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4144 TREE_TYPE (ref)))
4145 ref = build_fold_addr_expr_loc (clause_loc, ref);
4146 SET_DECL_VALUE_EXPR (placeholder, ref);
4147 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4148 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4149 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4150 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4151 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4153 else
4155 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4156 ref = build_outer_var_ref (var, ctx);
4157 gimplify_assign (ref, x, &sub_seq);
4161 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4163 gimple_seq_add_stmt (stmt_seqp, stmt);
4165 gimple_seq_add_seq (stmt_seqp, sub_seq);
4167 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4169 gimple_seq_add_stmt (stmt_seqp, stmt);
4173 /* Generate code to implement the COPYPRIVATE clauses. */
4175 static void
4176 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4177 omp_context *ctx)
4179 tree c;
4181 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4183 tree var, new_var, ref, x;
4184 bool by_ref;
4185 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4187 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4188 continue;
4190 var = OMP_CLAUSE_DECL (c);
4191 by_ref = use_pointer_for_field (var, NULL);
4193 ref = build_sender_ref (var, ctx);
4194 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4195 if (by_ref)
4197 x = build_fold_addr_expr_loc (clause_loc, new_var);
4198 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4200 gimplify_assign (ref, x, slist);
4202 ref = build_receiver_ref (var, false, ctx);
4203 if (by_ref)
4205 ref = fold_convert_loc (clause_loc,
4206 build_pointer_type (TREE_TYPE (new_var)),
4207 ref);
4208 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4210 if (is_reference (var))
4212 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4213 ref = build_simple_mem_ref_loc (clause_loc, ref);
4214 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4216 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4217 gimplify_and_add (x, rlist);
4222 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4223 and REDUCTION from the sender (aka parent) side. */
4225 static void
4226 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4227 omp_context *ctx)
4229 tree c;
4231 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4233 tree val, ref, x, var;
4234 bool by_ref, do_in = false, do_out = false;
4235 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4237 switch (OMP_CLAUSE_CODE (c))
4239 case OMP_CLAUSE_PRIVATE:
4240 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4241 break;
4242 continue;
4243 case OMP_CLAUSE_FIRSTPRIVATE:
4244 case OMP_CLAUSE_COPYIN:
4245 case OMP_CLAUSE_LASTPRIVATE:
4246 case OMP_CLAUSE_REDUCTION:
4247 case OMP_CLAUSE__LOOPTEMP_:
4248 break;
4249 default:
4250 continue;
4253 val = OMP_CLAUSE_DECL (c);
4254 var = lookup_decl_in_outer_ctx (val, ctx);
4256 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4257 && is_global_var (var))
4258 continue;
4259 if (is_variable_sized (val))
4260 continue;
4261 by_ref = use_pointer_for_field (val, NULL);
4263 switch (OMP_CLAUSE_CODE (c))
4265 case OMP_CLAUSE_PRIVATE:
4266 case OMP_CLAUSE_FIRSTPRIVATE:
4267 case OMP_CLAUSE_COPYIN:
4268 case OMP_CLAUSE__LOOPTEMP_:
4269 do_in = true;
4270 break;
4272 case OMP_CLAUSE_LASTPRIVATE:
4273 if (by_ref || is_reference (val))
4275 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4276 continue;
4277 do_in = true;
4279 else
4281 do_out = true;
4282 if (lang_hooks.decls.omp_private_outer_ref (val))
4283 do_in = true;
4285 break;
4287 case OMP_CLAUSE_REDUCTION:
4288 do_in = true;
4289 do_out = !(by_ref || is_reference (val));
4290 break;
4292 default:
4293 gcc_unreachable ();
4296 if (do_in)
4298 ref = build_sender_ref (val, ctx);
4299 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4300 gimplify_assign (ref, x, ilist);
4301 if (is_task_ctx (ctx))
4302 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4305 if (do_out)
4307 ref = build_sender_ref (val, ctx);
4308 gimplify_assign (var, ref, olist);
4313 /* Generate code to implement SHARED from the sender (aka parent)
4314 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4315 list things that got automatically shared. */
4317 static void
4318 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4320 tree var, ovar, nvar, f, x, record_type;
4322 if (ctx->record_type == NULL)
4323 return;
4325 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4326 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4328 ovar = DECL_ABSTRACT_ORIGIN (f);
4329 nvar = maybe_lookup_decl (ovar, ctx);
4330 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4331 continue;
4333 /* If CTX is a nested parallel directive. Find the immediately
4334 enclosing parallel or workshare construct that contains a
4335 mapping for OVAR. */
4336 var = lookup_decl_in_outer_ctx (ovar, ctx);
4338 if (use_pointer_for_field (ovar, ctx))
4340 x = build_sender_ref (ovar, ctx);
4341 var = build_fold_addr_expr (var);
4342 gimplify_assign (x, var, ilist);
4344 else
4346 x = build_sender_ref (ovar, ctx);
4347 gimplify_assign (x, var, ilist);
4349 if (!TREE_READONLY (var)
4350 /* We don't need to receive a new reference to a result
4351 or parm decl. In fact we may not store to it as we will
4352 invalidate any pending RSO and generate wrong gimple
4353 during inlining. */
4354 && !((TREE_CODE (var) == RESULT_DECL
4355 || TREE_CODE (var) == PARM_DECL)
4356 && DECL_BY_REFERENCE (var)))
4358 x = build_sender_ref (ovar, ctx);
4359 gimplify_assign (var, x, olist);
4366 /* A convenience function to build an empty GIMPLE_COND with just the
4367 condition. */
4369 static gcond *
4370 gimple_build_cond_empty (tree cond)
4372 enum tree_code pred_code;
4373 tree lhs, rhs;
4375 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4376 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4380 /* Build the function calls to GOMP_parallel_start etc to actually
4381 generate the parallel operation. REGION is the parallel region
4382 being expanded. BB is the block where to insert the code. WS_ARGS
4383 will be set if this is a call to a combined parallel+workshare
4384 construct, it contains the list of additional arguments needed by
4385 the workshare construct. */
4387 static void
4388 expand_parallel_call (struct omp_region *region, basic_block bb,
4389 gomp_parallel *entry_stmt,
4390 vec<tree, va_gc> *ws_args)
4392 tree t, t1, t2, val, cond, c, clauses, flags;
4393 gimple_stmt_iterator gsi;
4394 gimple stmt;
4395 enum built_in_function start_ix;
4396 int start_ix2;
4397 location_t clause_loc;
4398 vec<tree, va_gc> *args;
4400 clauses = gimple_omp_parallel_clauses (entry_stmt);
4402 /* Determine what flavor of GOMP_parallel we will be
4403 emitting. */
4404 start_ix = BUILT_IN_GOMP_PARALLEL;
4405 if (is_combined_parallel (region))
4407 switch (region->inner->type)
4409 case GIMPLE_OMP_FOR:
4410 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4411 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4412 + (region->inner->sched_kind
4413 == OMP_CLAUSE_SCHEDULE_RUNTIME
4414 ? 3 : region->inner->sched_kind));
4415 start_ix = (enum built_in_function)start_ix2;
4416 break;
4417 case GIMPLE_OMP_SECTIONS:
4418 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4419 break;
4420 default:
4421 gcc_unreachable ();
4425 /* By default, the value of NUM_THREADS is zero (selected at run time)
4426 and there is no conditional. */
4427 cond = NULL_TREE;
4428 val = build_int_cst (unsigned_type_node, 0);
4429 flags = build_int_cst (unsigned_type_node, 0);
4431 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4432 if (c)
4433 cond = OMP_CLAUSE_IF_EXPR (c);
4435 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4436 if (c)
4438 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4439 clause_loc = OMP_CLAUSE_LOCATION (c);
4441 else
4442 clause_loc = gimple_location (entry_stmt);
4444 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4445 if (c)
4446 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4448 /* Ensure 'val' is of the correct type. */
4449 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4451 /* If we found the clause 'if (cond)', build either
4452 (cond != 0) or (cond ? val : 1u). */
4453 if (cond)
4455 cond = gimple_boolify (cond);
4457 if (integer_zerop (val))
4458 val = fold_build2_loc (clause_loc,
4459 EQ_EXPR, unsigned_type_node, cond,
4460 build_int_cst (TREE_TYPE (cond), 0));
4461 else
4463 basic_block cond_bb, then_bb, else_bb;
4464 edge e, e_then, e_else;
4465 tree tmp_then, tmp_else, tmp_join, tmp_var;
4467 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4468 if (gimple_in_ssa_p (cfun))
4470 tmp_then = make_ssa_name (tmp_var, NULL);
4471 tmp_else = make_ssa_name (tmp_var, NULL);
4472 tmp_join = make_ssa_name (tmp_var, NULL);
4474 else
4476 tmp_then = tmp_var;
4477 tmp_else = tmp_var;
4478 tmp_join = tmp_var;
4481 e = split_block (bb, NULL);
4482 cond_bb = e->src;
4483 bb = e->dest;
4484 remove_edge (e);
4486 then_bb = create_empty_bb (cond_bb);
4487 else_bb = create_empty_bb (then_bb);
4488 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4489 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4491 stmt = gimple_build_cond_empty (cond);
4492 gsi = gsi_start_bb (cond_bb);
4493 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4495 gsi = gsi_start_bb (then_bb);
4496 stmt = gimple_build_assign (tmp_then, val);
4497 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4499 gsi = gsi_start_bb (else_bb);
4500 stmt = gimple_build_assign
4501 (tmp_else, build_int_cst (unsigned_type_node, 1));
4502 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4504 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4505 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4506 add_bb_to_loop (then_bb, cond_bb->loop_father);
4507 add_bb_to_loop (else_bb, cond_bb->loop_father);
4508 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4509 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4511 if (gimple_in_ssa_p (cfun))
4513 gphi *phi = create_phi_node (tmp_join, bb);
4514 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4515 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4518 val = tmp_join;
4521 gsi = gsi_start_bb (bb);
4522 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4523 false, GSI_CONTINUE_LINKING);
4526 gsi = gsi_last_bb (bb);
4527 t = gimple_omp_parallel_data_arg (entry_stmt);
4528 if (t == NULL)
4529 t1 = null_pointer_node;
4530 else
4531 t1 = build_fold_addr_expr (t);
4532 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4534 vec_alloc (args, 4 + vec_safe_length (ws_args));
4535 args->quick_push (t2);
4536 args->quick_push (t1);
4537 args->quick_push (val);
4538 if (ws_args)
4539 args->splice (*ws_args);
4540 args->quick_push (flags);
4542 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4543 builtin_decl_explicit (start_ix), args);
4545 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4546 false, GSI_CONTINUE_LINKING);
4549 /* Insert a function call whose name is FUNC_NAME with the information from
4550 ENTRY_STMT into the basic_block BB. */
4552 static void
4553 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
4554 vec <tree, va_gc> *ws_args)
4556 tree t, t1, t2;
4557 gimple_stmt_iterator gsi;
4558 vec <tree, va_gc> *args;
4560 gcc_assert (vec_safe_length (ws_args) == 2);
4561 tree func_name = (*ws_args)[0];
4562 tree grain = (*ws_args)[1];
4564 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
4565 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
4566 gcc_assert (count != NULL_TREE);
4567 count = OMP_CLAUSE_OPERAND (count, 0);
4569 gsi = gsi_last_bb (bb);
4570 t = gimple_omp_parallel_data_arg (entry_stmt);
4571 if (t == NULL)
4572 t1 = null_pointer_node;
4573 else
4574 t1 = build_fold_addr_expr (t);
4575 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4577 vec_alloc (args, 4);
4578 args->quick_push (t2);
4579 args->quick_push (t1);
4580 args->quick_push (count);
4581 args->quick_push (grain);
4582 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
4584 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
4585 GSI_CONTINUE_LINKING);
4588 /* Build the function call to GOMP_task to actually
4589 generate the task operation. BB is the block where to insert the code. */
4591 static void
4592 expand_task_call (basic_block bb, gomp_task *entry_stmt)
4594 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4595 gimple_stmt_iterator gsi;
4596 location_t loc = gimple_location (entry_stmt);
4598 clauses = gimple_omp_task_clauses (entry_stmt);
4600 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4601 if (c)
4602 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4603 else
4604 cond = boolean_true_node;
4606 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4607 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4608 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4609 flags = build_int_cst (unsigned_type_node,
4610 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4612 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4613 if (c)
4615 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4616 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4617 build_int_cst (unsigned_type_node, 2),
4618 build_int_cst (unsigned_type_node, 0));
4619 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4621 if (depend)
4622 depend = OMP_CLAUSE_DECL (depend);
4623 else
4624 depend = build_int_cst (ptr_type_node, 0);
4626 gsi = gsi_last_bb (bb);
4627 t = gimple_omp_task_data_arg (entry_stmt);
4628 if (t == NULL)
4629 t2 = null_pointer_node;
4630 else
4631 t2 = build_fold_addr_expr_loc (loc, t);
4632 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4633 t = gimple_omp_task_copy_fn (entry_stmt);
4634 if (t == NULL)
4635 t3 = null_pointer_node;
4636 else
4637 t3 = build_fold_addr_expr_loc (loc, t);
4639 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4640 8, t1, t2, t3,
4641 gimple_omp_task_arg_size (entry_stmt),
4642 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4643 depend);
4645 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4646 false, GSI_CONTINUE_LINKING);
4650 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4651 catch handler and return it. This prevents programs from violating the
4652 structured block semantics with throws. */
4654 static gimple_seq
4655 maybe_catch_exception (gimple_seq body)
4657 gimple g;
4658 tree decl;
4660 if (!flag_exceptions)
4661 return body;
4663 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4664 decl = lang_hooks.eh_protect_cleanup_actions ();
4665 else
4666 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4668 g = gimple_build_eh_must_not_throw (decl);
4669 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4670 GIMPLE_TRY_CATCH);
4672 return gimple_seq_alloc_with_stmt (g);
4675 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4677 static tree
4678 vec2chain (vec<tree, va_gc> *v)
4680 tree chain = NULL_TREE, t;
4681 unsigned ix;
4683 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4685 DECL_CHAIN (t) = chain;
4686 chain = t;
4689 return chain;
4693 /* Remove barriers in REGION->EXIT's block. Note that this is only
4694 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4695 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4696 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4697 removed. */
4699 static void
4700 remove_exit_barrier (struct omp_region *region)
4702 gimple_stmt_iterator gsi;
4703 basic_block exit_bb;
4704 edge_iterator ei;
4705 edge e;
4706 gimple stmt;
4707 int any_addressable_vars = -1;
4709 exit_bb = region->exit;
4711 /* If the parallel region doesn't return, we don't have REGION->EXIT
4712 block at all. */
4713 if (! exit_bb)
4714 return;
4716 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4717 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4718 statements that can appear in between are extremely limited -- no
4719 memory operations at all. Here, we allow nothing at all, so the
4720 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4721 gsi = gsi_last_bb (exit_bb);
4722 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4723 gsi_prev (&gsi);
4724 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4725 return;
4727 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4729 gsi = gsi_last_bb (e->src);
4730 if (gsi_end_p (gsi))
4731 continue;
4732 stmt = gsi_stmt (gsi);
4733 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4734 && !gimple_omp_return_nowait_p (stmt))
4736 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4737 in many cases. If there could be tasks queued, the barrier
4738 might be needed to let the tasks run before some local
4739 variable of the parallel that the task uses as shared
4740 runs out of scope. The task can be spawned either
4741 from within current function (this would be easy to check)
4742 or from some function it calls and gets passed an address
4743 of such a variable. */
4744 if (any_addressable_vars < 0)
4746 gomp_parallel *parallel_stmt
4747 = as_a <gomp_parallel *> (last_stmt (region->entry));
4748 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4749 tree local_decls, block, decl;
4750 unsigned ix;
4752 any_addressable_vars = 0;
4753 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4754 if (TREE_ADDRESSABLE (decl))
4756 any_addressable_vars = 1;
4757 break;
4759 for (block = gimple_block (stmt);
4760 !any_addressable_vars
4761 && block
4762 && TREE_CODE (block) == BLOCK;
4763 block = BLOCK_SUPERCONTEXT (block))
4765 for (local_decls = BLOCK_VARS (block);
4766 local_decls;
4767 local_decls = DECL_CHAIN (local_decls))
4768 if (TREE_ADDRESSABLE (local_decls))
4770 any_addressable_vars = 1;
4771 break;
4773 if (block == gimple_block (parallel_stmt))
4774 break;
4777 if (!any_addressable_vars)
4778 gimple_omp_return_set_nowait (stmt);
4783 static void
4784 remove_exit_barriers (struct omp_region *region)
4786 if (region->type == GIMPLE_OMP_PARALLEL)
4787 remove_exit_barrier (region);
4789 if (region->inner)
4791 region = region->inner;
4792 remove_exit_barriers (region);
4793 while (region->next)
4795 region = region->next;
4796 remove_exit_barriers (region);
4801 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4802 calls. These can't be declared as const functions, but
4803 within one parallel body they are constant, so they can be
4804 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4805 which are declared const. Similarly for task body, except
4806 that in untied task omp_get_thread_num () can change at any task
4807 scheduling point. */
4809 static void
4810 optimize_omp_library_calls (gimple entry_stmt)
4812 basic_block bb;
4813 gimple_stmt_iterator gsi;
4814 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4815 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4816 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4817 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4818 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4819 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4820 OMP_CLAUSE_UNTIED) != NULL);
4822 FOR_EACH_BB_FN (bb, cfun)
4823 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4825 gimple call = gsi_stmt (gsi);
4826 tree decl;
4828 if (is_gimple_call (call)
4829 && (decl = gimple_call_fndecl (call))
4830 && DECL_EXTERNAL (decl)
4831 && TREE_PUBLIC (decl)
4832 && DECL_INITIAL (decl) == NULL)
4834 tree built_in;
4836 if (DECL_NAME (decl) == thr_num_id)
4838 /* In #pragma omp task untied omp_get_thread_num () can change
4839 during the execution of the task region. */
4840 if (untied_task)
4841 continue;
4842 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4844 else if (DECL_NAME (decl) == num_thr_id)
4845 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4846 else
4847 continue;
4849 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4850 || gimple_call_num_args (call) != 0)
4851 continue;
4853 if (flag_exceptions && !TREE_NOTHROW (decl))
4854 continue;
4856 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4857 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4858 TREE_TYPE (TREE_TYPE (built_in))))
4859 continue;
4861 gimple_call_set_fndecl (call, built_in);
4866 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4867 regimplified. */
4869 static tree
4870 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4872 tree t = *tp;
4874 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4875 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4876 return t;
4878 if (TREE_CODE (t) == ADDR_EXPR)
4879 recompute_tree_invariant_for_addr_expr (t);
4881 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4882 return NULL_TREE;
4885 /* Prepend TO = FROM assignment before *GSI_P. */
4887 static void
4888 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4890 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4891 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4892 true, GSI_SAME_STMT);
4893 gimple stmt = gimple_build_assign (to, from);
4894 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4895 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4896 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4898 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4899 gimple_regimplify_operands (stmt, &gsi);
4903 /* Expand the OpenMP parallel or task directive starting at REGION. */
4905 static void
4906 expand_omp_taskreg (struct omp_region *region)
4908 basic_block entry_bb, exit_bb, new_bb;
4909 struct function *child_cfun;
4910 tree child_fn, block, t;
4911 gimple_stmt_iterator gsi;
4912 gimple entry_stmt, stmt;
4913 edge e;
4914 vec<tree, va_gc> *ws_args;
4916 entry_stmt = last_stmt (region->entry);
4917 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4918 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4920 entry_bb = region->entry;
4921 exit_bb = region->exit;
4923 bool is_cilk_for
4924 = (flag_cilkplus
4925 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
4926 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
4927 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
4929 if (is_cilk_for)
4930 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
4931 and the inner statement contains the name of the built-in function
4932 and grain. */
4933 ws_args = region->inner->ws_args;
4934 else if (is_combined_parallel (region))
4935 ws_args = region->ws_args;
4936 else
4937 ws_args = NULL;
4939 if (child_cfun->cfg)
4941 /* Due to inlining, it may happen that we have already outlined
4942 the region, in which case all we need to do is make the
4943 sub-graph unreachable and emit the parallel call. */
4944 edge entry_succ_e, exit_succ_e;
4946 entry_succ_e = single_succ_edge (entry_bb);
4948 gsi = gsi_last_bb (entry_bb);
4949 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4950 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4951 gsi_remove (&gsi, true);
4953 new_bb = entry_bb;
4954 if (exit_bb)
4956 exit_succ_e = single_succ_edge (exit_bb);
4957 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4959 remove_edge_and_dominated_blocks (entry_succ_e);
4961 else
4963 unsigned srcidx, dstidx, num;
4965 /* If the parallel region needs data sent from the parent
4966 function, then the very first statement (except possible
4967 tree profile counter updates) of the parallel body
4968 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4969 &.OMP_DATA_O is passed as an argument to the child function,
4970 we need to replace it with the argument as seen by the child
4971 function.
4973 In most cases, this will end up being the identity assignment
4974 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4975 a function call that has been inlined, the original PARM_DECL
4976 .OMP_DATA_I may have been converted into a different local
4977 variable. In which case, we need to keep the assignment. */
4978 if (gimple_omp_taskreg_data_arg (entry_stmt))
4980 basic_block entry_succ_bb = single_succ (entry_bb);
4981 tree arg, narg;
4982 gimple parcopy_stmt = NULL;
4984 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4986 gimple stmt;
4988 gcc_assert (!gsi_end_p (gsi));
4989 stmt = gsi_stmt (gsi);
4990 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4991 continue;
4993 if (gimple_num_ops (stmt) == 2)
4995 tree arg = gimple_assign_rhs1 (stmt);
4997 /* We're ignore the subcode because we're
4998 effectively doing a STRIP_NOPS. */
5000 if (TREE_CODE (arg) == ADDR_EXPR
5001 && TREE_OPERAND (arg, 0)
5002 == gimple_omp_taskreg_data_arg (entry_stmt))
5004 parcopy_stmt = stmt;
5005 break;
5010 gcc_assert (parcopy_stmt != NULL);
5011 arg = DECL_ARGUMENTS (child_fn);
5013 if (!gimple_in_ssa_p (cfun))
5015 if (gimple_assign_lhs (parcopy_stmt) == arg)
5016 gsi_remove (&gsi, true);
5017 else
5019 /* ?? Is setting the subcode really necessary ?? */
5020 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5021 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5024 else
5026 /* If we are in ssa form, we must load the value from the default
5027 definition of the argument. That should not be defined now,
5028 since the argument is not used uninitialized. */
5029 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5030 narg = make_ssa_name (arg, gimple_build_nop ());
5031 set_ssa_default_def (cfun, arg, narg);
5032 /* ?? Is setting the subcode really necessary ?? */
5033 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5034 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5035 update_stmt (parcopy_stmt);
5039 /* Declare local variables needed in CHILD_CFUN. */
5040 block = DECL_INITIAL (child_fn);
5041 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5042 /* The gimplifier could record temporaries in parallel/task block
5043 rather than in containing function's local_decls chain,
5044 which would mean cgraph missed finalizing them. Do it now. */
5045 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5046 if (TREE_CODE (t) == VAR_DECL
5047 && TREE_STATIC (t)
5048 && !DECL_EXTERNAL (t))
5049 varpool_node::finalize_decl (t);
5050 DECL_SAVED_TREE (child_fn) = NULL;
5051 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5052 gimple_set_body (child_fn, NULL);
5053 TREE_USED (block) = 1;
5055 /* Reset DECL_CONTEXT on function arguments. */
5056 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5057 DECL_CONTEXT (t) = child_fn;
5059 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5060 so that it can be moved to the child function. */
5061 gsi = gsi_last_bb (entry_bb);
5062 stmt = gsi_stmt (gsi);
5063 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5064 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5065 gsi_remove (&gsi, true);
5066 e = split_block (entry_bb, stmt);
5067 entry_bb = e->dest;
5068 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5070 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5071 if (exit_bb)
5073 gsi = gsi_last_bb (exit_bb);
5074 gcc_assert (!gsi_end_p (gsi)
5075 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5076 stmt = gimple_build_return (NULL);
5077 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5078 gsi_remove (&gsi, true);
5081 /* Move the parallel region into CHILD_CFUN. */
5083 if (gimple_in_ssa_p (cfun))
5085 init_tree_ssa (child_cfun);
5086 init_ssa_operands (child_cfun);
5087 child_cfun->gimple_df->in_ssa_p = true;
5088 block = NULL_TREE;
5090 else
5091 block = gimple_block (entry_stmt);
5093 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5094 if (exit_bb)
5095 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5096 /* When the OMP expansion process cannot guarantee an up-to-date
5097 loop tree arrange for the child function to fixup loops. */
5098 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5099 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5101 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5102 num = vec_safe_length (child_cfun->local_decls);
5103 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5105 t = (*child_cfun->local_decls)[srcidx];
5106 if (DECL_CONTEXT (t) == cfun->decl)
5107 continue;
5108 if (srcidx != dstidx)
5109 (*child_cfun->local_decls)[dstidx] = t;
5110 dstidx++;
5112 if (dstidx != num)
5113 vec_safe_truncate (child_cfun->local_decls, dstidx);
5115 /* Inform the callgraph about the new function. */
5116 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5117 cgraph_node::add_new_function (child_fn, true);
5119 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5120 fixed in a following pass. */
5121 push_cfun (child_cfun);
5122 if (optimize)
5123 optimize_omp_library_calls (entry_stmt);
5124 cgraph_edge::rebuild_edges ();
5126 /* Some EH regions might become dead, see PR34608. If
5127 pass_cleanup_cfg isn't the first pass to happen with the
5128 new child, these dead EH edges might cause problems.
5129 Clean them up now. */
5130 if (flag_exceptions)
5132 basic_block bb;
5133 bool changed = false;
5135 FOR_EACH_BB_FN (bb, cfun)
5136 changed |= gimple_purge_dead_eh_edges (bb);
5137 if (changed)
5138 cleanup_tree_cfg ();
5140 if (gimple_in_ssa_p (cfun))
5141 update_ssa (TODO_update_ssa);
5142 pop_cfun ();
5145 /* Emit a library call to launch the children threads. */
5146 if (is_cilk_for)
5147 expand_cilk_for_call (new_bb,
5148 as_a <gomp_parallel *> (entry_stmt), ws_args);
5149 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5150 expand_parallel_call (region, new_bb,
5151 as_a <gomp_parallel *> (entry_stmt), ws_args);
5152 else
5153 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5154 if (gimple_in_ssa_p (cfun))
5155 update_ssa (TODO_update_ssa_only_virtuals);
5159 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5160 of the combined collapse > 1 loop constructs, generate code like:
5161 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5162 if (cond3 is <)
5163 adj = STEP3 - 1;
5164 else
5165 adj = STEP3 + 1;
5166 count3 = (adj + N32 - N31) / STEP3;
5167 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5168 if (cond2 is <)
5169 adj = STEP2 - 1;
5170 else
5171 adj = STEP2 + 1;
5172 count2 = (adj + N22 - N21) / STEP2;
5173 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5174 if (cond1 is <)
5175 adj = STEP1 - 1;
5176 else
5177 adj = STEP1 + 1;
5178 count1 = (adj + N12 - N11) / STEP1;
5179 count = count1 * count2 * count3;
5180 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5181 count = 0;
5182 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5183 of the combined loop constructs, just initialize COUNTS array
5184 from the _looptemp_ clauses. */
5186 /* NOTE: It *could* be better to moosh all of the BBs together,
5187 creating one larger BB with all the computation and the unexpected
5188 jump at the end. I.e.
5190 bool zero3, zero2, zero1, zero;
5192 zero3 = N32 c3 N31;
5193 count3 = (N32 - N31) /[cl] STEP3;
5194 zero2 = N22 c2 N21;
5195 count2 = (N22 - N21) /[cl] STEP2;
5196 zero1 = N12 c1 N11;
5197 count1 = (N12 - N11) /[cl] STEP1;
5198 zero = zero3 || zero2 || zero1;
5199 count = count1 * count2 * count3;
5200 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5202 After all, we expect the zero=false, and thus we expect to have to
5203 evaluate all of the comparison expressions, so short-circuiting
5204 oughtn't be a win. Since the condition isn't protecting a
5205 denominator, we're not concerned about divide-by-zero, so we can
5206 fully evaluate count even if a numerator turned out to be wrong.
5208 It seems like putting this all together would create much better
5209 scheduling opportunities, and less pressure on the chip's branch
5210 predictor. */
5212 static void
5213 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5214 basic_block &entry_bb, tree *counts,
5215 basic_block &zero_iter_bb, int &first_zero_iter,
5216 basic_block &l2_dom_bb)
5218 tree t, type = TREE_TYPE (fd->loop.v);
5219 edge e, ne;
5220 int i;
5222 /* Collapsed loops need work for expansion into SSA form. */
5223 gcc_assert (!gimple_in_ssa_p (cfun));
5225 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5226 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5228 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5229 isn't supposed to be handled, as the inner loop doesn't
5230 use it. */
5231 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5232 OMP_CLAUSE__LOOPTEMP_);
5233 gcc_assert (innerc);
5234 for (i = 0; i < fd->collapse; i++)
5236 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5237 OMP_CLAUSE__LOOPTEMP_);
5238 gcc_assert (innerc);
5239 if (i)
5240 counts[i] = OMP_CLAUSE_DECL (innerc);
5241 else
5242 counts[0] = NULL_TREE;
5244 return;
5247 for (i = 0; i < fd->collapse; i++)
5249 tree itype = TREE_TYPE (fd->loops[i].v);
5251 if (SSA_VAR_P (fd->loop.n2)
5252 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5253 fold_convert (itype, fd->loops[i].n1),
5254 fold_convert (itype, fd->loops[i].n2)))
5255 == NULL_TREE || !integer_onep (t)))
5257 gcond *cond_stmt;
5258 tree n1, n2;
5259 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5260 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5261 true, GSI_SAME_STMT);
5262 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5263 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5264 true, GSI_SAME_STMT);
5265 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5266 NULL_TREE, NULL_TREE);
5267 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5268 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5269 expand_omp_regimplify_p, NULL, NULL)
5270 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5271 expand_omp_regimplify_p, NULL, NULL))
5273 *gsi = gsi_for_stmt (cond_stmt);
5274 gimple_regimplify_operands (cond_stmt, gsi);
5276 e = split_block (entry_bb, cond_stmt);
5277 if (zero_iter_bb == NULL)
5279 gassign *assign_stmt;
5280 first_zero_iter = i;
5281 zero_iter_bb = create_empty_bb (entry_bb);
5282 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5283 *gsi = gsi_after_labels (zero_iter_bb);
5284 assign_stmt = gimple_build_assign (fd->loop.n2,
5285 build_zero_cst (type));
5286 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5287 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5288 entry_bb);
5290 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5291 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5292 e->flags = EDGE_TRUE_VALUE;
5293 e->probability = REG_BR_PROB_BASE - ne->probability;
5294 if (l2_dom_bb == NULL)
5295 l2_dom_bb = entry_bb;
5296 entry_bb = e->dest;
5297 *gsi = gsi_last_bb (entry_bb);
5300 if (POINTER_TYPE_P (itype))
5301 itype = signed_type_for (itype);
5302 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5303 ? -1 : 1));
5304 t = fold_build2 (PLUS_EXPR, itype,
5305 fold_convert (itype, fd->loops[i].step), t);
5306 t = fold_build2 (PLUS_EXPR, itype, t,
5307 fold_convert (itype, fd->loops[i].n2));
5308 t = fold_build2 (MINUS_EXPR, itype, t,
5309 fold_convert (itype, fd->loops[i].n1));
5310 /* ?? We could probably use CEIL_DIV_EXPR instead of
5311 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5312 generate the same code in the end because generically we
5313 don't know that the values involved must be negative for
5314 GT?? */
5315 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5316 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5317 fold_build1 (NEGATE_EXPR, itype, t),
5318 fold_build1 (NEGATE_EXPR, itype,
5319 fold_convert (itype,
5320 fd->loops[i].step)));
5321 else
5322 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5323 fold_convert (itype, fd->loops[i].step));
5324 t = fold_convert (type, t);
5325 if (TREE_CODE (t) == INTEGER_CST)
5326 counts[i] = t;
5327 else
5329 counts[i] = create_tmp_reg (type, ".count");
5330 expand_omp_build_assign (gsi, counts[i], t);
5332 if (SSA_VAR_P (fd->loop.n2))
5334 if (i == 0)
5335 t = counts[0];
5336 else
5337 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5338 expand_omp_build_assign (gsi, fd->loop.n2, t);
5344 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5345 T = V;
5346 V3 = N31 + (T % count3) * STEP3;
5347 T = T / count3;
5348 V2 = N21 + (T % count2) * STEP2;
5349 T = T / count2;
5350 V1 = N11 + T * STEP1;
5351 if this loop doesn't have an inner loop construct combined with it.
5352 If it does have an inner loop construct combined with it and the
5353 iteration count isn't known constant, store values from counts array
5354 into its _looptemp_ temporaries instead. */
5356 static void
5357 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5358 tree *counts, gimple inner_stmt, tree startvar)
5360 int i;
5361 if (gimple_omp_for_combined_p (fd->for_stmt))
5363 /* If fd->loop.n2 is constant, then no propagation of the counts
5364 is needed, they are constant. */
5365 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5366 return;
5368 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5369 ? gimple_omp_parallel_clauses (inner_stmt)
5370 : gimple_omp_for_clauses (inner_stmt);
5371 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5372 isn't supposed to be handled, as the inner loop doesn't
5373 use it. */
5374 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5375 gcc_assert (innerc);
5376 for (i = 0; i < fd->collapse; i++)
5378 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5379 OMP_CLAUSE__LOOPTEMP_);
5380 gcc_assert (innerc);
5381 if (i)
5383 tree tem = OMP_CLAUSE_DECL (innerc);
5384 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5385 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5386 false, GSI_CONTINUE_LINKING);
5387 gassign *stmt = gimple_build_assign (tem, t);
5388 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5391 return;
5394 tree type = TREE_TYPE (fd->loop.v);
5395 tree tem = create_tmp_reg (type, ".tem");
5396 gassign *stmt = gimple_build_assign (tem, startvar);
5397 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5399 for (i = fd->collapse - 1; i >= 0; i--)
5401 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5402 itype = vtype;
5403 if (POINTER_TYPE_P (vtype))
5404 itype = signed_type_for (vtype);
5405 if (i != 0)
5406 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5407 else
5408 t = tem;
5409 t = fold_convert (itype, t);
5410 t = fold_build2 (MULT_EXPR, itype, t,
5411 fold_convert (itype, fd->loops[i].step));
5412 if (POINTER_TYPE_P (vtype))
5413 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5414 else
5415 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5416 t = force_gimple_operand_gsi (gsi, t,
5417 DECL_P (fd->loops[i].v)
5418 && TREE_ADDRESSABLE (fd->loops[i].v),
5419 NULL_TREE, false,
5420 GSI_CONTINUE_LINKING);
5421 stmt = gimple_build_assign (fd->loops[i].v, t);
5422 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5423 if (i != 0)
5425 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5426 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5427 false, GSI_CONTINUE_LINKING);
5428 stmt = gimple_build_assign (tem, t);
5429 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5435 /* Helper function for expand_omp_for_*. Generate code like:
5436 L10:
5437 V3 += STEP3;
5438 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5439 L11:
5440 V3 = N31;
5441 V2 += STEP2;
5442 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5443 L12:
5444 V2 = N21;
5445 V1 += STEP1;
5446 goto BODY_BB; */
5448 static basic_block
5449 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5450 basic_block body_bb)
5452 basic_block last_bb, bb, collapse_bb = NULL;
5453 int i;
5454 gimple_stmt_iterator gsi;
5455 edge e;
5456 tree t;
5457 gimple stmt;
5459 last_bb = cont_bb;
5460 for (i = fd->collapse - 1; i >= 0; i--)
5462 tree vtype = TREE_TYPE (fd->loops[i].v);
5464 bb = create_empty_bb (last_bb);
5465 add_bb_to_loop (bb, last_bb->loop_father);
5466 gsi = gsi_start_bb (bb);
5468 if (i < fd->collapse - 1)
5470 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5471 e->probability = REG_BR_PROB_BASE / 8;
5473 t = fd->loops[i + 1].n1;
5474 t = force_gimple_operand_gsi (&gsi, t,
5475 DECL_P (fd->loops[i + 1].v)
5476 && TREE_ADDRESSABLE (fd->loops[i
5477 + 1].v),
5478 NULL_TREE, false,
5479 GSI_CONTINUE_LINKING);
5480 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5481 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5483 else
5484 collapse_bb = bb;
5486 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5488 if (POINTER_TYPE_P (vtype))
5489 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5490 else
5491 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5492 t = force_gimple_operand_gsi (&gsi, t,
5493 DECL_P (fd->loops[i].v)
5494 && TREE_ADDRESSABLE (fd->loops[i].v),
5495 NULL_TREE, false, GSI_CONTINUE_LINKING);
5496 stmt = gimple_build_assign (fd->loops[i].v, t);
5497 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5499 if (i > 0)
5501 t = fd->loops[i].n2;
5502 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5503 false, GSI_CONTINUE_LINKING);
5504 tree v = fd->loops[i].v;
5505 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5506 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5507 false, GSI_CONTINUE_LINKING);
5508 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5509 stmt = gimple_build_cond_empty (t);
5510 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5511 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5512 e->probability = REG_BR_PROB_BASE * 7 / 8;
5514 else
5515 make_edge (bb, body_bb, EDGE_FALLTHRU);
5516 last_bb = bb;
5519 return collapse_bb;
5523 /* A subroutine of expand_omp_for. Generate code for a parallel
5524 loop with any schedule. Given parameters:
5526 for (V = N1; V cond N2; V += STEP) BODY;
5528 where COND is "<" or ">", we generate pseudocode
5530 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5531 if (more) goto L0; else goto L3;
5533 V = istart0;
5534 iend = iend0;
5536 BODY;
5537 V += STEP;
5538 if (V cond iend) goto L1; else goto L2;
5540 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5543 If this is a combined omp parallel loop, instead of the call to
5544 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5545 If this is gimple_omp_for_combined_p loop, then instead of assigning
5546 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5547 inner GIMPLE_OMP_FOR and V += STEP; and
5548 if (V cond iend) goto L1; else goto L2; are removed.
5550 For collapsed loops, given parameters:
5551 collapse(3)
5552 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5553 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5554 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5555 BODY;
5557 we generate pseudocode
5559 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5560 if (cond3 is <)
5561 adj = STEP3 - 1;
5562 else
5563 adj = STEP3 + 1;
5564 count3 = (adj + N32 - N31) / STEP3;
5565 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5566 if (cond2 is <)
5567 adj = STEP2 - 1;
5568 else
5569 adj = STEP2 + 1;
5570 count2 = (adj + N22 - N21) / STEP2;
5571 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5572 if (cond1 is <)
5573 adj = STEP1 - 1;
5574 else
5575 adj = STEP1 + 1;
5576 count1 = (adj + N12 - N11) / STEP1;
5577 count = count1 * count2 * count3;
5578 goto Z1;
5580 count = 0;
5582 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5583 if (more) goto L0; else goto L3;
5585 V = istart0;
5586 T = V;
5587 V3 = N31 + (T % count3) * STEP3;
5588 T = T / count3;
5589 V2 = N21 + (T % count2) * STEP2;
5590 T = T / count2;
5591 V1 = N11 + T * STEP1;
5592 iend = iend0;
5594 BODY;
5595 V += 1;
5596 if (V < iend) goto L10; else goto L2;
5597 L10:
5598 V3 += STEP3;
5599 if (V3 cond3 N32) goto L1; else goto L11;
5600 L11:
5601 V3 = N31;
5602 V2 += STEP2;
5603 if (V2 cond2 N22) goto L1; else goto L12;
5604 L12:
5605 V2 = N21;
5606 V1 += STEP1;
5607 goto L1;
5609 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5614 static void
5615 expand_omp_for_generic (struct omp_region *region,
5616 struct omp_for_data *fd,
5617 enum built_in_function start_fn,
5618 enum built_in_function next_fn,
5619 gimple inner_stmt)
5621 tree type, istart0, iend0, iend;
5622 tree t, vmain, vback, bias = NULL_TREE;
5623 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5624 basic_block l2_bb = NULL, l3_bb = NULL;
5625 gimple_stmt_iterator gsi;
5626 gassign *assign_stmt;
5627 bool in_combined_parallel = is_combined_parallel (region);
5628 bool broken_loop = region->cont == NULL;
5629 edge e, ne;
5630 tree *counts = NULL;
5631 int i;
5633 gcc_assert (!broken_loop || !in_combined_parallel);
5634 gcc_assert (fd->iter_type == long_integer_type_node
5635 || !in_combined_parallel);
5637 type = TREE_TYPE (fd->loop.v);
5638 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5639 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5640 TREE_ADDRESSABLE (istart0) = 1;
5641 TREE_ADDRESSABLE (iend0) = 1;
5643 /* See if we need to bias by LLONG_MIN. */
5644 if (fd->iter_type == long_long_unsigned_type_node
5645 && TREE_CODE (type) == INTEGER_TYPE
5646 && !TYPE_UNSIGNED (type))
5648 tree n1, n2;
5650 if (fd->loop.cond_code == LT_EXPR)
5652 n1 = fd->loop.n1;
5653 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5655 else
5657 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5658 n2 = fd->loop.n1;
5660 if (TREE_CODE (n1) != INTEGER_CST
5661 || TREE_CODE (n2) != INTEGER_CST
5662 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5663 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5666 entry_bb = region->entry;
5667 cont_bb = region->cont;
5668 collapse_bb = NULL;
5669 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5670 gcc_assert (broken_loop
5671 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5672 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5673 l1_bb = single_succ (l0_bb);
5674 if (!broken_loop)
5676 l2_bb = create_empty_bb (cont_bb);
5677 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5678 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5680 else
5681 l2_bb = NULL;
5682 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5683 exit_bb = region->exit;
5685 gsi = gsi_last_bb (entry_bb);
5687 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5688 if (fd->collapse > 1)
5690 int first_zero_iter = -1;
5691 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5693 counts = XALLOCAVEC (tree, fd->collapse);
5694 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5695 zero_iter_bb, first_zero_iter,
5696 l2_dom_bb);
5698 if (zero_iter_bb)
5700 /* Some counts[i] vars might be uninitialized if
5701 some loop has zero iterations. But the body shouldn't
5702 be executed in that case, so just avoid uninit warnings. */
5703 for (i = first_zero_iter; i < fd->collapse; i++)
5704 if (SSA_VAR_P (counts[i]))
5705 TREE_NO_WARNING (counts[i]) = 1;
5706 gsi_prev (&gsi);
5707 e = split_block (entry_bb, gsi_stmt (gsi));
5708 entry_bb = e->dest;
5709 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5710 gsi = gsi_last_bb (entry_bb);
5711 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5712 get_immediate_dominator (CDI_DOMINATORS,
5713 zero_iter_bb));
5716 if (in_combined_parallel)
5718 /* In a combined parallel loop, emit a call to
5719 GOMP_loop_foo_next. */
5720 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5721 build_fold_addr_expr (istart0),
5722 build_fold_addr_expr (iend0));
5724 else
5726 tree t0, t1, t2, t3, t4;
5727 /* If this is not a combined parallel loop, emit a call to
5728 GOMP_loop_foo_start in ENTRY_BB. */
5729 t4 = build_fold_addr_expr (iend0);
5730 t3 = build_fold_addr_expr (istart0);
5731 t2 = fold_convert (fd->iter_type, fd->loop.step);
5732 t1 = fd->loop.n2;
5733 t0 = fd->loop.n1;
5734 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5736 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5737 OMP_CLAUSE__LOOPTEMP_);
5738 gcc_assert (innerc);
5739 t0 = OMP_CLAUSE_DECL (innerc);
5740 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5741 OMP_CLAUSE__LOOPTEMP_);
5742 gcc_assert (innerc);
5743 t1 = OMP_CLAUSE_DECL (innerc);
5745 if (POINTER_TYPE_P (TREE_TYPE (t0))
5746 && TYPE_PRECISION (TREE_TYPE (t0))
5747 != TYPE_PRECISION (fd->iter_type))
5749 /* Avoid casting pointers to integer of a different size. */
5750 tree itype = signed_type_for (type);
5751 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5752 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5754 else
5756 t1 = fold_convert (fd->iter_type, t1);
5757 t0 = fold_convert (fd->iter_type, t0);
5759 if (bias)
5761 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5762 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5764 if (fd->iter_type == long_integer_type_node)
5766 if (fd->chunk_size)
5768 t = fold_convert (fd->iter_type, fd->chunk_size);
5769 t = build_call_expr (builtin_decl_explicit (start_fn),
5770 6, t0, t1, t2, t, t3, t4);
5772 else
5773 t = build_call_expr (builtin_decl_explicit (start_fn),
5774 5, t0, t1, t2, t3, t4);
5776 else
5778 tree t5;
5779 tree c_bool_type;
5780 tree bfn_decl;
5782 /* The GOMP_loop_ull_*start functions have additional boolean
5783 argument, true for < loops and false for > loops.
5784 In Fortran, the C bool type can be different from
5785 boolean_type_node. */
5786 bfn_decl = builtin_decl_explicit (start_fn);
5787 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5788 t5 = build_int_cst (c_bool_type,
5789 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5790 if (fd->chunk_size)
5792 tree bfn_decl = builtin_decl_explicit (start_fn);
5793 t = fold_convert (fd->iter_type, fd->chunk_size);
5794 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5796 else
5797 t = build_call_expr (builtin_decl_explicit (start_fn),
5798 6, t5, t0, t1, t2, t3, t4);
5801 if (TREE_TYPE (t) != boolean_type_node)
5802 t = fold_build2 (NE_EXPR, boolean_type_node,
5803 t, build_int_cst (TREE_TYPE (t), 0));
5804 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5805 true, GSI_SAME_STMT);
5806 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5808 /* Remove the GIMPLE_OMP_FOR statement. */
5809 gsi_remove (&gsi, true);
5811 /* Iteration setup for sequential loop goes in L0_BB. */
5812 tree startvar = fd->loop.v;
5813 tree endvar = NULL_TREE;
5815 if (gimple_omp_for_combined_p (fd->for_stmt))
5817 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5818 && gimple_omp_for_kind (inner_stmt)
5819 == GF_OMP_FOR_KIND_SIMD);
5820 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5821 OMP_CLAUSE__LOOPTEMP_);
5822 gcc_assert (innerc);
5823 startvar = OMP_CLAUSE_DECL (innerc);
5824 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5825 OMP_CLAUSE__LOOPTEMP_);
5826 gcc_assert (innerc);
5827 endvar = OMP_CLAUSE_DECL (innerc);
5830 gsi = gsi_start_bb (l0_bb);
5831 t = istart0;
5832 if (bias)
5833 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5834 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5835 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5836 t = fold_convert (TREE_TYPE (startvar), t);
5837 t = force_gimple_operand_gsi (&gsi, t,
5838 DECL_P (startvar)
5839 && TREE_ADDRESSABLE (startvar),
5840 NULL_TREE, false, GSI_CONTINUE_LINKING);
5841 assign_stmt = gimple_build_assign (startvar, t);
5842 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5844 t = iend0;
5845 if (bias)
5846 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5847 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5848 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5849 t = fold_convert (TREE_TYPE (startvar), t);
5850 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5851 false, GSI_CONTINUE_LINKING);
5852 if (endvar)
5854 assign_stmt = gimple_build_assign (endvar, iend);
5855 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5856 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
5857 assign_stmt = gimple_build_assign (fd->loop.v, iend);
5858 else
5859 assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend);
5860 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5862 if (fd->collapse > 1)
5863 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5865 if (!broken_loop)
5867 /* Code to control the increment and predicate for the sequential
5868 loop goes in the CONT_BB. */
5869 gsi = gsi_last_bb (cont_bb);
5870 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
5871 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
5872 vmain = gimple_omp_continue_control_use (cont_stmt);
5873 vback = gimple_omp_continue_control_def (cont_stmt);
5875 if (!gimple_omp_for_combined_p (fd->for_stmt))
5877 if (POINTER_TYPE_P (type))
5878 t = fold_build_pointer_plus (vmain, fd->loop.step);
5879 else
5880 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5881 t = force_gimple_operand_gsi (&gsi, t,
5882 DECL_P (vback)
5883 && TREE_ADDRESSABLE (vback),
5884 NULL_TREE, true, GSI_SAME_STMT);
5885 assign_stmt = gimple_build_assign (vback, t);
5886 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
5888 t = build2 (fd->loop.cond_code, boolean_type_node,
5889 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5890 iend);
5891 gcond *cond_stmt = gimple_build_cond_empty (t);
5892 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
5895 /* Remove GIMPLE_OMP_CONTINUE. */
5896 gsi_remove (&gsi, true);
5898 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5899 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5901 /* Emit code to get the next parallel iteration in L2_BB. */
5902 gsi = gsi_start_bb (l2_bb);
5904 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5905 build_fold_addr_expr (istart0),
5906 build_fold_addr_expr (iend0));
5907 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5908 false, GSI_CONTINUE_LINKING);
5909 if (TREE_TYPE (t) != boolean_type_node)
5910 t = fold_build2 (NE_EXPR, boolean_type_node,
5911 t, build_int_cst (TREE_TYPE (t), 0));
5912 gcond *cond_stmt = gimple_build_cond_empty (t);
5913 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
5916 /* Add the loop cleanup function. */
5917 gsi = gsi_last_bb (exit_bb);
5918 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5919 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5920 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5921 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5922 else
5923 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5924 gcall *call_stmt = gimple_build_call (t, 0);
5925 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5926 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5927 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
5928 gsi_remove (&gsi, true);
5930 /* Connect the new blocks. */
5931 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5932 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5934 if (!broken_loop)
5936 gimple_seq phis;
5938 e = find_edge (cont_bb, l3_bb);
5939 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5941 phis = phi_nodes (l3_bb);
5942 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5944 gimple phi = gsi_stmt (gsi);
5945 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5946 PHI_ARG_DEF_FROM_EDGE (phi, e));
5948 remove_edge (e);
5950 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5951 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5952 e = find_edge (cont_bb, l1_bb);
5953 if (gimple_omp_for_combined_p (fd->for_stmt))
5955 remove_edge (e);
5956 e = NULL;
5958 else if (fd->collapse > 1)
5960 remove_edge (e);
5961 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5963 else
5964 e->flags = EDGE_TRUE_VALUE;
5965 if (e)
5967 e->probability = REG_BR_PROB_BASE * 7 / 8;
5968 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5970 else
5972 e = find_edge (cont_bb, l2_bb);
5973 e->flags = EDGE_FALLTHRU;
5975 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5977 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5978 recompute_dominator (CDI_DOMINATORS, l2_bb));
5979 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5980 recompute_dominator (CDI_DOMINATORS, l3_bb));
5981 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5982 recompute_dominator (CDI_DOMINATORS, l0_bb));
5983 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5984 recompute_dominator (CDI_DOMINATORS, l1_bb));
5986 struct loop *outer_loop = alloc_loop ();
5987 outer_loop->header = l0_bb;
5988 outer_loop->latch = l2_bb;
5989 add_loop (outer_loop, l0_bb->loop_father);
5991 if (!gimple_omp_for_combined_p (fd->for_stmt))
5993 struct loop *loop = alloc_loop ();
5994 loop->header = l1_bb;
5995 /* The loop may have multiple latches. */
5996 add_loop (loop, outer_loop);
6002 /* A subroutine of expand_omp_for. Generate code for a parallel
6003 loop with static schedule and no specified chunk size. Given
6004 parameters:
6006 for (V = N1; V cond N2; V += STEP) BODY;
6008 where COND is "<" or ">", we generate pseudocode
6010 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6011 if (cond is <)
6012 adj = STEP - 1;
6013 else
6014 adj = STEP + 1;
6015 if ((__typeof (V)) -1 > 0 && cond is >)
6016 n = -(adj + N2 - N1) / -STEP;
6017 else
6018 n = (adj + N2 - N1) / STEP;
6019 q = n / nthreads;
6020 tt = n % nthreads;
6021 if (threadid < tt) goto L3; else goto L4;
6023 tt = 0;
6024 q = q + 1;
6026 s0 = q * threadid + tt;
6027 e0 = s0 + q;
6028 V = s0 * STEP + N1;
6029 if (s0 >= e0) goto L2; else goto L0;
6031 e = e0 * STEP + N1;
6033 BODY;
6034 V += STEP;
6035 if (V cond e) goto L1;
6039 static void
6040 expand_omp_for_static_nochunk (struct omp_region *region,
6041 struct omp_for_data *fd,
6042 gimple inner_stmt)
6044 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6045 tree type, itype, vmain, vback;
6046 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6047 basic_block body_bb, cont_bb, collapse_bb = NULL;
6048 basic_block fin_bb;
6049 gimple_stmt_iterator gsi;
6050 edge ep;
6051 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6052 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6053 bool broken_loop = region->cont == NULL;
6054 tree *counts = NULL;
6055 tree n1, n2, step;
6057 itype = type = TREE_TYPE (fd->loop.v);
6058 if (POINTER_TYPE_P (type))
6059 itype = signed_type_for (type);
6061 entry_bb = region->entry;
6062 cont_bb = region->cont;
6063 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6064 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6065 gcc_assert (broken_loop
6066 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6067 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6068 body_bb = single_succ (seq_start_bb);
6069 if (!broken_loop)
6071 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6072 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6074 exit_bb = region->exit;
6076 /* Iteration space partitioning goes in ENTRY_BB. */
6077 gsi = gsi_last_bb (entry_bb);
6078 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6080 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6082 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6083 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6086 if (fd->collapse > 1)
6088 int first_zero_iter = -1;
6089 basic_block l2_dom_bb = NULL;
6091 counts = XALLOCAVEC (tree, fd->collapse);
6092 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6093 fin_bb, first_zero_iter,
6094 l2_dom_bb);
6095 t = NULL_TREE;
6097 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6098 t = integer_one_node;
6099 else
6100 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6101 fold_convert (type, fd->loop.n1),
6102 fold_convert (type, fd->loop.n2));
6103 if (fd->collapse == 1
6104 && TYPE_UNSIGNED (type)
6105 && (t == NULL_TREE || !integer_onep (t)))
6107 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6108 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6109 true, GSI_SAME_STMT);
6110 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6111 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6112 true, GSI_SAME_STMT);
6113 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6114 NULL_TREE, NULL_TREE);
6115 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6116 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6117 expand_omp_regimplify_p, NULL, NULL)
6118 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6119 expand_omp_regimplify_p, NULL, NULL))
6121 gsi = gsi_for_stmt (cond_stmt);
6122 gimple_regimplify_operands (cond_stmt, &gsi);
6124 ep = split_block (entry_bb, cond_stmt);
6125 ep->flags = EDGE_TRUE_VALUE;
6126 entry_bb = ep->dest;
6127 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6128 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6129 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6130 if (gimple_in_ssa_p (cfun))
6132 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6133 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6134 !gsi_end_p (gpi); gsi_next (&gpi))
6136 gphi *phi = gpi.phi ();
6137 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6138 ep, UNKNOWN_LOCATION);
6141 gsi = gsi_last_bb (entry_bb);
6144 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6145 t = fold_convert (itype, t);
6146 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6147 true, GSI_SAME_STMT);
6149 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6150 t = fold_convert (itype, t);
6151 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6152 true, GSI_SAME_STMT);
6154 n1 = fd->loop.n1;
6155 n2 = fd->loop.n2;
6156 step = fd->loop.step;
6157 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6159 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6160 OMP_CLAUSE__LOOPTEMP_);
6161 gcc_assert (innerc);
6162 n1 = OMP_CLAUSE_DECL (innerc);
6163 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6164 OMP_CLAUSE__LOOPTEMP_);
6165 gcc_assert (innerc);
6166 n2 = OMP_CLAUSE_DECL (innerc);
6168 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6169 true, NULL_TREE, true, GSI_SAME_STMT);
6170 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6171 true, NULL_TREE, true, GSI_SAME_STMT);
6172 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6173 true, NULL_TREE, true, GSI_SAME_STMT);
6175 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6176 t = fold_build2 (PLUS_EXPR, itype, step, t);
6177 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6178 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6179 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6180 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6181 fold_build1 (NEGATE_EXPR, itype, t),
6182 fold_build1 (NEGATE_EXPR, itype, step));
6183 else
6184 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6185 t = fold_convert (itype, t);
6186 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6188 q = create_tmp_reg (itype, "q");
6189 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6190 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6191 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6193 tt = create_tmp_reg (itype, "tt");
6194 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6195 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6196 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6198 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6199 gcond *cond_stmt = gimple_build_cond_empty (t);
6200 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6202 second_bb = split_block (entry_bb, cond_stmt)->dest;
6203 gsi = gsi_last_bb (second_bb);
6204 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6206 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6207 GSI_SAME_STMT);
6208 gassign *assign_stmt
6209 = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
6210 build_int_cst (itype, 1));
6211 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6213 third_bb = split_block (second_bb, assign_stmt)->dest;
6214 gsi = gsi_last_bb (third_bb);
6215 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6217 t = build2 (MULT_EXPR, itype, q, threadid);
6218 t = build2 (PLUS_EXPR, itype, t, tt);
6219 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6221 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6222 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6224 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6225 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6227 /* Remove the GIMPLE_OMP_FOR statement. */
6228 gsi_remove (&gsi, true);
6230 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6231 gsi = gsi_start_bb (seq_start_bb);
6233 tree startvar = fd->loop.v;
6234 tree endvar = NULL_TREE;
6236 if (gimple_omp_for_combined_p (fd->for_stmt))
6238 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6239 ? gimple_omp_parallel_clauses (inner_stmt)
6240 : gimple_omp_for_clauses (inner_stmt);
6241 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6242 gcc_assert (innerc);
6243 startvar = OMP_CLAUSE_DECL (innerc);
6244 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6245 OMP_CLAUSE__LOOPTEMP_);
6246 gcc_assert (innerc);
6247 endvar = OMP_CLAUSE_DECL (innerc);
6249 t = fold_convert (itype, s0);
6250 t = fold_build2 (MULT_EXPR, itype, t, step);
6251 if (POINTER_TYPE_P (type))
6252 t = fold_build_pointer_plus (n1, t);
6253 else
6254 t = fold_build2 (PLUS_EXPR, type, t, n1);
6255 t = fold_convert (TREE_TYPE (startvar), t);
6256 t = force_gimple_operand_gsi (&gsi, t,
6257 DECL_P (startvar)
6258 && TREE_ADDRESSABLE (startvar),
6259 NULL_TREE, false, GSI_CONTINUE_LINKING);
6260 assign_stmt = gimple_build_assign (startvar, t);
6261 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6263 t = fold_convert (itype, e0);
6264 t = fold_build2 (MULT_EXPR, itype, t, step);
6265 if (POINTER_TYPE_P (type))
6266 t = fold_build_pointer_plus (n1, t);
6267 else
6268 t = fold_build2 (PLUS_EXPR, type, t, n1);
6269 t = fold_convert (TREE_TYPE (startvar), t);
6270 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6271 false, GSI_CONTINUE_LINKING);
6272 if (endvar)
6274 assign_stmt = gimple_build_assign (endvar, e);
6275 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6276 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6277 assign_stmt = gimple_build_assign (fd->loop.v, e);
6278 else
6279 assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e);
6280 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6282 if (fd->collapse > 1)
6283 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6285 if (!broken_loop)
6287 /* The code controlling the sequential loop replaces the
6288 GIMPLE_OMP_CONTINUE. */
6289 gsi = gsi_last_bb (cont_bb);
6290 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6291 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6292 vmain = gimple_omp_continue_control_use (cont_stmt);
6293 vback = gimple_omp_continue_control_def (cont_stmt);
6295 if (!gimple_omp_for_combined_p (fd->for_stmt))
6297 if (POINTER_TYPE_P (type))
6298 t = fold_build_pointer_plus (vmain, step);
6299 else
6300 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6301 t = force_gimple_operand_gsi (&gsi, t,
6302 DECL_P (vback)
6303 && TREE_ADDRESSABLE (vback),
6304 NULL_TREE, true, GSI_SAME_STMT);
6305 assign_stmt = gimple_build_assign (vback, t);
6306 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6308 t = build2 (fd->loop.cond_code, boolean_type_node,
6309 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6310 ? t : vback, e);
6311 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6314 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6315 gsi_remove (&gsi, true);
6317 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6318 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6321 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6322 gsi = gsi_last_bb (exit_bb);
6323 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6325 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6326 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6328 gsi_remove (&gsi, true);
6330 /* Connect all the blocks. */
6331 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6332 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6333 ep = find_edge (entry_bb, second_bb);
6334 ep->flags = EDGE_TRUE_VALUE;
6335 ep->probability = REG_BR_PROB_BASE / 4;
6336 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6337 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6339 if (!broken_loop)
6341 ep = find_edge (cont_bb, body_bb);
6342 if (gimple_omp_for_combined_p (fd->for_stmt))
6344 remove_edge (ep);
6345 ep = NULL;
6347 else if (fd->collapse > 1)
6349 remove_edge (ep);
6350 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6352 else
6353 ep->flags = EDGE_TRUE_VALUE;
6354 find_edge (cont_bb, fin_bb)->flags
6355 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6358 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6359 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6360 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6362 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6363 recompute_dominator (CDI_DOMINATORS, body_bb));
6364 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6365 recompute_dominator (CDI_DOMINATORS, fin_bb));
6367 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6369 struct loop *loop = alloc_loop ();
6370 loop->header = body_bb;
6371 if (collapse_bb == NULL)
6372 loop->latch = cont_bb;
6373 add_loop (loop, body_bb->loop_father);
6378 /* A subroutine of expand_omp_for. Generate code for a parallel
6379 loop with static schedule and a specified chunk size. Given
6380 parameters:
6382 for (V = N1; V cond N2; V += STEP) BODY;
6384 where COND is "<" or ">", we generate pseudocode
6386 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6387 if (cond is <)
6388 adj = STEP - 1;
6389 else
6390 adj = STEP + 1;
6391 if ((__typeof (V)) -1 > 0 && cond is >)
6392 n = -(adj + N2 - N1) / -STEP;
6393 else
6394 n = (adj + N2 - N1) / STEP;
6395 trip = 0;
6396 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6397 here so that V is defined
6398 if the loop is not entered
6400 s0 = (trip * nthreads + threadid) * CHUNK;
6401 e0 = min(s0 + CHUNK, n);
6402 if (s0 < n) goto L1; else goto L4;
6404 V = s0 * STEP + N1;
6405 e = e0 * STEP + N1;
6407 BODY;
6408 V += STEP;
6409 if (V cond e) goto L2; else goto L3;
6411 trip += 1;
6412 goto L0;
6416 static void
6417 expand_omp_for_static_chunk (struct omp_region *region,
6418 struct omp_for_data *fd, gimple inner_stmt)
6420 tree n, s0, e0, e, t;
6421 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6422 tree type, itype, vmain, vback, vextra;
6423 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6424 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6425 gimple_stmt_iterator gsi;
6426 edge se;
6427 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6428 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6429 bool broken_loop = region->cont == NULL;
6430 tree *counts = NULL;
6431 tree n1, n2, step;
6433 itype = type = TREE_TYPE (fd->loop.v);
6434 if (POINTER_TYPE_P (type))
6435 itype = signed_type_for (type);
6437 entry_bb = region->entry;
6438 se = split_block (entry_bb, last_stmt (entry_bb));
6439 entry_bb = se->src;
6440 iter_part_bb = se->dest;
6441 cont_bb = region->cont;
6442 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6443 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6444 gcc_assert (broken_loop
6445 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6446 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6447 body_bb = single_succ (seq_start_bb);
6448 if (!broken_loop)
6450 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6451 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6452 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6454 exit_bb = region->exit;
6456 /* Trip and adjustment setup goes in ENTRY_BB. */
6457 gsi = gsi_last_bb (entry_bb);
6458 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6460 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6462 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6463 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6466 if (fd->collapse > 1)
6468 int first_zero_iter = -1;
6469 basic_block l2_dom_bb = NULL;
6471 counts = XALLOCAVEC (tree, fd->collapse);
6472 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6473 fin_bb, first_zero_iter,
6474 l2_dom_bb);
6475 t = NULL_TREE;
6477 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6478 t = integer_one_node;
6479 else
6480 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6481 fold_convert (type, fd->loop.n1),
6482 fold_convert (type, fd->loop.n2));
6483 if (fd->collapse == 1
6484 && TYPE_UNSIGNED (type)
6485 && (t == NULL_TREE || !integer_onep (t)))
6487 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6488 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6489 true, GSI_SAME_STMT);
6490 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6491 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6492 true, GSI_SAME_STMT);
6493 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6494 NULL_TREE, NULL_TREE);
6495 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6496 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6497 expand_omp_regimplify_p, NULL, NULL)
6498 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6499 expand_omp_regimplify_p, NULL, NULL))
6501 gsi = gsi_for_stmt (cond_stmt);
6502 gimple_regimplify_operands (cond_stmt, &gsi);
6504 se = split_block (entry_bb, cond_stmt);
6505 se->flags = EDGE_TRUE_VALUE;
6506 entry_bb = se->dest;
6507 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6508 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6509 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6510 if (gimple_in_ssa_p (cfun))
6512 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6513 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6514 !gsi_end_p (gpi); gsi_next (&gpi))
6516 gphi *phi = gpi.phi ();
6517 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6518 se, UNKNOWN_LOCATION);
6521 gsi = gsi_last_bb (entry_bb);
6524 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6525 t = fold_convert (itype, t);
6526 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6527 true, GSI_SAME_STMT);
6529 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6530 t = fold_convert (itype, t);
6531 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6532 true, GSI_SAME_STMT);
6534 n1 = fd->loop.n1;
6535 n2 = fd->loop.n2;
6536 step = fd->loop.step;
6537 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6539 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6540 OMP_CLAUSE__LOOPTEMP_);
6541 gcc_assert (innerc);
6542 n1 = OMP_CLAUSE_DECL (innerc);
6543 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6544 OMP_CLAUSE__LOOPTEMP_);
6545 gcc_assert (innerc);
6546 n2 = OMP_CLAUSE_DECL (innerc);
6548 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6549 true, NULL_TREE, true, GSI_SAME_STMT);
6550 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6551 true, NULL_TREE, true, GSI_SAME_STMT);
6552 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6553 true, NULL_TREE, true, GSI_SAME_STMT);
6554 fd->chunk_size
6555 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
6556 true, NULL_TREE, true, GSI_SAME_STMT);
6558 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6559 t = fold_build2 (PLUS_EXPR, itype, step, t);
6560 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6561 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6562 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6563 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6564 fold_build1 (NEGATE_EXPR, itype, t),
6565 fold_build1 (NEGATE_EXPR, itype, step));
6566 else
6567 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6568 t = fold_convert (itype, t);
6569 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6570 true, GSI_SAME_STMT);
6572 trip_var = create_tmp_reg (itype, ".trip");
6573 if (gimple_in_ssa_p (cfun))
6575 trip_init = make_ssa_name (trip_var, NULL);
6576 trip_main = make_ssa_name (trip_var, NULL);
6577 trip_back = make_ssa_name (trip_var, NULL);
6579 else
6581 trip_init = trip_var;
6582 trip_main = trip_var;
6583 trip_back = trip_var;
6586 gassign *assign_stmt
6587 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6588 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6590 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6591 t = fold_build2 (MULT_EXPR, itype, t, step);
6592 if (POINTER_TYPE_P (type))
6593 t = fold_build_pointer_plus (n1, t);
6594 else
6595 t = fold_build2 (PLUS_EXPR, type, t, n1);
6596 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6597 true, GSI_SAME_STMT);
6599 /* Remove the GIMPLE_OMP_FOR. */
6600 gsi_remove (&gsi, true);
6602 /* Iteration space partitioning goes in ITER_PART_BB. */
6603 gsi = gsi_last_bb (iter_part_bb);
6605 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6606 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6607 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6608 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6609 false, GSI_CONTINUE_LINKING);
6611 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6612 t = fold_build2 (MIN_EXPR, itype, t, n);
6613 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6614 false, GSI_CONTINUE_LINKING);
6616 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6617 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6619 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6620 gsi = gsi_start_bb (seq_start_bb);
6622 tree startvar = fd->loop.v;
6623 tree endvar = NULL_TREE;
6625 if (gimple_omp_for_combined_p (fd->for_stmt))
6627 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6628 ? gimple_omp_parallel_clauses (inner_stmt)
6629 : gimple_omp_for_clauses (inner_stmt);
6630 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6631 gcc_assert (innerc);
6632 startvar = OMP_CLAUSE_DECL (innerc);
6633 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6634 OMP_CLAUSE__LOOPTEMP_);
6635 gcc_assert (innerc);
6636 endvar = OMP_CLAUSE_DECL (innerc);
6639 t = fold_convert (itype, s0);
6640 t = fold_build2 (MULT_EXPR, itype, t, step);
6641 if (POINTER_TYPE_P (type))
6642 t = fold_build_pointer_plus (n1, t);
6643 else
6644 t = fold_build2 (PLUS_EXPR, type, t, n1);
6645 t = fold_convert (TREE_TYPE (startvar), t);
6646 t = force_gimple_operand_gsi (&gsi, t,
6647 DECL_P (startvar)
6648 && TREE_ADDRESSABLE (startvar),
6649 NULL_TREE, false, GSI_CONTINUE_LINKING);
6650 assign_stmt = gimple_build_assign (startvar, t);
6651 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6653 t = fold_convert (itype, e0);
6654 t = fold_build2 (MULT_EXPR, itype, t, step);
6655 if (POINTER_TYPE_P (type))
6656 t = fold_build_pointer_plus (n1, t);
6657 else
6658 t = fold_build2 (PLUS_EXPR, type, t, n1);
6659 t = fold_convert (TREE_TYPE (startvar), t);
6660 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6661 false, GSI_CONTINUE_LINKING);
6662 if (endvar)
6664 assign_stmt = gimple_build_assign (endvar, e);
6665 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6666 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6667 assign_stmt = gimple_build_assign (fd->loop.v, e);
6668 else
6669 assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e);
6670 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6672 if (fd->collapse > 1)
6673 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6675 if (!broken_loop)
6677 /* The code controlling the sequential loop goes in CONT_BB,
6678 replacing the GIMPLE_OMP_CONTINUE. */
6679 gsi = gsi_last_bb (cont_bb);
6680 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6681 vmain = gimple_omp_continue_control_use (cont_stmt);
6682 vback = gimple_omp_continue_control_def (cont_stmt);
6684 if (!gimple_omp_for_combined_p (fd->for_stmt))
6686 if (POINTER_TYPE_P (type))
6687 t = fold_build_pointer_plus (vmain, step);
6688 else
6689 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6690 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
6691 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6692 true, GSI_SAME_STMT);
6693 assign_stmt = gimple_build_assign (vback, t);
6694 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6696 t = build2 (fd->loop.cond_code, boolean_type_node,
6697 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6698 ? t : vback, e);
6699 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6702 /* Remove GIMPLE_OMP_CONTINUE. */
6703 gsi_remove (&gsi, true);
6705 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6706 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6708 /* Trip update code goes into TRIP_UPDATE_BB. */
6709 gsi = gsi_start_bb (trip_update_bb);
6711 t = build_int_cst (itype, 1);
6712 t = build2 (PLUS_EXPR, itype, trip_main, t);
6713 assign_stmt = gimple_build_assign (trip_back, t);
6714 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6717 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6718 gsi = gsi_last_bb (exit_bb);
6719 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6721 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6722 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6724 gsi_remove (&gsi, true);
6726 /* Connect the new blocks. */
6727 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6728 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6730 if (!broken_loop)
6732 se = find_edge (cont_bb, body_bb);
6733 if (gimple_omp_for_combined_p (fd->for_stmt))
6735 remove_edge (se);
6736 se = NULL;
6738 else if (fd->collapse > 1)
6740 remove_edge (se);
6741 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6743 else
6744 se->flags = EDGE_TRUE_VALUE;
6745 find_edge (cont_bb, trip_update_bb)->flags
6746 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6748 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6751 if (gimple_in_ssa_p (cfun))
6753 gphi_iterator psi;
6754 gphi *phi;
6755 edge re, ene;
6756 edge_var_map *vm;
6757 size_t i;
6759 gcc_assert (fd->collapse == 1 && !broken_loop);
6761 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6762 remove arguments of the phi nodes in fin_bb. We need to create
6763 appropriate phi nodes in iter_part_bb instead. */
6764 se = single_pred_edge (fin_bb);
6765 re = single_succ_edge (trip_update_bb);
6766 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
6767 ene = single_succ_edge (entry_bb);
6769 psi = gsi_start_phis (fin_bb);
6770 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6771 gsi_next (&psi), ++i)
6773 gphi *nphi;
6774 source_location locus;
6776 phi = psi.phi ();
6777 t = gimple_phi_result (phi);
6778 gcc_assert (t == redirect_edge_var_map_result (vm));
6779 nphi = create_phi_node (t, iter_part_bb);
6781 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6782 locus = gimple_phi_arg_location_from_edge (phi, se);
6784 /* A special case -- fd->loop.v is not yet computed in
6785 iter_part_bb, we need to use vextra instead. */
6786 if (t == fd->loop.v)
6787 t = vextra;
6788 add_phi_arg (nphi, t, ene, locus);
6789 locus = redirect_edge_var_map_location (vm);
6790 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6792 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6793 redirect_edge_var_map_clear (re);
6794 while (1)
6796 psi = gsi_start_phis (fin_bb);
6797 if (gsi_end_p (psi))
6798 break;
6799 remove_phi_node (&psi, false);
6802 /* Make phi node for trip. */
6803 phi = create_phi_node (trip_main, iter_part_bb);
6804 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6805 UNKNOWN_LOCATION);
6806 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6807 UNKNOWN_LOCATION);
6810 if (!broken_loop)
6811 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6812 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6813 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6814 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6815 recompute_dominator (CDI_DOMINATORS, fin_bb));
6816 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6817 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6818 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6819 recompute_dominator (CDI_DOMINATORS, body_bb));
6821 if (!broken_loop)
6823 struct loop *trip_loop = alloc_loop ();
6824 trip_loop->header = iter_part_bb;
6825 trip_loop->latch = trip_update_bb;
6826 add_loop (trip_loop, iter_part_bb->loop_father);
6828 if (!gimple_omp_for_combined_p (fd->for_stmt))
6830 struct loop *loop = alloc_loop ();
6831 loop->header = body_bb;
6832 if (collapse_bb == NULL)
6833 loop->latch = cont_bb;
6834 add_loop (loop, trip_loop);
6839 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
6840 Given parameters:
6841 for (V = N1; V cond N2; V += STEP) BODY;
6843 where COND is "<" or ">" or "!=", we generate pseudocode
6845 for (ind_var = low; ind_var < high; ind_var++)
6847 V = n1 + (ind_var * STEP)
6849 <BODY>
6852 In the above pseudocode, low and high are function parameters of the
6853 child function. In the function below, we are inserting a temp.
6854 variable that will be making a call to two OMP functions that will not be
6855 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
6856 with _Cilk_for). These functions are replaced with low and high
6857 by the function that handles taskreg. */
6860 static void
6861 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
6863 bool broken_loop = region->cont == NULL;
6864 basic_block entry_bb = region->entry;
6865 basic_block cont_bb = region->cont;
6867 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6868 gcc_assert (broken_loop
6869 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6870 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6871 basic_block l1_bb, l2_bb;
6873 if (!broken_loop)
6875 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6876 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6877 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6878 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6880 else
6882 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6883 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6884 l2_bb = single_succ (l1_bb);
6886 basic_block exit_bb = region->exit;
6887 basic_block l2_dom_bb = NULL;
6889 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
6891 /* Below statements until the "tree high_val = ..." are pseudo statements
6892 used to pass information to be used by expand_omp_taskreg.
6893 low_val and high_val will be replaced by the __low and __high
6894 parameter from the child function.
6896 The call_exprs part is a place-holder, it is mainly used
6897 to distinctly identify to the top-level part that this is
6898 where we should put low and high (reasoning given in header
6899 comment). */
6901 tree child_fndecl
6902 = gimple_omp_parallel_child_fn (
6903 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
6904 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
6905 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
6907 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
6908 high_val = t;
6909 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
6910 low_val = t;
6912 gcc_assert (low_val && high_val);
6914 tree type = TREE_TYPE (low_val);
6915 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
6916 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6918 /* Not needed in SSA form right now. */
6919 gcc_assert (!gimple_in_ssa_p (cfun));
6920 if (l2_dom_bb == NULL)
6921 l2_dom_bb = l1_bb;
6923 tree n1 = low_val;
6924 tree n2 = high_val;
6926 gimple stmt = gimple_build_assign (ind_var, n1);
6928 /* Replace the GIMPLE_OMP_FOR statement. */
6929 gsi_replace (&gsi, stmt, true);
6931 if (!broken_loop)
6933 /* Code to control the increment goes in the CONT_BB. */
6934 gsi = gsi_last_bb (cont_bb);
6935 stmt = gsi_stmt (gsi);
6936 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6937 stmt = gimple_build_assign_with_ops (PLUS_EXPR, ind_var, ind_var,
6938 build_one_cst (type));
6940 /* Replace GIMPLE_OMP_CONTINUE. */
6941 gsi_replace (&gsi, stmt, true);
6944 /* Emit the condition in L1_BB. */
6945 gsi = gsi_after_labels (l1_bb);
6946 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
6947 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
6948 fd->loop.step);
6949 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
6950 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6951 fd->loop.n1, fold_convert (sizetype, t));
6952 else
6953 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6954 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
6955 t = fold_convert (TREE_TYPE (fd->loop.v), t);
6956 expand_omp_build_assign (&gsi, fd->loop.v, t);
6958 /* The condition is always '<' since the runtime will fill in the low
6959 and high values. */
6960 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
6961 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6963 /* Remove GIMPLE_OMP_RETURN. */
6964 gsi = gsi_last_bb (exit_bb);
6965 gsi_remove (&gsi, true);
6967 /* Connect the new blocks. */
6968 remove_edge (FALLTHRU_EDGE (entry_bb));
6970 edge e, ne;
6971 if (!broken_loop)
6973 remove_edge (BRANCH_EDGE (entry_bb));
6974 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6976 e = BRANCH_EDGE (l1_bb);
6977 ne = FALLTHRU_EDGE (l1_bb);
6978 e->flags = EDGE_TRUE_VALUE;
6980 else
6982 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6984 ne = single_succ_edge (l1_bb);
6985 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6988 ne->flags = EDGE_FALSE_VALUE;
6989 e->probability = REG_BR_PROB_BASE * 7 / 8;
6990 ne->probability = REG_BR_PROB_BASE / 8;
6992 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6993 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6994 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6996 if (!broken_loop)
6998 struct loop *loop = alloc_loop ();
6999 loop->header = l1_bb;
7000 loop->latch = cont_bb;
7001 add_loop (loop, l1_bb->loop_father);
7002 loop->safelen = INT_MAX;
7005 /* Pick the correct library function based on the precision of the
7006 induction variable type. */
7007 tree lib_fun = NULL_TREE;
7008 if (TYPE_PRECISION (type) == 32)
7009 lib_fun = cilk_for_32_fndecl;
7010 else if (TYPE_PRECISION (type) == 64)
7011 lib_fun = cilk_for_64_fndecl;
7012 else
7013 gcc_unreachable ();
7015 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7017 /* WS_ARGS contains the library function flavor to call:
7018 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7019 user-defined grain value. If the user does not define one, then zero
7020 is passed in by the parser. */
7021 vec_alloc (region->ws_args, 2);
7022 region->ws_args->quick_push (lib_fun);
7023 region->ws_args->quick_push (fd->chunk_size);
7026 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7027 loop. Given parameters:
7029 for (V = N1; V cond N2; V += STEP) BODY;
7031 where COND is "<" or ">", we generate pseudocode
7033 V = N1;
7034 goto L1;
7036 BODY;
7037 V += STEP;
7039 if (V cond N2) goto L0; else goto L2;
7042 For collapsed loops, given parameters:
7043 collapse(3)
7044 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7045 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7046 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7047 BODY;
7049 we generate pseudocode
7051 if (cond3 is <)
7052 adj = STEP3 - 1;
7053 else
7054 adj = STEP3 + 1;
7055 count3 = (adj + N32 - N31) / STEP3;
7056 if (cond2 is <)
7057 adj = STEP2 - 1;
7058 else
7059 adj = STEP2 + 1;
7060 count2 = (adj + N22 - N21) / STEP2;
7061 if (cond1 is <)
7062 adj = STEP1 - 1;
7063 else
7064 adj = STEP1 + 1;
7065 count1 = (adj + N12 - N11) / STEP1;
7066 count = count1 * count2 * count3;
7067 V = 0;
7068 V1 = N11;
7069 V2 = N21;
7070 V3 = N31;
7071 goto L1;
7073 BODY;
7074 V += 1;
7075 V3 += STEP3;
7076 V2 += (V3 cond3 N32) ? 0 : STEP2;
7077 V3 = (V3 cond3 N32) ? V3 : N31;
7078 V1 += (V2 cond2 N22) ? 0 : STEP1;
7079 V2 = (V2 cond2 N22) ? V2 : N21;
7081 if (V < count) goto L0; else goto L2;
7086 static void
7087 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7089 tree type, t;
7090 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7091 gimple_stmt_iterator gsi;
7092 gimple stmt;
7093 gcond *cond_stmt;
7094 bool broken_loop = region->cont == NULL;
7095 edge e, ne;
7096 tree *counts = NULL;
7097 int i;
7098 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7099 OMP_CLAUSE_SAFELEN);
7100 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7101 OMP_CLAUSE__SIMDUID_);
7102 tree n1, n2;
7104 type = TREE_TYPE (fd->loop.v);
7105 entry_bb = region->entry;
7106 cont_bb = region->cont;
7107 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7108 gcc_assert (broken_loop
7109 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7110 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7111 if (!broken_loop)
7113 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7114 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7115 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7116 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7118 else
7120 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7121 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7122 l2_bb = single_succ (l1_bb);
7124 exit_bb = region->exit;
7125 l2_dom_bb = NULL;
7127 gsi = gsi_last_bb (entry_bb);
7129 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7130 /* Not needed in SSA form right now. */
7131 gcc_assert (!gimple_in_ssa_p (cfun));
7132 if (fd->collapse > 1)
7134 int first_zero_iter = -1;
7135 basic_block zero_iter_bb = l2_bb;
7137 counts = XALLOCAVEC (tree, fd->collapse);
7138 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7139 zero_iter_bb, first_zero_iter,
7140 l2_dom_bb);
7142 if (l2_dom_bb == NULL)
7143 l2_dom_bb = l1_bb;
7145 n1 = fd->loop.n1;
7146 n2 = fd->loop.n2;
7147 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7149 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7150 OMP_CLAUSE__LOOPTEMP_);
7151 gcc_assert (innerc);
7152 n1 = OMP_CLAUSE_DECL (innerc);
7153 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7154 OMP_CLAUSE__LOOPTEMP_);
7155 gcc_assert (innerc);
7156 n2 = OMP_CLAUSE_DECL (innerc);
7157 expand_omp_build_assign (&gsi, fd->loop.v,
7158 fold_convert (type, n1));
7159 if (fd->collapse > 1)
7161 gsi_prev (&gsi);
7162 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7163 gsi_next (&gsi);
7166 else
7168 expand_omp_build_assign (&gsi, fd->loop.v,
7169 fold_convert (type, fd->loop.n1));
7170 if (fd->collapse > 1)
7171 for (i = 0; i < fd->collapse; i++)
7173 tree itype = TREE_TYPE (fd->loops[i].v);
7174 if (POINTER_TYPE_P (itype))
7175 itype = signed_type_for (itype);
7176 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7177 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7181 /* Remove the GIMPLE_OMP_FOR statement. */
7182 gsi_remove (&gsi, true);
7184 if (!broken_loop)
7186 /* Code to control the increment goes in the CONT_BB. */
7187 gsi = gsi_last_bb (cont_bb);
7188 stmt = gsi_stmt (gsi);
7189 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7191 if (POINTER_TYPE_P (type))
7192 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7193 else
7194 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7195 expand_omp_build_assign (&gsi, fd->loop.v, t);
7197 if (fd->collapse > 1)
7199 i = fd->collapse - 1;
7200 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7202 t = fold_convert (sizetype, fd->loops[i].step);
7203 t = fold_build_pointer_plus (fd->loops[i].v, t);
7205 else
7207 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7208 fd->loops[i].step);
7209 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7210 fd->loops[i].v, t);
7212 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7214 for (i = fd->collapse - 1; i > 0; i--)
7216 tree itype = TREE_TYPE (fd->loops[i].v);
7217 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7218 if (POINTER_TYPE_P (itype2))
7219 itype2 = signed_type_for (itype2);
7220 t = build3 (COND_EXPR, itype2,
7221 build2 (fd->loops[i].cond_code, boolean_type_node,
7222 fd->loops[i].v,
7223 fold_convert (itype, fd->loops[i].n2)),
7224 build_int_cst (itype2, 0),
7225 fold_convert (itype2, fd->loops[i - 1].step));
7226 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7227 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7228 else
7229 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7230 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7232 t = build3 (COND_EXPR, itype,
7233 build2 (fd->loops[i].cond_code, boolean_type_node,
7234 fd->loops[i].v,
7235 fold_convert (itype, fd->loops[i].n2)),
7236 fd->loops[i].v,
7237 fold_convert (itype, fd->loops[i].n1));
7238 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7242 /* Remove GIMPLE_OMP_CONTINUE. */
7243 gsi_remove (&gsi, true);
7246 /* Emit the condition in L1_BB. */
7247 gsi = gsi_start_bb (l1_bb);
7249 t = fold_convert (type, n2);
7250 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7251 false, GSI_CONTINUE_LINKING);
7252 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7253 cond_stmt = gimple_build_cond_empty (t);
7254 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7255 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7256 NULL, NULL)
7257 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7258 NULL, NULL))
7260 gsi = gsi_for_stmt (cond_stmt);
7261 gimple_regimplify_operands (cond_stmt, &gsi);
7264 /* Remove GIMPLE_OMP_RETURN. */
7265 gsi = gsi_last_bb (exit_bb);
7266 gsi_remove (&gsi, true);
7268 /* Connect the new blocks. */
7269 remove_edge (FALLTHRU_EDGE (entry_bb));
7271 if (!broken_loop)
7273 remove_edge (BRANCH_EDGE (entry_bb));
7274 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7276 e = BRANCH_EDGE (l1_bb);
7277 ne = FALLTHRU_EDGE (l1_bb);
7278 e->flags = EDGE_TRUE_VALUE;
7280 else
7282 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7284 ne = single_succ_edge (l1_bb);
7285 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7288 ne->flags = EDGE_FALSE_VALUE;
7289 e->probability = REG_BR_PROB_BASE * 7 / 8;
7290 ne->probability = REG_BR_PROB_BASE / 8;
7292 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7293 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7294 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7296 if (!broken_loop)
7298 struct loop *loop = alloc_loop ();
7299 loop->header = l1_bb;
7300 loop->latch = cont_bb;
7301 add_loop (loop, l1_bb->loop_father);
7302 if (safelen == NULL_TREE)
7303 loop->safelen = INT_MAX;
7304 else
7306 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7307 if (TREE_CODE (safelen) != INTEGER_CST)
7308 loop->safelen = 0;
7309 else if (!tree_fits_uhwi_p (safelen)
7310 || tree_to_uhwi (safelen) > INT_MAX)
7311 loop->safelen = INT_MAX;
7312 else
7313 loop->safelen = tree_to_uhwi (safelen);
7314 if (loop->safelen == 1)
7315 loop->safelen = 0;
7317 if (simduid)
7319 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7320 cfun->has_simduid_loops = true;
7322 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7323 the loop. */
7324 if ((flag_tree_loop_vectorize
7325 || (!global_options_set.x_flag_tree_loop_vectorize
7326 && !global_options_set.x_flag_tree_vectorize))
7327 && flag_tree_loop_optimize
7328 && loop->safelen > 1)
7330 loop->force_vectorize = true;
7331 cfun->has_force_vectorize_loops = true;
7337 /* Expand the OpenMP loop defined by REGION. */
7339 static void
7340 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7342 struct omp_for_data fd;
7343 struct omp_for_data_loop *loops;
7345 loops
7346 = (struct omp_for_data_loop *)
7347 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7348 * sizeof (struct omp_for_data_loop));
7349 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7350 &fd, loops);
7351 region->sched_kind = fd.sched_kind;
7353 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7354 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7355 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7356 if (region->cont)
7358 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7359 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7360 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7362 else
7363 /* If there isn't a continue then this is a degerate case where
7364 the introduction of abnormal edges during lowering will prevent
7365 original loops from being detected. Fix that up. */
7366 loops_state_set (LOOPS_NEED_FIXUP);
7368 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7369 expand_omp_simd (region, &fd);
7370 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7371 expand_cilk_for (region, &fd);
7372 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7373 && !fd.have_ordered)
7375 if (fd.chunk_size == NULL)
7376 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7377 else
7378 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7380 else
7382 int fn_index, start_ix, next_ix;
7384 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7385 == GF_OMP_FOR_KIND_FOR);
7386 if (fd.chunk_size == NULL
7387 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7388 fd.chunk_size = integer_zero_node;
7389 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7390 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7391 ? 3 : fd.sched_kind;
7392 fn_index += fd.have_ordered * 4;
7393 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7394 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7395 if (fd.iter_type == long_long_unsigned_type_node)
7397 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7398 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7399 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7400 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7402 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7403 (enum built_in_function) next_ix, inner_stmt);
7406 if (gimple_in_ssa_p (cfun))
7407 update_ssa (TODO_update_ssa_only_virtuals);
7411 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7413 v = GOMP_sections_start (n);
7415 switch (v)
7417 case 0:
7418 goto L2;
7419 case 1:
7420 section 1;
7421 goto L1;
7422 case 2:
7424 case n:
7426 default:
7427 abort ();
7430 v = GOMP_sections_next ();
7431 goto L0;
7433 reduction;
7435 If this is a combined parallel sections, replace the call to
7436 GOMP_sections_start with call to GOMP_sections_next. */
7438 static void
7439 expand_omp_sections (struct omp_region *region)
7441 tree t, u, vin = NULL, vmain, vnext, l2;
7442 unsigned len;
7443 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7444 gimple_stmt_iterator si, switch_si;
7445 gomp_sections *sections_stmt;
7446 gimple stmt;
7447 gomp_continue *cont;
7448 edge_iterator ei;
7449 edge e;
7450 struct omp_region *inner;
7451 unsigned i, casei;
7452 bool exit_reachable = region->cont != NULL;
7454 gcc_assert (region->exit != NULL);
7455 entry_bb = region->entry;
7456 l0_bb = single_succ (entry_bb);
7457 l1_bb = region->cont;
7458 l2_bb = region->exit;
7459 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7460 l2 = gimple_block_label (l2_bb);
7461 else
7463 /* This can happen if there are reductions. */
7464 len = EDGE_COUNT (l0_bb->succs);
7465 gcc_assert (len > 0);
7466 e = EDGE_SUCC (l0_bb, len - 1);
7467 si = gsi_last_bb (e->dest);
7468 l2 = NULL_TREE;
7469 if (gsi_end_p (si)
7470 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7471 l2 = gimple_block_label (e->dest);
7472 else
7473 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7475 si = gsi_last_bb (e->dest);
7476 if (gsi_end_p (si)
7477 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7479 l2 = gimple_block_label (e->dest);
7480 break;
7484 if (exit_reachable)
7485 default_bb = create_empty_bb (l1_bb->prev_bb);
7486 else
7487 default_bb = create_empty_bb (l0_bb);
7489 /* We will build a switch() with enough cases for all the
7490 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7491 and a default case to abort if something goes wrong. */
7492 len = EDGE_COUNT (l0_bb->succs);
7494 /* Use vec::quick_push on label_vec throughout, since we know the size
7495 in advance. */
7496 auto_vec<tree> label_vec (len);
7498 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7499 GIMPLE_OMP_SECTIONS statement. */
7500 si = gsi_last_bb (entry_bb);
7501 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
7502 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7503 vin = gimple_omp_sections_control (sections_stmt);
7504 if (!is_combined_parallel (region))
7506 /* If we are not inside a combined parallel+sections region,
7507 call GOMP_sections_start. */
7508 t = build_int_cst (unsigned_type_node, len - 1);
7509 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7510 stmt = gimple_build_call (u, 1, t);
7512 else
7514 /* Otherwise, call GOMP_sections_next. */
7515 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7516 stmt = gimple_build_call (u, 0);
7518 gimple_call_set_lhs (stmt, vin);
7519 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7520 gsi_remove (&si, true);
7522 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7523 L0_BB. */
7524 switch_si = gsi_last_bb (l0_bb);
7525 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7526 if (exit_reachable)
7528 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
7529 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7530 vmain = gimple_omp_continue_control_use (cont);
7531 vnext = gimple_omp_continue_control_def (cont);
7533 else
7535 vmain = vin;
7536 vnext = NULL_TREE;
7539 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7540 label_vec.quick_push (t);
7541 i = 1;
7543 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7544 for (inner = region->inner, casei = 1;
7545 inner;
7546 inner = inner->next, i++, casei++)
7548 basic_block s_entry_bb, s_exit_bb;
7550 /* Skip optional reduction region. */
7551 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7553 --i;
7554 --casei;
7555 continue;
7558 s_entry_bb = inner->entry;
7559 s_exit_bb = inner->exit;
7561 t = gimple_block_label (s_entry_bb);
7562 u = build_int_cst (unsigned_type_node, casei);
7563 u = build_case_label (u, NULL, t);
7564 label_vec.quick_push (u);
7566 si = gsi_last_bb (s_entry_bb);
7567 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7568 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7569 gsi_remove (&si, true);
7570 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7572 if (s_exit_bb == NULL)
7573 continue;
7575 si = gsi_last_bb (s_exit_bb);
7576 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7577 gsi_remove (&si, true);
7579 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7582 /* Error handling code goes in DEFAULT_BB. */
7583 t = gimple_block_label (default_bb);
7584 u = build_case_label (NULL, NULL, t);
7585 make_edge (l0_bb, default_bb, 0);
7586 add_bb_to_loop (default_bb, current_loops->tree_root);
7588 stmt = gimple_build_switch (vmain, u, label_vec);
7589 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7590 gsi_remove (&switch_si, true);
7592 si = gsi_start_bb (default_bb);
7593 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7594 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7596 if (exit_reachable)
7598 tree bfn_decl;
7600 /* Code to get the next section goes in L1_BB. */
7601 si = gsi_last_bb (l1_bb);
7602 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7604 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7605 stmt = gimple_build_call (bfn_decl, 0);
7606 gimple_call_set_lhs (stmt, vnext);
7607 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7608 gsi_remove (&si, true);
7610 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7613 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7614 si = gsi_last_bb (l2_bb);
7615 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7616 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7617 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7618 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7619 else
7620 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7621 stmt = gimple_build_call (t, 0);
7622 if (gimple_omp_return_lhs (gsi_stmt (si)))
7623 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7624 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7625 gsi_remove (&si, true);
7627 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7631 /* Expand code for an OpenMP single directive. We've already expanded
7632 much of the code, here we simply place the GOMP_barrier call. */
7634 static void
7635 expand_omp_single (struct omp_region *region)
7637 basic_block entry_bb, exit_bb;
7638 gimple_stmt_iterator si;
7640 entry_bb = region->entry;
7641 exit_bb = region->exit;
7643 si = gsi_last_bb (entry_bb);
7644 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7645 gsi_remove (&si, true);
7646 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7648 si = gsi_last_bb (exit_bb);
7649 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7651 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7652 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7654 gsi_remove (&si, true);
7655 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7659 /* Generic expansion for OpenMP synchronization directives: master,
7660 ordered and critical. All we need to do here is remove the entry
7661 and exit markers for REGION. */
7663 static void
7664 expand_omp_synch (struct omp_region *region)
7666 basic_block entry_bb, exit_bb;
7667 gimple_stmt_iterator si;
7669 entry_bb = region->entry;
7670 exit_bb = region->exit;
7672 si = gsi_last_bb (entry_bb);
7673 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7674 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7675 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7676 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7677 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7678 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7679 gsi_remove (&si, true);
7680 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7682 if (exit_bb)
7684 si = gsi_last_bb (exit_bb);
7685 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7686 gsi_remove (&si, true);
7687 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7691 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7692 operation as a normal volatile load. */
7694 static bool
7695 expand_omp_atomic_load (basic_block load_bb, tree addr,
7696 tree loaded_val, int index)
7698 enum built_in_function tmpbase;
7699 gimple_stmt_iterator gsi;
7700 basic_block store_bb;
7701 location_t loc;
7702 gimple stmt;
7703 tree decl, call, type, itype;
7705 gsi = gsi_last_bb (load_bb);
7706 stmt = gsi_stmt (gsi);
7707 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7708 loc = gimple_location (stmt);
7710 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7711 is smaller than word size, then expand_atomic_load assumes that the load
7712 is atomic. We could avoid the builtin entirely in this case. */
7714 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7715 decl = builtin_decl_explicit (tmpbase);
7716 if (decl == NULL_TREE)
7717 return false;
7719 type = TREE_TYPE (loaded_val);
7720 itype = TREE_TYPE (TREE_TYPE (decl));
7722 call = build_call_expr_loc (loc, decl, 2, addr,
7723 build_int_cst (NULL,
7724 gimple_omp_atomic_seq_cst_p (stmt)
7725 ? MEMMODEL_SEQ_CST
7726 : MEMMODEL_RELAXED));
7727 if (!useless_type_conversion_p (type, itype))
7728 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7729 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7731 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7732 gsi_remove (&gsi, true);
7734 store_bb = single_succ (load_bb);
7735 gsi = gsi_last_bb (store_bb);
7736 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7737 gsi_remove (&gsi, true);
7739 if (gimple_in_ssa_p (cfun))
7740 update_ssa (TODO_update_ssa_no_phi);
7742 return true;
7745 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7746 operation as a normal volatile store. */
7748 static bool
7749 expand_omp_atomic_store (basic_block load_bb, tree addr,
7750 tree loaded_val, tree stored_val, int index)
7752 enum built_in_function tmpbase;
7753 gimple_stmt_iterator gsi;
7754 basic_block store_bb = single_succ (load_bb);
7755 location_t loc;
7756 gimple stmt;
7757 tree decl, call, type, itype;
7758 machine_mode imode;
7759 bool exchange;
7761 gsi = gsi_last_bb (load_bb);
7762 stmt = gsi_stmt (gsi);
7763 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7765 /* If the load value is needed, then this isn't a store but an exchange. */
7766 exchange = gimple_omp_atomic_need_value_p (stmt);
7768 gsi = gsi_last_bb (store_bb);
7769 stmt = gsi_stmt (gsi);
7770 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7771 loc = gimple_location (stmt);
7773 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7774 is smaller than word size, then expand_atomic_store assumes that the store
7775 is atomic. We could avoid the builtin entirely in this case. */
7777 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7778 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7779 decl = builtin_decl_explicit (tmpbase);
7780 if (decl == NULL_TREE)
7781 return false;
7783 type = TREE_TYPE (stored_val);
7785 /* Dig out the type of the function's second argument. */
7786 itype = TREE_TYPE (decl);
7787 itype = TYPE_ARG_TYPES (itype);
7788 itype = TREE_CHAIN (itype);
7789 itype = TREE_VALUE (itype);
7790 imode = TYPE_MODE (itype);
7792 if (exchange && !can_atomic_exchange_p (imode, true))
7793 return false;
7795 if (!useless_type_conversion_p (itype, type))
7796 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7797 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7798 build_int_cst (NULL,
7799 gimple_omp_atomic_seq_cst_p (stmt)
7800 ? MEMMODEL_SEQ_CST
7801 : MEMMODEL_RELAXED));
7802 if (exchange)
7804 if (!useless_type_conversion_p (type, itype))
7805 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7806 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7809 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7810 gsi_remove (&gsi, true);
7812 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7813 gsi = gsi_last_bb (load_bb);
7814 gsi_remove (&gsi, true);
7816 if (gimple_in_ssa_p (cfun))
7817 update_ssa (TODO_update_ssa_no_phi);
7819 return true;
7822 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7823 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7824 size of the data type, and thus usable to find the index of the builtin
7825 decl. Returns false if the expression is not of the proper form. */
7827 static bool
7828 expand_omp_atomic_fetch_op (basic_block load_bb,
7829 tree addr, tree loaded_val,
7830 tree stored_val, int index)
7832 enum built_in_function oldbase, newbase, tmpbase;
7833 tree decl, itype, call;
7834 tree lhs, rhs;
7835 basic_block store_bb = single_succ (load_bb);
7836 gimple_stmt_iterator gsi;
7837 gimple stmt;
7838 location_t loc;
7839 enum tree_code code;
7840 bool need_old, need_new;
7841 machine_mode imode;
7842 bool seq_cst;
7844 /* We expect to find the following sequences:
7846 load_bb:
7847 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7849 store_bb:
7850 val = tmp OP something; (or: something OP tmp)
7851 GIMPLE_OMP_STORE (val)
7853 ???FIXME: Allow a more flexible sequence.
7854 Perhaps use data flow to pick the statements.
7858 gsi = gsi_after_labels (store_bb);
7859 stmt = gsi_stmt (gsi);
7860 loc = gimple_location (stmt);
7861 if (!is_gimple_assign (stmt))
7862 return false;
7863 gsi_next (&gsi);
7864 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7865 return false;
7866 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7867 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7868 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7869 gcc_checking_assert (!need_old || !need_new);
7871 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7872 return false;
7874 /* Check for one of the supported fetch-op operations. */
7875 code = gimple_assign_rhs_code (stmt);
7876 switch (code)
7878 case PLUS_EXPR:
7879 case POINTER_PLUS_EXPR:
7880 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7881 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7882 break;
7883 case MINUS_EXPR:
7884 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7885 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7886 break;
7887 case BIT_AND_EXPR:
7888 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7889 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7890 break;
7891 case BIT_IOR_EXPR:
7892 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7893 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7894 break;
7895 case BIT_XOR_EXPR:
7896 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7897 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7898 break;
7899 default:
7900 return false;
7903 /* Make sure the expression is of the proper form. */
7904 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7905 rhs = gimple_assign_rhs2 (stmt);
7906 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7907 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7908 rhs = gimple_assign_rhs1 (stmt);
7909 else
7910 return false;
7912 tmpbase = ((enum built_in_function)
7913 ((need_new ? newbase : oldbase) + index + 1));
7914 decl = builtin_decl_explicit (tmpbase);
7915 if (decl == NULL_TREE)
7916 return false;
7917 itype = TREE_TYPE (TREE_TYPE (decl));
7918 imode = TYPE_MODE (itype);
7920 /* We could test all of the various optabs involved, but the fact of the
7921 matter is that (with the exception of i486 vs i586 and xadd) all targets
7922 that support any atomic operaton optab also implements compare-and-swap.
7923 Let optabs.c take care of expanding any compare-and-swap loop. */
7924 if (!can_compare_and_swap_p (imode, true))
7925 return false;
7927 gsi = gsi_last_bb (load_bb);
7928 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7930 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7931 It only requires that the operation happen atomically. Thus we can
7932 use the RELAXED memory model. */
7933 call = build_call_expr_loc (loc, decl, 3, addr,
7934 fold_convert_loc (loc, itype, rhs),
7935 build_int_cst (NULL,
7936 seq_cst ? MEMMODEL_SEQ_CST
7937 : MEMMODEL_RELAXED));
7939 if (need_old || need_new)
7941 lhs = need_old ? loaded_val : stored_val;
7942 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7943 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7945 else
7946 call = fold_convert_loc (loc, void_type_node, call);
7947 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7948 gsi_remove (&gsi, true);
7950 gsi = gsi_last_bb (store_bb);
7951 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7952 gsi_remove (&gsi, true);
7953 gsi = gsi_last_bb (store_bb);
7954 gsi_remove (&gsi, true);
7956 if (gimple_in_ssa_p (cfun))
7957 update_ssa (TODO_update_ssa_no_phi);
7959 return true;
7962 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7964 oldval = *addr;
7965 repeat:
7966 newval = rhs; // with oldval replacing *addr in rhs
7967 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7968 if (oldval != newval)
7969 goto repeat;
7971 INDEX is log2 of the size of the data type, and thus usable to find the
7972 index of the builtin decl. */
7974 static bool
7975 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7976 tree addr, tree loaded_val, tree stored_val,
7977 int index)
7979 tree loadedi, storedi, initial, new_storedi, old_vali;
7980 tree type, itype, cmpxchg, iaddr;
7981 gimple_stmt_iterator si;
7982 basic_block loop_header = single_succ (load_bb);
7983 gimple phi, stmt;
7984 edge e;
7985 enum built_in_function fncode;
7987 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7988 order to use the RELAXED memory model effectively. */
7989 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7990 + index + 1);
7991 cmpxchg = builtin_decl_explicit (fncode);
7992 if (cmpxchg == NULL_TREE)
7993 return false;
7994 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7995 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7997 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7998 return false;
8000 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8001 si = gsi_last_bb (load_bb);
8002 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8004 /* For floating-point values, we'll need to view-convert them to integers
8005 so that we can perform the atomic compare and swap. Simplify the
8006 following code by always setting up the "i"ntegral variables. */
8007 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8009 tree iaddr_val;
8011 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8012 true), NULL);
8013 iaddr_val
8014 = force_gimple_operand_gsi (&si,
8015 fold_convert (TREE_TYPE (iaddr), addr),
8016 false, NULL_TREE, true, GSI_SAME_STMT);
8017 stmt = gimple_build_assign (iaddr, iaddr_val);
8018 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8019 loadedi = create_tmp_var (itype, NULL);
8020 if (gimple_in_ssa_p (cfun))
8021 loadedi = make_ssa_name (loadedi, NULL);
8023 else
8025 iaddr = addr;
8026 loadedi = loaded_val;
8029 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8030 tree loaddecl = builtin_decl_explicit (fncode);
8031 if (loaddecl)
8032 initial
8033 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8034 build_call_expr (loaddecl, 2, iaddr,
8035 build_int_cst (NULL_TREE,
8036 MEMMODEL_RELAXED)));
8037 else
8038 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8039 build_int_cst (TREE_TYPE (iaddr), 0));
8041 initial
8042 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8043 GSI_SAME_STMT);
8045 /* Move the value to the LOADEDI temporary. */
8046 if (gimple_in_ssa_p (cfun))
8048 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8049 phi = create_phi_node (loadedi, loop_header);
8050 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8051 initial);
8053 else
8054 gsi_insert_before (&si,
8055 gimple_build_assign (loadedi, initial),
8056 GSI_SAME_STMT);
8057 if (loadedi != loaded_val)
8059 gimple_stmt_iterator gsi2;
8060 tree x;
8062 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8063 gsi2 = gsi_start_bb (loop_header);
8064 if (gimple_in_ssa_p (cfun))
8066 gassign *stmt;
8067 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8068 true, GSI_SAME_STMT);
8069 stmt = gimple_build_assign (loaded_val, x);
8070 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8072 else
8074 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8075 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8076 true, GSI_SAME_STMT);
8079 gsi_remove (&si, true);
8081 si = gsi_last_bb (store_bb);
8082 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8084 if (iaddr == addr)
8085 storedi = stored_val;
8086 else
8087 storedi =
8088 force_gimple_operand_gsi (&si,
8089 build1 (VIEW_CONVERT_EXPR, itype,
8090 stored_val), true, NULL_TREE, true,
8091 GSI_SAME_STMT);
8093 /* Build the compare&swap statement. */
8094 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8095 new_storedi = force_gimple_operand_gsi (&si,
8096 fold_convert (TREE_TYPE (loadedi),
8097 new_storedi),
8098 true, NULL_TREE,
8099 true, GSI_SAME_STMT);
8101 if (gimple_in_ssa_p (cfun))
8102 old_vali = loadedi;
8103 else
8105 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
8106 stmt = gimple_build_assign (old_vali, loadedi);
8107 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8109 stmt = gimple_build_assign (loadedi, new_storedi);
8110 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8113 /* Note that we always perform the comparison as an integer, even for
8114 floating point. This allows the atomic operation to properly
8115 succeed even with NaNs and -0.0. */
8116 stmt = gimple_build_cond_empty
8117 (build2 (NE_EXPR, boolean_type_node,
8118 new_storedi, old_vali));
8119 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8121 /* Update cfg. */
8122 e = single_succ_edge (store_bb);
8123 e->flags &= ~EDGE_FALLTHRU;
8124 e->flags |= EDGE_FALSE_VALUE;
8126 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8128 /* Copy the new value to loadedi (we already did that before the condition
8129 if we are not in SSA). */
8130 if (gimple_in_ssa_p (cfun))
8132 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8133 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8136 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8137 gsi_remove (&si, true);
8139 struct loop *loop = alloc_loop ();
8140 loop->header = loop_header;
8141 loop->latch = store_bb;
8142 add_loop (loop, loop_header->loop_father);
8144 if (gimple_in_ssa_p (cfun))
8145 update_ssa (TODO_update_ssa_no_phi);
8147 return true;
8150 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8152 GOMP_atomic_start ();
8153 *addr = rhs;
8154 GOMP_atomic_end ();
8156 The result is not globally atomic, but works so long as all parallel
8157 references are within #pragma omp atomic directives. According to
8158 responses received from omp@openmp.org, appears to be within spec.
8159 Which makes sense, since that's how several other compilers handle
8160 this situation as well.
8161 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8162 expanding. STORED_VAL is the operand of the matching
8163 GIMPLE_OMP_ATOMIC_STORE.
8165 We replace
8166 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8167 loaded_val = *addr;
8169 and replace
8170 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8171 *addr = stored_val;
8174 static bool
8175 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8176 tree addr, tree loaded_val, tree stored_val)
8178 gimple_stmt_iterator si;
8179 gassign *stmt;
8180 tree t;
8182 si = gsi_last_bb (load_bb);
8183 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8185 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8186 t = build_call_expr (t, 0);
8187 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8189 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8190 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8191 gsi_remove (&si, true);
8193 si = gsi_last_bb (store_bb);
8194 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8196 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8197 stored_val);
8198 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8200 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8201 t = build_call_expr (t, 0);
8202 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8203 gsi_remove (&si, true);
8205 if (gimple_in_ssa_p (cfun))
8206 update_ssa (TODO_update_ssa_no_phi);
8207 return true;
8210 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8211 using expand_omp_atomic_fetch_op. If it failed, we try to
8212 call expand_omp_atomic_pipeline, and if it fails too, the
8213 ultimate fallback is wrapping the operation in a mutex
8214 (expand_omp_atomic_mutex). REGION is the atomic region built
8215 by build_omp_regions_1(). */
8217 static void
8218 expand_omp_atomic (struct omp_region *region)
8220 basic_block load_bb = region->entry, store_bb = region->exit;
8221 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8222 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8223 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8224 tree addr = gimple_omp_atomic_load_rhs (load);
8225 tree stored_val = gimple_omp_atomic_store_val (store);
8226 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8227 HOST_WIDE_INT index;
8229 /* Make sure the type is one of the supported sizes. */
8230 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8231 index = exact_log2 (index);
8232 if (index >= 0 && index <= 4)
8234 unsigned int align = TYPE_ALIGN_UNIT (type);
8236 /* __sync builtins require strict data alignment. */
8237 if (exact_log2 (align) >= index)
8239 /* Atomic load. */
8240 if (loaded_val == stored_val
8241 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8242 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8243 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8244 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8245 return;
8247 /* Atomic store. */
8248 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8249 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8250 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8251 && store_bb == single_succ (load_bb)
8252 && first_stmt (store_bb) == store
8253 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8254 stored_val, index))
8255 return;
8257 /* When possible, use specialized atomic update functions. */
8258 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8259 && store_bb == single_succ (load_bb)
8260 && expand_omp_atomic_fetch_op (load_bb, addr,
8261 loaded_val, stored_val, index))
8262 return;
8264 /* If we don't have specialized __sync builtins, try and implement
8265 as a compare and swap loop. */
8266 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8267 loaded_val, stored_val, index))
8268 return;
8272 /* The ultimate fallback is wrapping the operation in a mutex. */
8273 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8277 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
8279 static void
8280 expand_omp_target (struct omp_region *region)
8282 basic_block entry_bb, exit_bb, new_bb;
8283 struct function *child_cfun = NULL;
8284 tree child_fn = NULL_TREE, block, t;
8285 gimple_stmt_iterator gsi;
8286 gomp_target *entry_stmt;
8287 gimple stmt;
8288 edge e;
8290 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8291 new_bb = region->entry;
8292 int kind = gimple_omp_target_kind (entry_stmt);
8293 if (kind == GF_OMP_TARGET_KIND_REGION)
8295 child_fn = gimple_omp_target_child_fn (entry_stmt);
8296 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8299 entry_bb = region->entry;
8300 exit_bb = region->exit;
8302 if (kind == GF_OMP_TARGET_KIND_REGION)
8304 unsigned srcidx, dstidx, num;
8306 /* If the target region needs data sent from the parent
8307 function, then the very first statement (except possible
8308 tree profile counter updates) of the parallel body
8309 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8310 &.OMP_DATA_O is passed as an argument to the child function,
8311 we need to replace it with the argument as seen by the child
8312 function.
8314 In most cases, this will end up being the identity assignment
8315 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8316 a function call that has been inlined, the original PARM_DECL
8317 .OMP_DATA_I may have been converted into a different local
8318 variable. In which case, we need to keep the assignment. */
8319 if (gimple_omp_target_data_arg (entry_stmt))
8321 basic_block entry_succ_bb = single_succ (entry_bb);
8322 gimple_stmt_iterator gsi;
8323 tree arg;
8324 gimple tgtcopy_stmt = NULL;
8325 tree sender
8326 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
8328 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8330 gcc_assert (!gsi_end_p (gsi));
8331 stmt = gsi_stmt (gsi);
8332 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8333 continue;
8335 if (gimple_num_ops (stmt) == 2)
8337 tree arg = gimple_assign_rhs1 (stmt);
8339 /* We're ignoring the subcode because we're
8340 effectively doing a STRIP_NOPS. */
8342 if (TREE_CODE (arg) == ADDR_EXPR
8343 && TREE_OPERAND (arg, 0) == sender)
8345 tgtcopy_stmt = stmt;
8346 break;
8351 gcc_assert (tgtcopy_stmt != NULL);
8352 arg = DECL_ARGUMENTS (child_fn);
8354 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8355 gsi_remove (&gsi, true);
8358 /* Declare local variables needed in CHILD_CFUN. */
8359 block = DECL_INITIAL (child_fn);
8360 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8361 /* The gimplifier could record temporaries in target block
8362 rather than in containing function's local_decls chain,
8363 which would mean cgraph missed finalizing them. Do it now. */
8364 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8365 if (TREE_CODE (t) == VAR_DECL
8366 && TREE_STATIC (t)
8367 && !DECL_EXTERNAL (t))
8368 varpool_node::finalize_decl (t);
8369 DECL_SAVED_TREE (child_fn) = NULL;
8370 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8371 gimple_set_body (child_fn, NULL);
8372 TREE_USED (block) = 1;
8374 /* Reset DECL_CONTEXT on function arguments. */
8375 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8376 DECL_CONTEXT (t) = child_fn;
8378 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8379 so that it can be moved to the child function. */
8380 gsi = gsi_last_bb (entry_bb);
8381 stmt = gsi_stmt (gsi);
8382 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
8383 && gimple_omp_target_kind (stmt)
8384 == GF_OMP_TARGET_KIND_REGION);
8385 gsi_remove (&gsi, true);
8386 e = split_block (entry_bb, stmt);
8387 entry_bb = e->dest;
8388 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8390 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8391 if (exit_bb)
8393 gsi = gsi_last_bb (exit_bb);
8394 gcc_assert (!gsi_end_p (gsi)
8395 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8396 stmt = gimple_build_return (NULL);
8397 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8398 gsi_remove (&gsi, true);
8401 /* Move the target region into CHILD_CFUN. */
8403 block = gimple_block (entry_stmt);
8405 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8406 if (exit_bb)
8407 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8408 /* When the OMP expansion process cannot guarantee an up-to-date
8409 loop tree arrange for the child function to fixup loops. */
8410 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8411 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8413 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8414 num = vec_safe_length (child_cfun->local_decls);
8415 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8417 t = (*child_cfun->local_decls)[srcidx];
8418 if (DECL_CONTEXT (t) == cfun->decl)
8419 continue;
8420 if (srcidx != dstidx)
8421 (*child_cfun->local_decls)[dstidx] = t;
8422 dstidx++;
8424 if (dstidx != num)
8425 vec_safe_truncate (child_cfun->local_decls, dstidx);
8427 /* Inform the callgraph about the new function. */
8428 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8429 cgraph_node::add_new_function (child_fn, true);
8431 #ifdef ENABLE_OFFLOADING
8432 /* Add the new function to the offload table. */
8433 vec_safe_push (offload_funcs, child_fn);
8434 #endif
8436 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8437 fixed in a following pass. */
8438 push_cfun (child_cfun);
8439 cgraph_edge::rebuild_edges ();
8441 #ifdef ENABLE_OFFLOADING
8442 /* Prevent IPA from removing child_fn as unreachable, since there are no
8443 refs from the parent function to child_fn in offload LTO mode. */
8444 struct cgraph_node *node = cgraph_node::get (child_fn);
8445 node->mark_force_output ();
8446 #endif
8448 /* Some EH regions might become dead, see PR34608. If
8449 pass_cleanup_cfg isn't the first pass to happen with the
8450 new child, these dead EH edges might cause problems.
8451 Clean them up now. */
8452 if (flag_exceptions)
8454 basic_block bb;
8455 bool changed = false;
8457 FOR_EACH_BB_FN (bb, cfun)
8458 changed |= gimple_purge_dead_eh_edges (bb);
8459 if (changed)
8460 cleanup_tree_cfg ();
8462 pop_cfun ();
8465 /* Emit a library call to launch the target region, or do data
8466 transfers. */
8467 tree t1, t2, t3, t4, device, cond, c, clauses;
8468 enum built_in_function start_ix;
8469 location_t clause_loc;
8471 clauses = gimple_omp_target_clauses (entry_stmt);
8473 if (kind == GF_OMP_TARGET_KIND_REGION)
8474 start_ix = BUILT_IN_GOMP_TARGET;
8475 else if (kind == GF_OMP_TARGET_KIND_DATA)
8476 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8477 else
8478 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8480 /* By default, the value of DEVICE is -1 (let runtime library choose)
8481 and there is no conditional. */
8482 cond = NULL_TREE;
8483 device = build_int_cst (integer_type_node, -1);
8485 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8486 if (c)
8487 cond = OMP_CLAUSE_IF_EXPR (c);
8489 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8490 if (c)
8492 device = OMP_CLAUSE_DEVICE_ID (c);
8493 clause_loc = OMP_CLAUSE_LOCATION (c);
8495 else
8496 clause_loc = gimple_location (entry_stmt);
8498 /* Ensure 'device' is of the correct type. */
8499 device = fold_convert_loc (clause_loc, integer_type_node, device);
8501 /* If we found the clause 'if (cond)', build
8502 (cond ? device : -2). */
8503 if (cond)
8505 cond = gimple_boolify (cond);
8507 basic_block cond_bb, then_bb, else_bb;
8508 edge e;
8509 tree tmp_var;
8511 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8512 if (kind != GF_OMP_TARGET_KIND_REGION)
8514 gsi = gsi_last_bb (new_bb);
8515 gsi_prev (&gsi);
8516 e = split_block (new_bb, gsi_stmt (gsi));
8518 else
8519 e = split_block (new_bb, NULL);
8520 cond_bb = e->src;
8521 new_bb = e->dest;
8522 remove_edge (e);
8524 then_bb = create_empty_bb (cond_bb);
8525 else_bb = create_empty_bb (then_bb);
8526 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8527 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8529 stmt = gimple_build_cond_empty (cond);
8530 gsi = gsi_last_bb (cond_bb);
8531 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8533 gsi = gsi_start_bb (then_bb);
8534 stmt = gimple_build_assign (tmp_var, device);
8535 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8537 gsi = gsi_start_bb (else_bb);
8538 stmt = gimple_build_assign (tmp_var,
8539 build_int_cst (integer_type_node, -2));
8540 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8542 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8543 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8544 add_bb_to_loop (then_bb, cond_bb->loop_father);
8545 add_bb_to_loop (else_bb, cond_bb->loop_father);
8546 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8547 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8549 device = tmp_var;
8552 gsi = gsi_last_bb (new_bb);
8553 t = gimple_omp_target_data_arg (entry_stmt);
8554 if (t == NULL)
8556 t1 = size_zero_node;
8557 t2 = build_zero_cst (ptr_type_node);
8558 t3 = t2;
8559 t4 = t2;
8561 else
8563 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8564 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8565 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8566 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8567 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8570 gimple g;
8571 /* FIXME: This will be address of
8572 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8573 symbol, as soon as the linker plugin is able to create it for us. */
8574 tree openmp_target = build_zero_cst (ptr_type_node);
8575 if (kind == GF_OMP_TARGET_KIND_REGION)
8577 tree fnaddr = build_fold_addr_expr (child_fn);
8578 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8579 device, fnaddr, openmp_target, t1, t2, t3, t4);
8581 else
8582 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8583 device, openmp_target, t1, t2, t3, t4);
8584 gimple_set_location (g, gimple_location (entry_stmt));
8585 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8586 if (kind != GF_OMP_TARGET_KIND_REGION)
8588 g = gsi_stmt (gsi);
8589 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8590 gsi_remove (&gsi, true);
8592 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8594 gsi = gsi_last_bb (region->exit);
8595 g = gsi_stmt (gsi);
8596 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8597 gsi_remove (&gsi, true);
8602 /* Expand the parallel region tree rooted at REGION. Expansion
8603 proceeds in depth-first order. Innermost regions are expanded
8604 first. This way, parallel regions that require a new function to
8605 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8606 internal dependencies in their body. */
8608 static void
8609 expand_omp (struct omp_region *region)
8611 while (region)
8613 location_t saved_location;
8614 gimple inner_stmt = NULL;
8616 /* First, determine whether this is a combined parallel+workshare
8617 region. */
8618 if (region->type == GIMPLE_OMP_PARALLEL)
8619 determine_parallel_type (region);
8621 if (region->type == GIMPLE_OMP_FOR
8622 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8623 inner_stmt = last_stmt (region->inner->entry);
8625 if (region->inner)
8626 expand_omp (region->inner);
8628 saved_location = input_location;
8629 if (gimple_has_location (last_stmt (region->entry)))
8630 input_location = gimple_location (last_stmt (region->entry));
8632 switch (region->type)
8634 case GIMPLE_OMP_PARALLEL:
8635 case GIMPLE_OMP_TASK:
8636 expand_omp_taskreg (region);
8637 break;
8639 case GIMPLE_OMP_FOR:
8640 expand_omp_for (region, inner_stmt);
8641 break;
8643 case GIMPLE_OMP_SECTIONS:
8644 expand_omp_sections (region);
8645 break;
8647 case GIMPLE_OMP_SECTION:
8648 /* Individual omp sections are handled together with their
8649 parent GIMPLE_OMP_SECTIONS region. */
8650 break;
8652 case GIMPLE_OMP_SINGLE:
8653 expand_omp_single (region);
8654 break;
8656 case GIMPLE_OMP_MASTER:
8657 case GIMPLE_OMP_TASKGROUP:
8658 case GIMPLE_OMP_ORDERED:
8659 case GIMPLE_OMP_CRITICAL:
8660 case GIMPLE_OMP_TEAMS:
8661 expand_omp_synch (region);
8662 break;
8664 case GIMPLE_OMP_ATOMIC_LOAD:
8665 expand_omp_atomic (region);
8666 break;
8668 case GIMPLE_OMP_TARGET:
8669 expand_omp_target (region);
8670 break;
8672 default:
8673 gcc_unreachable ();
8676 input_location = saved_location;
8677 region = region->next;
8682 /* Helper for build_omp_regions. Scan the dominator tree starting at
8683 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8684 true, the function ends once a single tree is built (otherwise, whole
8685 forest of OMP constructs may be built). */
8687 static void
8688 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8689 bool single_tree)
8691 gimple_stmt_iterator gsi;
8692 gimple stmt;
8693 basic_block son;
8695 gsi = gsi_last_bb (bb);
8696 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8698 struct omp_region *region;
8699 enum gimple_code code;
8701 stmt = gsi_stmt (gsi);
8702 code = gimple_code (stmt);
8703 if (code == GIMPLE_OMP_RETURN)
8705 /* STMT is the return point out of region PARENT. Mark it
8706 as the exit point and make PARENT the immediately
8707 enclosing region. */
8708 gcc_assert (parent);
8709 region = parent;
8710 region->exit = bb;
8711 parent = parent->outer;
8713 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8715 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8716 GIMPLE_OMP_RETURN, but matches with
8717 GIMPLE_OMP_ATOMIC_LOAD. */
8718 gcc_assert (parent);
8719 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8720 region = parent;
8721 region->exit = bb;
8722 parent = parent->outer;
8725 else if (code == GIMPLE_OMP_CONTINUE)
8727 gcc_assert (parent);
8728 parent->cont = bb;
8730 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8732 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8733 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8736 else if (code == GIMPLE_OMP_TARGET
8737 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8738 new_omp_region (bb, code, parent);
8739 else
8741 /* Otherwise, this directive becomes the parent for a new
8742 region. */
8743 region = new_omp_region (bb, code, parent);
8744 parent = region;
8748 if (single_tree && !parent)
8749 return;
8751 for (son = first_dom_son (CDI_DOMINATORS, bb);
8752 son;
8753 son = next_dom_son (CDI_DOMINATORS, son))
8754 build_omp_regions_1 (son, parent, single_tree);
8757 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8758 root_omp_region. */
8760 static void
8761 build_omp_regions_root (basic_block root)
8763 gcc_assert (root_omp_region == NULL);
8764 build_omp_regions_1 (root, NULL, true);
8765 gcc_assert (root_omp_region != NULL);
8768 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8770 void
8771 omp_expand_local (basic_block head)
8773 build_omp_regions_root (head);
8774 if (dump_file && (dump_flags & TDF_DETAILS))
8776 fprintf (dump_file, "\nOMP region tree\n\n");
8777 dump_omp_region (dump_file, root_omp_region, 0);
8778 fprintf (dump_file, "\n");
8781 remove_exit_barriers (root_omp_region);
8782 expand_omp (root_omp_region);
8784 free_omp_regions ();
8787 /* Scan the CFG and build a tree of OMP regions. Return the root of
8788 the OMP region tree. */
8790 static void
8791 build_omp_regions (void)
8793 gcc_assert (root_omp_region == NULL);
8794 calculate_dominance_info (CDI_DOMINATORS);
8795 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8798 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8800 static unsigned int
8801 execute_expand_omp (void)
8803 build_omp_regions ();
8805 if (!root_omp_region)
8806 return 0;
8808 if (dump_file)
8810 fprintf (dump_file, "\nOMP region tree\n\n");
8811 dump_omp_region (dump_file, root_omp_region, 0);
8812 fprintf (dump_file, "\n");
8815 remove_exit_barriers (root_omp_region);
8817 expand_omp (root_omp_region);
8819 cleanup_tree_cfg ();
8821 free_omp_regions ();
8823 return 0;
8826 /* OMP expansion -- the default pass, run before creation of SSA form. */
8828 namespace {
8830 const pass_data pass_data_expand_omp =
8832 GIMPLE_PASS, /* type */
8833 "ompexp", /* name */
8834 OPTGROUP_NONE, /* optinfo_flags */
8835 TV_NONE, /* tv_id */
8836 PROP_gimple_any, /* properties_required */
8837 PROP_gimple_eomp, /* properties_provided */
8838 0, /* properties_destroyed */
8839 0, /* todo_flags_start */
8840 0, /* todo_flags_finish */
8843 class pass_expand_omp : public gimple_opt_pass
8845 public:
8846 pass_expand_omp (gcc::context *ctxt)
8847 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8850 /* opt_pass methods: */
8851 virtual unsigned int execute (function *)
8853 bool gate = ((flag_openmp != 0 || flag_openmp_simd != 0
8854 || flag_cilkplus != 0) && !seen_error ());
8856 /* This pass always runs, to provide PROP_gimple_eomp.
8857 But there is nothing to do unless -fopenmp is given. */
8858 if (!gate)
8859 return 0;
8861 return execute_expand_omp ();
8864 }; // class pass_expand_omp
8866 } // anon namespace
8868 gimple_opt_pass *
8869 make_pass_expand_omp (gcc::context *ctxt)
8871 return new pass_expand_omp (ctxt);
8874 namespace {
8876 const pass_data pass_data_expand_omp_ssa =
8878 GIMPLE_PASS, /* type */
8879 "ompexpssa", /* name */
8880 OPTGROUP_NONE, /* optinfo_flags */
8881 TV_NONE, /* tv_id */
8882 PROP_cfg | PROP_ssa, /* properties_required */
8883 PROP_gimple_eomp, /* properties_provided */
8884 0, /* properties_destroyed */
8885 0, /* todo_flags_start */
8886 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
8889 class pass_expand_omp_ssa : public gimple_opt_pass
8891 public:
8892 pass_expand_omp_ssa (gcc::context *ctxt)
8893 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
8896 /* opt_pass methods: */
8897 virtual bool gate (function *fun)
8899 return !(fun->curr_properties & PROP_gimple_eomp);
8901 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8903 }; // class pass_expand_omp_ssa
8905 } // anon namespace
8907 gimple_opt_pass *
8908 make_pass_expand_omp_ssa (gcc::context *ctxt)
8910 return new pass_expand_omp_ssa (ctxt);
8913 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8915 /* If ctx is a worksharing context inside of a cancellable parallel
8916 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8917 and conditional branch to parallel's cancel_label to handle
8918 cancellation in the implicit barrier. */
8920 static void
8921 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8923 gimple omp_return = gimple_seq_last_stmt (*body);
8924 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8925 if (gimple_omp_return_nowait_p (omp_return))
8926 return;
8927 if (ctx->outer
8928 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8929 && ctx->outer->cancellable)
8931 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8932 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8933 tree lhs = create_tmp_var (c_bool_type, NULL);
8934 gimple_omp_return_set_lhs (omp_return, lhs);
8935 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8936 gimple g = gimple_build_cond (NE_EXPR, lhs,
8937 fold_convert (c_bool_type,
8938 boolean_false_node),
8939 ctx->outer->cancel_label, fallthru_label);
8940 gimple_seq_add_stmt (body, g);
8941 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8945 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8946 CTX is the enclosing OMP context for the current statement. */
8948 static void
8949 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8951 tree block, control;
8952 gimple_stmt_iterator tgsi;
8953 gomp_sections *stmt;
8954 gimple t;
8955 gbind *new_stmt, *bind;
8956 gimple_seq ilist, dlist, olist, new_body;
8958 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
8960 push_gimplify_context ();
8962 dlist = NULL;
8963 ilist = NULL;
8964 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8965 &ilist, &dlist, ctx, NULL);
8967 new_body = gimple_omp_body (stmt);
8968 gimple_omp_set_body (stmt, NULL);
8969 tgsi = gsi_start (new_body);
8970 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8972 omp_context *sctx;
8973 gimple sec_start;
8975 sec_start = gsi_stmt (tgsi);
8976 sctx = maybe_lookup_ctx (sec_start);
8977 gcc_assert (sctx);
8979 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8980 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8981 GSI_CONTINUE_LINKING);
8982 gimple_omp_set_body (sec_start, NULL);
8984 if (gsi_one_before_end_p (tgsi))
8986 gimple_seq l = NULL;
8987 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8988 &l, ctx);
8989 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8990 gimple_omp_section_set_last (sec_start);
8993 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8994 GSI_CONTINUE_LINKING);
8997 block = make_node (BLOCK);
8998 bind = gimple_build_bind (NULL, new_body, block);
9000 olist = NULL;
9001 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
9003 block = make_node (BLOCK);
9004 new_stmt = gimple_build_bind (NULL, NULL, block);
9005 gsi_replace (gsi_p, new_stmt, true);
9007 pop_gimplify_context (new_stmt);
9008 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9009 BLOCK_VARS (block) = gimple_bind_vars (bind);
9010 if (BLOCK_VARS (block))
9011 TREE_USED (block) = 1;
9013 new_body = NULL;
9014 gimple_seq_add_seq (&new_body, ilist);
9015 gimple_seq_add_stmt (&new_body, stmt);
9016 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
9017 gimple_seq_add_stmt (&new_body, bind);
9019 control = create_tmp_var (unsigned_type_node, ".section");
9020 t = gimple_build_omp_continue (control, control);
9021 gimple_omp_sections_set_control (stmt, control);
9022 gimple_seq_add_stmt (&new_body, t);
9024 gimple_seq_add_seq (&new_body, olist);
9025 if (ctx->cancellable)
9026 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9027 gimple_seq_add_seq (&new_body, dlist);
9029 new_body = maybe_catch_exception (new_body);
9031 t = gimple_build_omp_return
9032 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
9033 OMP_CLAUSE_NOWAIT));
9034 gimple_seq_add_stmt (&new_body, t);
9035 maybe_add_implicit_barrier_cancel (ctx, &new_body);
9037 gimple_bind_set_body (new_stmt, new_body);
9041 /* A subroutine of lower_omp_single. Expand the simple form of
9042 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
9044 if (GOMP_single_start ())
9045 BODY;
9046 [ GOMP_barrier (); ] -> unless 'nowait' is present.
9048 FIXME. It may be better to delay expanding the logic of this until
9049 pass_expand_omp. The expanded logic may make the job more difficult
9050 to a synchronization analysis pass. */
9052 static void
9053 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
9055 location_t loc = gimple_location (single_stmt);
9056 tree tlabel = create_artificial_label (loc);
9057 tree flabel = create_artificial_label (loc);
9058 gimple call, cond;
9059 tree lhs, decl;
9061 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
9062 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
9063 call = gimple_build_call (decl, 0);
9064 gimple_call_set_lhs (call, lhs);
9065 gimple_seq_add_stmt (pre_p, call);
9067 cond = gimple_build_cond (EQ_EXPR, lhs,
9068 fold_convert_loc (loc, TREE_TYPE (lhs),
9069 boolean_true_node),
9070 tlabel, flabel);
9071 gimple_seq_add_stmt (pre_p, cond);
9072 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
9073 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9074 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
9078 /* A subroutine of lower_omp_single. Expand the simple form of
9079 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
9081 #pragma omp single copyprivate (a, b, c)
9083 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
9086 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
9088 BODY;
9089 copyout.a = a;
9090 copyout.b = b;
9091 copyout.c = c;
9092 GOMP_single_copy_end (&copyout);
9094 else
9096 a = copyout_p->a;
9097 b = copyout_p->b;
9098 c = copyout_p->c;
9100 GOMP_barrier ();
9103 FIXME. It may be better to delay expanding the logic of this until
9104 pass_expand_omp. The expanded logic may make the job more difficult
9105 to a synchronization analysis pass. */
9107 static void
9108 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
9109 omp_context *ctx)
9111 tree ptr_type, t, l0, l1, l2, bfn_decl;
9112 gimple_seq copyin_seq;
9113 location_t loc = gimple_location (single_stmt);
9115 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
9117 ptr_type = build_pointer_type (ctx->record_type);
9118 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
9120 l0 = create_artificial_label (loc);
9121 l1 = create_artificial_label (loc);
9122 l2 = create_artificial_label (loc);
9124 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
9125 t = build_call_expr_loc (loc, bfn_decl, 0);
9126 t = fold_convert_loc (loc, ptr_type, t);
9127 gimplify_assign (ctx->receiver_decl, t, pre_p);
9129 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
9130 build_int_cst (ptr_type, 0));
9131 t = build3 (COND_EXPR, void_type_node, t,
9132 build_and_jump (&l0), build_and_jump (&l1));
9133 gimplify_and_add (t, pre_p);
9135 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
9137 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9139 copyin_seq = NULL;
9140 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
9141 &copyin_seq, ctx);
9143 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9144 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
9145 t = build_call_expr_loc (loc, bfn_decl, 1, t);
9146 gimplify_and_add (t, pre_p);
9148 t = build_and_jump (&l2);
9149 gimplify_and_add (t, pre_p);
9151 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
9153 gimple_seq_add_seq (pre_p, copyin_seq);
9155 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
9159 /* Expand code for an OpenMP single directive. */
9161 static void
9162 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9164 tree block;
9165 gimple t;
9166 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
9167 gbind *bind;
9168 gimple_seq bind_body, bind_body_tail = NULL, dlist;
9170 push_gimplify_context ();
9172 block = make_node (BLOCK);
9173 bind = gimple_build_bind (NULL, NULL, block);
9174 gsi_replace (gsi_p, bind, true);
9175 bind_body = NULL;
9176 dlist = NULL;
9177 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
9178 &bind_body, &dlist, ctx, NULL);
9179 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
9181 gimple_seq_add_stmt (&bind_body, single_stmt);
9183 if (ctx->record_type)
9184 lower_omp_single_copy (single_stmt, &bind_body, ctx);
9185 else
9186 lower_omp_single_simple (single_stmt, &bind_body);
9188 gimple_omp_set_body (single_stmt, NULL);
9190 gimple_seq_add_seq (&bind_body, dlist);
9192 bind_body = maybe_catch_exception (bind_body);
9194 t = gimple_build_omp_return
9195 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
9196 OMP_CLAUSE_NOWAIT));
9197 gimple_seq_add_stmt (&bind_body_tail, t);
9198 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
9199 if (ctx->record_type)
9201 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9202 tree clobber = build_constructor (ctx->record_type, NULL);
9203 TREE_THIS_VOLATILE (clobber) = 1;
9204 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9205 clobber), GSI_SAME_STMT);
9207 gimple_seq_add_seq (&bind_body, bind_body_tail);
9208 gimple_bind_set_body (bind, bind_body);
9210 pop_gimplify_context (bind);
9212 gimple_bind_append_vars (bind, ctx->block_vars);
9213 BLOCK_VARS (block) = ctx->block_vars;
9214 if (BLOCK_VARS (block))
9215 TREE_USED (block) = 1;
9219 /* Expand code for an OpenMP master directive. */
9221 static void
9222 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9224 tree block, lab = NULL, x, bfn_decl;
9225 gimple stmt = gsi_stmt (*gsi_p);
9226 gbind *bind;
9227 location_t loc = gimple_location (stmt);
9228 gimple_seq tseq;
9230 push_gimplify_context ();
9232 block = make_node (BLOCK);
9233 bind = gimple_build_bind (NULL, NULL, block);
9234 gsi_replace (gsi_p, bind, true);
9235 gimple_bind_add_stmt (bind, stmt);
9237 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9238 x = build_call_expr_loc (loc, bfn_decl, 0);
9239 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
9240 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9241 tseq = NULL;
9242 gimplify_and_add (x, &tseq);
9243 gimple_bind_add_seq (bind, tseq);
9245 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9246 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9247 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9248 gimple_omp_set_body (stmt, NULL);
9250 gimple_bind_add_stmt (bind, gimple_build_label (lab));
9252 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9254 pop_gimplify_context (bind);
9256 gimple_bind_append_vars (bind, ctx->block_vars);
9257 BLOCK_VARS (block) = ctx->block_vars;
9261 /* Expand code for an OpenMP taskgroup directive. */
9263 static void
9264 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9266 gimple stmt = gsi_stmt (*gsi_p);
9267 gcall *x;
9268 gbind *bind;
9269 tree block = make_node (BLOCK);
9271 bind = gimple_build_bind (NULL, NULL, block);
9272 gsi_replace (gsi_p, bind, true);
9273 gimple_bind_add_stmt (bind, stmt);
9275 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9277 gimple_bind_add_stmt (bind, x);
9279 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9280 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9281 gimple_omp_set_body (stmt, NULL);
9283 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9285 gimple_bind_append_vars (bind, ctx->block_vars);
9286 BLOCK_VARS (block) = ctx->block_vars;
9290 /* Expand code for an OpenMP ordered directive. */
9292 static void
9293 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9295 tree block;
9296 gimple stmt = gsi_stmt (*gsi_p);
9297 gcall *x;
9298 gbind *bind;
9300 push_gimplify_context ();
9302 block = make_node (BLOCK);
9303 bind = gimple_build_bind (NULL, NULL, block);
9304 gsi_replace (gsi_p, bind, true);
9305 gimple_bind_add_stmt (bind, stmt);
9307 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
9309 gimple_bind_add_stmt (bind, x);
9311 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9312 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9313 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9314 gimple_omp_set_body (stmt, NULL);
9316 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
9317 gimple_bind_add_stmt (bind, x);
9319 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9321 pop_gimplify_context (bind);
9323 gimple_bind_append_vars (bind, ctx->block_vars);
9324 BLOCK_VARS (block) = gimple_bind_vars (bind);
9328 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9329 substitution of a couple of function calls. But in the NAMED case,
9330 requires that languages coordinate a symbol name. It is therefore
9331 best put here in common code. */
9333 static GTY((param1_is (tree), param2_is (tree)))
9334 splay_tree critical_name_mutexes;
9336 static void
9337 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9339 tree block;
9340 tree name, lock, unlock;
9341 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
9342 gbind *bind;
9343 location_t loc = gimple_location (stmt);
9344 gimple_seq tbody;
9346 name = gimple_omp_critical_name (stmt);
9347 if (name)
9349 tree decl;
9350 splay_tree_node n;
9352 if (!critical_name_mutexes)
9353 critical_name_mutexes
9354 = splay_tree_new_ggc (splay_tree_compare_pointers,
9355 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
9356 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
9358 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
9359 if (n == NULL)
9361 char *new_str;
9363 decl = create_tmp_var_raw (ptr_type_node, NULL);
9365 new_str = ACONCAT ((".gomp_critical_user_",
9366 IDENTIFIER_POINTER (name), NULL));
9367 DECL_NAME (decl) = get_identifier (new_str);
9368 TREE_PUBLIC (decl) = 1;
9369 TREE_STATIC (decl) = 1;
9370 DECL_COMMON (decl) = 1;
9371 DECL_ARTIFICIAL (decl) = 1;
9372 DECL_IGNORED_P (decl) = 1;
9374 /* If '#pragma omp critical' is inside target region, the symbol must
9375 be marked for offloading. */
9376 omp_context *octx;
9377 for (octx = ctx->outer; octx; octx = octx->outer)
9378 if (is_targetreg_ctx (octx))
9380 varpool_node::get_create (decl)->offloadable = 1;
9381 break;
9384 varpool_node::finalize_decl (decl);
9386 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
9387 (splay_tree_value) decl);
9389 else
9390 decl = (tree) n->value;
9392 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
9393 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
9395 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
9396 unlock = build_call_expr_loc (loc, unlock, 1,
9397 build_fold_addr_expr_loc (loc, decl));
9399 else
9401 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
9402 lock = build_call_expr_loc (loc, lock, 0);
9404 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
9405 unlock = build_call_expr_loc (loc, unlock, 0);
9408 push_gimplify_context ();
9410 block = make_node (BLOCK);
9411 bind = gimple_build_bind (NULL, NULL, block);
9412 gsi_replace (gsi_p, bind, true);
9413 gimple_bind_add_stmt (bind, stmt);
9415 tbody = gimple_bind_body (bind);
9416 gimplify_and_add (lock, &tbody);
9417 gimple_bind_set_body (bind, tbody);
9419 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9420 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9421 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9422 gimple_omp_set_body (stmt, NULL);
9424 tbody = gimple_bind_body (bind);
9425 gimplify_and_add (unlock, &tbody);
9426 gimple_bind_set_body (bind, tbody);
9428 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9430 pop_gimplify_context (bind);
9431 gimple_bind_append_vars (bind, ctx->block_vars);
9432 BLOCK_VARS (block) = gimple_bind_vars (bind);
9436 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9437 for a lastprivate clause. Given a loop control predicate of (V
9438 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9439 is appended to *DLIST, iterator initialization is appended to
9440 *BODY_P. */
9442 static void
9443 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
9444 gimple_seq *dlist, struct omp_context *ctx)
9446 tree clauses, cond, vinit;
9447 enum tree_code cond_code;
9448 gimple_seq stmts;
9450 cond_code = fd->loop.cond_code;
9451 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
9453 /* When possible, use a strict equality expression. This can let VRP
9454 type optimizations deduce the value and remove a copy. */
9455 if (tree_fits_shwi_p (fd->loop.step))
9457 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
9458 if (step == 1 || step == -1)
9459 cond_code = EQ_EXPR;
9462 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
9464 clauses = gimple_omp_for_clauses (fd->for_stmt);
9465 stmts = NULL;
9466 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
9467 if (!gimple_seq_empty_p (stmts))
9469 gimple_seq_add_seq (&stmts, *dlist);
9470 *dlist = stmts;
9472 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9473 vinit = fd->loop.n1;
9474 if (cond_code == EQ_EXPR
9475 && tree_fits_shwi_p (fd->loop.n2)
9476 && ! integer_zerop (fd->loop.n2))
9477 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
9478 else
9479 vinit = unshare_expr (vinit);
9481 /* Initialize the iterator variable, so that threads that don't execute
9482 any iterations don't execute the lastprivate clauses by accident. */
9483 gimplify_assign (fd->loop.v, vinit, body_p);
9488 /* Lower code for an OpenMP loop directive. */
9490 static void
9491 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9493 tree *rhs_p, block;
9494 struct omp_for_data fd, *fdp = NULL;
9495 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
9496 gbind *new_stmt;
9497 gimple_seq omp_for_body, body, dlist;
9498 size_t i;
9500 push_gimplify_context ();
9502 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
9504 block = make_node (BLOCK);
9505 new_stmt = gimple_build_bind (NULL, NULL, block);
9506 /* Replace at gsi right away, so that 'stmt' is no member
9507 of a sequence anymore as we're going to add to to a different
9508 one below. */
9509 gsi_replace (gsi_p, new_stmt, true);
9511 /* Move declaration of temporaries in the loop body before we make
9512 it go away. */
9513 omp_for_body = gimple_omp_body (stmt);
9514 if (!gimple_seq_empty_p (omp_for_body)
9515 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9517 gbind *inner_bind
9518 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
9519 tree vars = gimple_bind_vars (inner_bind);
9520 gimple_bind_append_vars (new_stmt, vars);
9521 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9522 keep them on the inner_bind and it's block. */
9523 gimple_bind_set_vars (inner_bind, NULL_TREE);
9524 if (gimple_bind_block (inner_bind))
9525 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9528 if (gimple_omp_for_combined_into_p (stmt))
9530 extract_omp_for_data (stmt, &fd, NULL);
9531 fdp = &fd;
9533 /* We need two temporaries with fd.loop.v type (istart/iend)
9534 and then (fd.collapse - 1) temporaries with the same
9535 type for count2 ... countN-1 vars if not constant. */
9536 size_t count = 2;
9537 tree type = fd.iter_type;
9538 if (fd.collapse > 1
9539 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9540 count += fd.collapse - 1;
9541 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9542 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9543 tree clauses = *pc;
9544 if (parallel_for)
9545 outerc
9546 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9547 OMP_CLAUSE__LOOPTEMP_);
9548 for (i = 0; i < count; i++)
9550 tree temp;
9551 if (parallel_for)
9553 gcc_assert (outerc);
9554 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9555 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9556 OMP_CLAUSE__LOOPTEMP_);
9558 else
9560 temp = create_tmp_var (type, NULL);
9561 insert_decl_map (&ctx->outer->cb, temp, temp);
9563 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9564 OMP_CLAUSE_DECL (*pc) = temp;
9565 pc = &OMP_CLAUSE_CHAIN (*pc);
9567 *pc = clauses;
9570 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9571 dlist = NULL;
9572 body = NULL;
9573 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9574 fdp);
9575 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9577 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9579 /* Lower the header expressions. At this point, we can assume that
9580 the header is of the form:
9582 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9584 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9585 using the .omp_data_s mapping, if needed. */
9586 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9588 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9589 if (!is_gimple_min_invariant (*rhs_p))
9590 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9592 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9593 if (!is_gimple_min_invariant (*rhs_p))
9594 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9596 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9597 if (!is_gimple_min_invariant (*rhs_p))
9598 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9601 /* Once lowered, extract the bounds and clauses. */
9602 extract_omp_for_data (stmt, &fd, NULL);
9604 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9606 gimple_seq_add_stmt (&body, stmt);
9607 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9609 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9610 fd.loop.v));
9612 /* After the loop, add exit clauses. */
9613 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9615 if (ctx->cancellable)
9616 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9618 gimple_seq_add_seq (&body, dlist);
9620 body = maybe_catch_exception (body);
9622 /* Region exit marker goes at the end of the loop body. */
9623 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9624 maybe_add_implicit_barrier_cancel (ctx, &body);
9625 pop_gimplify_context (new_stmt);
9627 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9628 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9629 if (BLOCK_VARS (block))
9630 TREE_USED (block) = 1;
9632 gimple_bind_set_body (new_stmt, body);
9633 gimple_omp_set_body (stmt, NULL);
9634 gimple_omp_for_set_pre_body (stmt, NULL);
9637 /* Callback for walk_stmts. Check if the current statement only contains
9638 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9640 static tree
9641 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9642 bool *handled_ops_p,
9643 struct walk_stmt_info *wi)
9645 int *info = (int *) wi->info;
9646 gimple stmt = gsi_stmt (*gsi_p);
9648 *handled_ops_p = true;
9649 switch (gimple_code (stmt))
9651 WALK_SUBSTMTS;
9653 case GIMPLE_OMP_FOR:
9654 case GIMPLE_OMP_SECTIONS:
9655 *info = *info == 0 ? 1 : -1;
9656 break;
9657 default:
9658 *info = -1;
9659 break;
9661 return NULL;
9664 struct omp_taskcopy_context
9666 /* This field must be at the beginning, as we do "inheritance": Some
9667 callback functions for tree-inline.c (e.g., omp_copy_decl)
9668 receive a copy_body_data pointer that is up-casted to an
9669 omp_context pointer. */
9670 copy_body_data cb;
9671 omp_context *ctx;
9674 static tree
9675 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9677 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9679 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9680 return create_tmp_var (TREE_TYPE (var), NULL);
9682 return var;
9685 static tree
9686 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9688 tree name, new_fields = NULL, type, f;
9690 type = lang_hooks.types.make_type (RECORD_TYPE);
9691 name = DECL_NAME (TYPE_NAME (orig_type));
9692 name = build_decl (gimple_location (tcctx->ctx->stmt),
9693 TYPE_DECL, name, type);
9694 TYPE_NAME (type) = name;
9696 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9698 tree new_f = copy_node (f);
9699 DECL_CONTEXT (new_f) = type;
9700 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9701 TREE_CHAIN (new_f) = new_fields;
9702 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9703 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9704 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9705 &tcctx->cb, NULL);
9706 new_fields = new_f;
9707 tcctx->cb.decl_map->put (f, new_f);
9709 TYPE_FIELDS (type) = nreverse (new_fields);
9710 layout_type (type);
9711 return type;
9714 /* Create task copyfn. */
9716 static void
9717 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
9719 struct function *child_cfun;
9720 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9721 tree record_type, srecord_type, bind, list;
9722 bool record_needs_remap = false, srecord_needs_remap = false;
9723 splay_tree_node n;
9724 struct omp_taskcopy_context tcctx;
9725 location_t loc = gimple_location (task_stmt);
9727 child_fn = gimple_omp_task_copy_fn (task_stmt);
9728 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9729 gcc_assert (child_cfun->cfg == NULL);
9730 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9732 /* Reset DECL_CONTEXT on function arguments. */
9733 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9734 DECL_CONTEXT (t) = child_fn;
9736 /* Populate the function. */
9737 push_gimplify_context ();
9738 push_cfun (child_cfun);
9740 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9741 TREE_SIDE_EFFECTS (bind) = 1;
9742 list = NULL;
9743 DECL_SAVED_TREE (child_fn) = bind;
9744 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9746 /* Remap src and dst argument types if needed. */
9747 record_type = ctx->record_type;
9748 srecord_type = ctx->srecord_type;
9749 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9750 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9752 record_needs_remap = true;
9753 break;
9755 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9756 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9758 srecord_needs_remap = true;
9759 break;
9762 if (record_needs_remap || srecord_needs_remap)
9764 memset (&tcctx, '\0', sizeof (tcctx));
9765 tcctx.cb.src_fn = ctx->cb.src_fn;
9766 tcctx.cb.dst_fn = child_fn;
9767 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
9768 gcc_checking_assert (tcctx.cb.src_node);
9769 tcctx.cb.dst_node = tcctx.cb.src_node;
9770 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9771 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9772 tcctx.cb.eh_lp_nr = 0;
9773 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9774 tcctx.cb.decl_map = new hash_map<tree, tree>;
9775 tcctx.ctx = ctx;
9777 if (record_needs_remap)
9778 record_type = task_copyfn_remap_type (&tcctx, record_type);
9779 if (srecord_needs_remap)
9780 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9782 else
9783 tcctx.cb.decl_map = NULL;
9785 arg = DECL_ARGUMENTS (child_fn);
9786 TREE_TYPE (arg) = build_pointer_type (record_type);
9787 sarg = DECL_CHAIN (arg);
9788 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9790 /* First pass: initialize temporaries used in record_type and srecord_type
9791 sizes and field offsets. */
9792 if (tcctx.cb.decl_map)
9793 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9794 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9796 tree *p;
9798 decl = OMP_CLAUSE_DECL (c);
9799 p = tcctx.cb.decl_map->get (decl);
9800 if (p == NULL)
9801 continue;
9802 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9803 sf = (tree) n->value;
9804 sf = *tcctx.cb.decl_map->get (sf);
9805 src = build_simple_mem_ref_loc (loc, sarg);
9806 src = omp_build_component_ref (src, sf);
9807 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9808 append_to_statement_list (t, &list);
9811 /* Second pass: copy shared var pointers and copy construct non-VLA
9812 firstprivate vars. */
9813 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9814 switch (OMP_CLAUSE_CODE (c))
9816 case OMP_CLAUSE_SHARED:
9817 decl = OMP_CLAUSE_DECL (c);
9818 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9819 if (n == NULL)
9820 break;
9821 f = (tree) n->value;
9822 if (tcctx.cb.decl_map)
9823 f = *tcctx.cb.decl_map->get (f);
9824 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9825 sf = (tree) n->value;
9826 if (tcctx.cb.decl_map)
9827 sf = *tcctx.cb.decl_map->get (sf);
9828 src = build_simple_mem_ref_loc (loc, sarg);
9829 src = omp_build_component_ref (src, sf);
9830 dst = build_simple_mem_ref_loc (loc, arg);
9831 dst = omp_build_component_ref (dst, f);
9832 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9833 append_to_statement_list (t, &list);
9834 break;
9835 case OMP_CLAUSE_FIRSTPRIVATE:
9836 decl = OMP_CLAUSE_DECL (c);
9837 if (is_variable_sized (decl))
9838 break;
9839 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9840 if (n == NULL)
9841 break;
9842 f = (tree) n->value;
9843 if (tcctx.cb.decl_map)
9844 f = *tcctx.cb.decl_map->get (f);
9845 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9846 if (n != NULL)
9848 sf = (tree) n->value;
9849 if (tcctx.cb.decl_map)
9850 sf = *tcctx.cb.decl_map->get (sf);
9851 src = build_simple_mem_ref_loc (loc, sarg);
9852 src = omp_build_component_ref (src, sf);
9853 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9854 src = build_simple_mem_ref_loc (loc, src);
9856 else
9857 src = decl;
9858 dst = build_simple_mem_ref_loc (loc, arg);
9859 dst = omp_build_component_ref (dst, f);
9860 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9861 append_to_statement_list (t, &list);
9862 break;
9863 case OMP_CLAUSE_PRIVATE:
9864 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9865 break;
9866 decl = OMP_CLAUSE_DECL (c);
9867 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9868 f = (tree) n->value;
9869 if (tcctx.cb.decl_map)
9870 f = *tcctx.cb.decl_map->get (f);
9871 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9872 if (n != NULL)
9874 sf = (tree) n->value;
9875 if (tcctx.cb.decl_map)
9876 sf = *tcctx.cb.decl_map->get (sf);
9877 src = build_simple_mem_ref_loc (loc, sarg);
9878 src = omp_build_component_ref (src, sf);
9879 if (use_pointer_for_field (decl, NULL))
9880 src = build_simple_mem_ref_loc (loc, src);
9882 else
9883 src = decl;
9884 dst = build_simple_mem_ref_loc (loc, arg);
9885 dst = omp_build_component_ref (dst, f);
9886 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9887 append_to_statement_list (t, &list);
9888 break;
9889 default:
9890 break;
9893 /* Last pass: handle VLA firstprivates. */
9894 if (tcctx.cb.decl_map)
9895 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9896 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9898 tree ind, ptr, df;
9900 decl = OMP_CLAUSE_DECL (c);
9901 if (!is_variable_sized (decl))
9902 continue;
9903 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9904 if (n == NULL)
9905 continue;
9906 f = (tree) n->value;
9907 f = *tcctx.cb.decl_map->get (f);
9908 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9909 ind = DECL_VALUE_EXPR (decl);
9910 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9911 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9912 n = splay_tree_lookup (ctx->sfield_map,
9913 (splay_tree_key) TREE_OPERAND (ind, 0));
9914 sf = (tree) n->value;
9915 sf = *tcctx.cb.decl_map->get (sf);
9916 src = build_simple_mem_ref_loc (loc, sarg);
9917 src = omp_build_component_ref (src, sf);
9918 src = build_simple_mem_ref_loc (loc, src);
9919 dst = build_simple_mem_ref_loc (loc, arg);
9920 dst = omp_build_component_ref (dst, f);
9921 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9922 append_to_statement_list (t, &list);
9923 n = splay_tree_lookup (ctx->field_map,
9924 (splay_tree_key) TREE_OPERAND (ind, 0));
9925 df = (tree) n->value;
9926 df = *tcctx.cb.decl_map->get (df);
9927 ptr = build_simple_mem_ref_loc (loc, arg);
9928 ptr = omp_build_component_ref (ptr, df);
9929 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9930 build_fold_addr_expr_loc (loc, dst));
9931 append_to_statement_list (t, &list);
9934 t = build1 (RETURN_EXPR, void_type_node, NULL);
9935 append_to_statement_list (t, &list);
9937 if (tcctx.cb.decl_map)
9938 delete tcctx.cb.decl_map;
9939 pop_gimplify_context (NULL);
9940 BIND_EXPR_BODY (bind) = list;
9941 pop_cfun ();
9944 static void
9945 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9947 tree c, clauses;
9948 gimple g;
9949 size_t n_in = 0, n_out = 0, idx = 2, i;
9951 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9952 OMP_CLAUSE_DEPEND);
9953 gcc_assert (clauses);
9954 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9955 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9956 switch (OMP_CLAUSE_DEPEND_KIND (c))
9958 case OMP_CLAUSE_DEPEND_IN:
9959 n_in++;
9960 break;
9961 case OMP_CLAUSE_DEPEND_OUT:
9962 case OMP_CLAUSE_DEPEND_INOUT:
9963 n_out++;
9964 break;
9965 default:
9966 gcc_unreachable ();
9968 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9969 tree array = create_tmp_var (type, NULL);
9970 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9971 NULL_TREE);
9972 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9973 gimple_seq_add_stmt (iseq, g);
9974 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9975 NULL_TREE);
9976 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9977 gimple_seq_add_stmt (iseq, g);
9978 for (i = 0; i < 2; i++)
9980 if ((i ? n_in : n_out) == 0)
9981 continue;
9982 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9983 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9984 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9986 tree t = OMP_CLAUSE_DECL (c);
9987 t = fold_convert (ptr_type_node, t);
9988 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9989 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9990 NULL_TREE, NULL_TREE);
9991 g = gimple_build_assign (r, t);
9992 gimple_seq_add_stmt (iseq, g);
9995 tree *p = gimple_omp_task_clauses_ptr (stmt);
9996 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9997 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9998 OMP_CLAUSE_CHAIN (c) = *p;
9999 *p = c;
10000 tree clobber = build_constructor (type, NULL);
10001 TREE_THIS_VOLATILE (clobber) = 1;
10002 g = gimple_build_assign (array, clobber);
10003 gimple_seq_add_stmt (oseq, g);
10006 /* Lower the OpenMP parallel or task directive in the current statement
10007 in GSI_P. CTX holds context information for the directive. */
10009 static void
10010 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10012 tree clauses;
10013 tree child_fn, t;
10014 gimple stmt = gsi_stmt (*gsi_p);
10015 gbind *par_bind, *bind, *dep_bind = NULL;
10016 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
10017 location_t loc = gimple_location (stmt);
10019 clauses = gimple_omp_taskreg_clauses (stmt);
10020 par_bind
10021 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
10022 par_body = gimple_bind_body (par_bind);
10023 child_fn = ctx->cb.dst_fn;
10024 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
10025 && !gimple_omp_parallel_combined_p (stmt))
10027 struct walk_stmt_info wi;
10028 int ws_num = 0;
10030 memset (&wi, 0, sizeof (wi));
10031 wi.info = &ws_num;
10032 wi.val_only = true;
10033 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
10034 if (ws_num == 1)
10035 gimple_omp_parallel_set_combined_p (stmt, true);
10037 gimple_seq dep_ilist = NULL;
10038 gimple_seq dep_olist = NULL;
10039 if (gimple_code (stmt) == GIMPLE_OMP_TASK
10040 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
10042 push_gimplify_context ();
10043 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
10044 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
10047 if (ctx->srecord_type)
10048 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
10050 push_gimplify_context ();
10052 par_olist = NULL;
10053 par_ilist = NULL;
10054 par_rlist = NULL;
10055 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
10056 lower_omp (&par_body, ctx);
10057 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
10058 lower_reduction_clauses (clauses, &par_rlist, ctx);
10060 /* Declare all the variables created by mapping and the variables
10061 declared in the scope of the parallel body. */
10062 record_vars_into (ctx->block_vars, child_fn);
10063 record_vars_into (gimple_bind_vars (par_bind), child_fn);
10065 if (ctx->record_type)
10067 ctx->sender_decl
10068 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
10069 : ctx->record_type, ".omp_data_o");
10070 DECL_NAMELESS (ctx->sender_decl) = 1;
10071 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10072 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
10075 olist = NULL;
10076 ilist = NULL;
10077 lower_send_clauses (clauses, &ilist, &olist, ctx);
10078 lower_send_shared_vars (&ilist, &olist, ctx);
10080 if (ctx->record_type)
10082 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
10083 TREE_THIS_VOLATILE (clobber) = 1;
10084 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10085 clobber));
10088 /* Once all the expansions are done, sequence all the different
10089 fragments inside gimple_omp_body. */
10091 new_body = NULL;
10093 if (ctx->record_type)
10095 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10096 /* fixup_child_record_type might have changed receiver_decl's type. */
10097 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10098 gimple_seq_add_stmt (&new_body,
10099 gimple_build_assign (ctx->receiver_decl, t));
10102 gimple_seq_add_seq (&new_body, par_ilist);
10103 gimple_seq_add_seq (&new_body, par_body);
10104 gimple_seq_add_seq (&new_body, par_rlist);
10105 if (ctx->cancellable)
10106 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10107 gimple_seq_add_seq (&new_body, par_olist);
10108 new_body = maybe_catch_exception (new_body);
10109 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10110 gimple_omp_set_body (stmt, new_body);
10112 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
10113 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
10114 gimple_bind_add_seq (bind, ilist);
10115 gimple_bind_add_stmt (bind, stmt);
10116 gimple_bind_add_seq (bind, olist);
10118 pop_gimplify_context (NULL);
10120 if (dep_bind)
10122 gimple_bind_add_seq (dep_bind, dep_ilist);
10123 gimple_bind_add_stmt (dep_bind, bind);
10124 gimple_bind_add_seq (dep_bind, dep_olist);
10125 pop_gimplify_context (dep_bind);
10129 /* Lower the OpenMP target directive in the current statement
10130 in GSI_P. CTX holds context information for the directive. */
10132 static void
10133 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10135 tree clauses;
10136 tree child_fn, t, c;
10137 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
10138 gbind *tgt_bind = NULL, *bind;
10139 gimple_seq tgt_body = NULL, olist, ilist, new_body;
10140 location_t loc = gimple_location (stmt);
10141 int kind = gimple_omp_target_kind (stmt);
10142 unsigned int map_cnt = 0;
10144 clauses = gimple_omp_target_clauses (stmt);
10145 if (kind == GF_OMP_TARGET_KIND_REGION)
10147 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
10148 tgt_body = gimple_bind_body (tgt_bind);
10150 else if (kind == GF_OMP_TARGET_KIND_DATA)
10151 tgt_body = gimple_omp_body (stmt);
10152 child_fn = ctx->cb.dst_fn;
10154 push_gimplify_context ();
10156 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10157 switch (OMP_CLAUSE_CODE (c))
10159 tree var, x;
10161 default:
10162 break;
10163 case OMP_CLAUSE_MAP:
10164 case OMP_CLAUSE_TO:
10165 case OMP_CLAUSE_FROM:
10166 var = OMP_CLAUSE_DECL (c);
10167 if (!DECL_P (var))
10169 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10170 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10171 map_cnt++;
10172 continue;
10175 if (DECL_SIZE (var)
10176 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
10178 tree var2 = DECL_VALUE_EXPR (var);
10179 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
10180 var2 = TREE_OPERAND (var2, 0);
10181 gcc_assert (DECL_P (var2));
10182 var = var2;
10185 if (!maybe_lookup_field (var, ctx))
10186 continue;
10188 if (kind == GF_OMP_TARGET_KIND_REGION)
10190 x = build_receiver_ref (var, true, ctx);
10191 tree new_var = lookup_decl (var, ctx);
10192 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10193 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10194 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10195 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
10196 x = build_simple_mem_ref (x);
10197 SET_DECL_VALUE_EXPR (new_var, x);
10198 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
10200 map_cnt++;
10203 if (kind == GF_OMP_TARGET_KIND_REGION)
10205 target_nesting_level++;
10206 lower_omp (&tgt_body, ctx);
10207 target_nesting_level--;
10209 else if (kind == GF_OMP_TARGET_KIND_DATA)
10210 lower_omp (&tgt_body, ctx);
10212 if (kind == GF_OMP_TARGET_KIND_REGION)
10214 /* Declare all the variables created by mapping and the variables
10215 declared in the scope of the target body. */
10216 record_vars_into (ctx->block_vars, child_fn);
10217 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
10220 olist = NULL;
10221 ilist = NULL;
10222 if (ctx->record_type)
10224 ctx->sender_decl
10225 = create_tmp_var (ctx->record_type, ".omp_data_arr");
10226 DECL_NAMELESS (ctx->sender_decl) = 1;
10227 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10228 t = make_tree_vec (3);
10229 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
10230 TREE_VEC_ELT (t, 1)
10231 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
10232 ".omp_data_sizes");
10233 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
10234 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
10235 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
10236 TREE_VEC_ELT (t, 2)
10237 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
10238 map_cnt),
10239 ".omp_data_kinds");
10240 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
10241 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
10242 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
10243 gimple_omp_target_set_data_arg (stmt, t);
10245 vec<constructor_elt, va_gc> *vsize;
10246 vec<constructor_elt, va_gc> *vkind;
10247 vec_alloc (vsize, map_cnt);
10248 vec_alloc (vkind, map_cnt);
10249 unsigned int map_idx = 0;
10251 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10252 switch (OMP_CLAUSE_CODE (c))
10254 tree ovar, nc;
10256 default:
10257 break;
10258 case OMP_CLAUSE_MAP:
10259 case OMP_CLAUSE_TO:
10260 case OMP_CLAUSE_FROM:
10261 nc = c;
10262 ovar = OMP_CLAUSE_DECL (c);
10263 if (!DECL_P (ovar))
10265 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10266 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10268 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
10269 == get_base_address (ovar));
10270 nc = OMP_CLAUSE_CHAIN (c);
10271 ovar = OMP_CLAUSE_DECL (nc);
10273 else
10275 tree x = build_sender_ref (ovar, ctx);
10276 tree v
10277 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
10278 gimplify_assign (x, v, &ilist);
10279 nc = NULL_TREE;
10282 else
10284 if (DECL_SIZE (ovar)
10285 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
10287 tree ovar2 = DECL_VALUE_EXPR (ovar);
10288 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
10289 ovar2 = TREE_OPERAND (ovar2, 0);
10290 gcc_assert (DECL_P (ovar2));
10291 ovar = ovar2;
10293 if (!maybe_lookup_field (ovar, ctx))
10294 continue;
10297 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
10298 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
10299 talign = DECL_ALIGN_UNIT (ovar);
10300 if (nc)
10302 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
10303 tree x = build_sender_ref (ovar, ctx);
10304 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10305 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10306 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10307 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
10309 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10310 tree avar
10311 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
10312 mark_addressable (avar);
10313 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
10314 talign = DECL_ALIGN_UNIT (avar);
10315 avar = build_fold_addr_expr (avar);
10316 gimplify_assign (x, avar, &ilist);
10318 else if (is_gimple_reg (var))
10320 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10321 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
10322 mark_addressable (avar);
10323 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
10324 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
10325 gimplify_assign (avar, var, &ilist);
10326 avar = build_fold_addr_expr (avar);
10327 gimplify_assign (x, avar, &ilist);
10328 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
10329 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
10330 && !TYPE_READONLY (TREE_TYPE (var)))
10332 x = build_sender_ref (ovar, ctx);
10333 x = build_simple_mem_ref (x);
10334 gimplify_assign (var, x, &olist);
10337 else
10339 var = build_fold_addr_expr (var);
10340 gimplify_assign (x, var, &ilist);
10343 tree s = OMP_CLAUSE_SIZE (c);
10344 if (s == NULL_TREE)
10345 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
10346 s = fold_convert (size_type_node, s);
10347 tree purpose = size_int (map_idx++);
10348 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
10349 if (TREE_CODE (s) != INTEGER_CST)
10350 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
10352 unsigned char tkind = 0;
10353 switch (OMP_CLAUSE_CODE (c))
10355 case OMP_CLAUSE_MAP:
10356 tkind = OMP_CLAUSE_MAP_KIND (c);
10357 break;
10358 case OMP_CLAUSE_TO:
10359 tkind = OMP_CLAUSE_MAP_TO;
10360 break;
10361 case OMP_CLAUSE_FROM:
10362 tkind = OMP_CLAUSE_MAP_FROM;
10363 break;
10364 default:
10365 gcc_unreachable ();
10367 talign = ceil_log2 (talign);
10368 tkind |= talign << 3;
10369 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
10370 build_int_cst (unsigned_char_type_node,
10371 tkind));
10372 if (nc && nc != c)
10373 c = nc;
10376 gcc_assert (map_idx == map_cnt);
10378 DECL_INITIAL (TREE_VEC_ELT (t, 1))
10379 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
10380 DECL_INITIAL (TREE_VEC_ELT (t, 2))
10381 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
10382 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
10384 gimple_seq initlist = NULL;
10385 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
10386 TREE_VEC_ELT (t, 1)),
10387 &initlist, true, NULL_TREE);
10388 gimple_seq_add_seq (&ilist, initlist);
10390 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
10391 NULL);
10392 TREE_THIS_VOLATILE (clobber) = 1;
10393 gimple_seq_add_stmt (&olist,
10394 gimple_build_assign (TREE_VEC_ELT (t, 1),
10395 clobber));
10398 tree clobber = build_constructor (ctx->record_type, NULL);
10399 TREE_THIS_VOLATILE (clobber) = 1;
10400 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10401 clobber));
10404 /* Once all the expansions are done, sequence all the different
10405 fragments inside gimple_omp_body. */
10407 new_body = NULL;
10409 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
10411 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10412 /* fixup_child_record_type might have changed receiver_decl's type. */
10413 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10414 gimple_seq_add_stmt (&new_body,
10415 gimple_build_assign (ctx->receiver_decl, t));
10418 if (kind == GF_OMP_TARGET_KIND_REGION)
10420 gimple_seq_add_seq (&new_body, tgt_body);
10421 new_body = maybe_catch_exception (new_body);
10423 else if (kind == GF_OMP_TARGET_KIND_DATA)
10424 new_body = tgt_body;
10425 if (kind != GF_OMP_TARGET_KIND_UPDATE)
10427 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10428 gimple_omp_set_body (stmt, new_body);
10431 bind = gimple_build_bind (NULL, NULL,
10432 tgt_bind ? gimple_bind_block (tgt_bind)
10433 : NULL_TREE);
10434 gsi_replace (gsi_p, bind, true);
10435 gimple_bind_add_seq (bind, ilist);
10436 gimple_bind_add_stmt (bind, stmt);
10437 gimple_bind_add_seq (bind, olist);
10439 pop_gimplify_context (NULL);
10442 /* Expand code for an OpenMP teams directive. */
10444 static void
10445 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10447 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
10448 push_gimplify_context ();
10450 tree block = make_node (BLOCK);
10451 gbind *bind = gimple_build_bind (NULL, NULL, block);
10452 gsi_replace (gsi_p, bind, true);
10453 gimple_seq bind_body = NULL;
10454 gimple_seq dlist = NULL;
10455 gimple_seq olist = NULL;
10457 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10458 OMP_CLAUSE_NUM_TEAMS);
10459 if (num_teams == NULL_TREE)
10460 num_teams = build_int_cst (unsigned_type_node, 0);
10461 else
10463 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
10464 num_teams = fold_convert (unsigned_type_node, num_teams);
10465 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
10467 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10468 OMP_CLAUSE_THREAD_LIMIT);
10469 if (thread_limit == NULL_TREE)
10470 thread_limit = build_int_cst (unsigned_type_node, 0);
10471 else
10473 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10474 thread_limit = fold_convert (unsigned_type_node, thread_limit);
10475 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
10476 fb_rvalue);
10479 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
10480 &bind_body, &dlist, ctx, NULL);
10481 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
10482 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
10483 gimple_seq_add_stmt (&bind_body, teams_stmt);
10485 location_t loc = gimple_location (teams_stmt);
10486 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
10487 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10488 gimple_set_location (call, loc);
10489 gimple_seq_add_stmt (&bind_body, call);
10491 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10492 gimple_omp_set_body (teams_stmt, NULL);
10493 gimple_seq_add_seq (&bind_body, olist);
10494 gimple_seq_add_seq (&bind_body, dlist);
10495 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10496 gimple_bind_set_body (bind, bind_body);
10498 pop_gimplify_context (bind);
10500 gimple_bind_append_vars (bind, ctx->block_vars);
10501 BLOCK_VARS (block) = ctx->block_vars;
10502 if (BLOCK_VARS (block))
10503 TREE_USED (block) = 1;
10507 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10508 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10509 of OpenMP context, but with task_shared_vars set. */
10511 static tree
10512 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10513 void *data)
10515 tree t = *tp;
10517 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10518 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
10519 return t;
10521 if (task_shared_vars
10522 && DECL_P (t)
10523 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10524 return t;
10526 /* If a global variable has been privatized, TREE_CONSTANT on
10527 ADDR_EXPR might be wrong. */
10528 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10529 recompute_tree_invariant_for_addr_expr (t);
10531 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10532 return NULL_TREE;
10535 static void
10536 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10538 gimple stmt = gsi_stmt (*gsi_p);
10539 struct walk_stmt_info wi;
10540 gcall *call_stmt;
10542 if (gimple_has_location (stmt))
10543 input_location = gimple_location (stmt);
10545 if (task_shared_vars)
10546 memset (&wi, '\0', sizeof (wi));
10548 /* If we have issued syntax errors, avoid doing any heavy lifting.
10549 Just replace the OpenMP directives with a NOP to avoid
10550 confusing RTL expansion. */
10551 if (seen_error () && is_gimple_omp (stmt))
10553 gsi_replace (gsi_p, gimple_build_nop (), true);
10554 return;
10557 switch (gimple_code (stmt))
10559 case GIMPLE_COND:
10561 gcond *cond_stmt = as_a <gcond *> (stmt);
10562 if ((ctx || task_shared_vars)
10563 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
10564 lower_omp_regimplify_p,
10565 ctx ? NULL : &wi, NULL)
10566 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
10567 lower_omp_regimplify_p,
10568 ctx ? NULL : &wi, NULL)))
10569 gimple_regimplify_operands (cond_stmt, gsi_p);
10571 break;
10572 case GIMPLE_CATCH:
10573 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
10574 break;
10575 case GIMPLE_EH_FILTER:
10576 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10577 break;
10578 case GIMPLE_TRY:
10579 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10580 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10581 break;
10582 case GIMPLE_TRANSACTION:
10583 lower_omp (gimple_transaction_body_ptr (
10584 as_a <gtransaction *> (stmt)),
10585 ctx);
10586 break;
10587 case GIMPLE_BIND:
10588 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
10589 break;
10590 case GIMPLE_OMP_PARALLEL:
10591 case GIMPLE_OMP_TASK:
10592 ctx = maybe_lookup_ctx (stmt);
10593 gcc_assert (ctx);
10594 if (ctx->cancellable)
10595 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10596 lower_omp_taskreg (gsi_p, ctx);
10597 break;
10598 case GIMPLE_OMP_FOR:
10599 ctx = maybe_lookup_ctx (stmt);
10600 gcc_assert (ctx);
10601 if (ctx->cancellable)
10602 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10603 lower_omp_for (gsi_p, ctx);
10604 break;
10605 case GIMPLE_OMP_SECTIONS:
10606 ctx = maybe_lookup_ctx (stmt);
10607 gcc_assert (ctx);
10608 if (ctx->cancellable)
10609 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10610 lower_omp_sections (gsi_p, ctx);
10611 break;
10612 case GIMPLE_OMP_SINGLE:
10613 ctx = maybe_lookup_ctx (stmt);
10614 gcc_assert (ctx);
10615 lower_omp_single (gsi_p, ctx);
10616 break;
10617 case GIMPLE_OMP_MASTER:
10618 ctx = maybe_lookup_ctx (stmt);
10619 gcc_assert (ctx);
10620 lower_omp_master (gsi_p, ctx);
10621 break;
10622 case GIMPLE_OMP_TASKGROUP:
10623 ctx = maybe_lookup_ctx (stmt);
10624 gcc_assert (ctx);
10625 lower_omp_taskgroup (gsi_p, ctx);
10626 break;
10627 case GIMPLE_OMP_ORDERED:
10628 ctx = maybe_lookup_ctx (stmt);
10629 gcc_assert (ctx);
10630 lower_omp_ordered (gsi_p, ctx);
10631 break;
10632 case GIMPLE_OMP_CRITICAL:
10633 ctx = maybe_lookup_ctx (stmt);
10634 gcc_assert (ctx);
10635 lower_omp_critical (gsi_p, ctx);
10636 break;
10637 case GIMPLE_OMP_ATOMIC_LOAD:
10638 if ((ctx || task_shared_vars)
10639 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
10640 as_a <gomp_atomic_load *> (stmt)),
10641 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10642 gimple_regimplify_operands (stmt, gsi_p);
10643 break;
10644 case GIMPLE_OMP_TARGET:
10645 ctx = maybe_lookup_ctx (stmt);
10646 gcc_assert (ctx);
10647 lower_omp_target (gsi_p, ctx);
10648 break;
10649 case GIMPLE_OMP_TEAMS:
10650 ctx = maybe_lookup_ctx (stmt);
10651 gcc_assert (ctx);
10652 lower_omp_teams (gsi_p, ctx);
10653 break;
10654 case GIMPLE_CALL:
10655 tree fndecl;
10656 call_stmt = as_a <gcall *> (stmt);
10657 fndecl = gimple_call_fndecl (call_stmt);
10658 if (fndecl
10659 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10660 switch (DECL_FUNCTION_CODE (fndecl))
10662 case BUILT_IN_GOMP_BARRIER:
10663 if (ctx == NULL)
10664 break;
10665 /* FALLTHRU */
10666 case BUILT_IN_GOMP_CANCEL:
10667 case BUILT_IN_GOMP_CANCELLATION_POINT:
10668 omp_context *cctx;
10669 cctx = ctx;
10670 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10671 cctx = cctx->outer;
10672 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
10673 if (!cctx->cancellable)
10675 if (DECL_FUNCTION_CODE (fndecl)
10676 == BUILT_IN_GOMP_CANCELLATION_POINT)
10678 stmt = gimple_build_nop ();
10679 gsi_replace (gsi_p, stmt, false);
10681 break;
10683 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10685 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10686 gimple_call_set_fndecl (call_stmt, fndecl);
10687 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
10689 tree lhs;
10690 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
10691 gimple_call_set_lhs (call_stmt, lhs);
10692 tree fallthru_label;
10693 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10694 gimple g;
10695 g = gimple_build_label (fallthru_label);
10696 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10697 g = gimple_build_cond (NE_EXPR, lhs,
10698 fold_convert (TREE_TYPE (lhs),
10699 boolean_false_node),
10700 cctx->cancel_label, fallthru_label);
10701 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10702 break;
10703 default:
10704 break;
10706 /* FALLTHRU */
10707 default:
10708 if ((ctx || task_shared_vars)
10709 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10710 ctx ? NULL : &wi))
10712 /* Just remove clobbers, this should happen only if we have
10713 "privatized" local addressable variables in SIMD regions,
10714 the clobber isn't needed in that case and gimplifying address
10715 of the ARRAY_REF into a pointer and creating MEM_REF based
10716 clobber would create worse code than we get with the clobber
10717 dropped. */
10718 if (gimple_clobber_p (stmt))
10720 gsi_replace (gsi_p, gimple_build_nop (), true);
10721 break;
10723 gimple_regimplify_operands (stmt, gsi_p);
10725 break;
10729 static void
10730 lower_omp (gimple_seq *body, omp_context *ctx)
10732 location_t saved_location = input_location;
10733 gimple_stmt_iterator gsi;
10734 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10735 lower_omp_1 (&gsi, ctx);
10736 /* During gimplification, we have not always invoked fold_stmt
10737 (gimplify.c:maybe_fold_stmt); call it now. */
10738 if (target_nesting_level)
10739 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10740 fold_stmt (&gsi);
10741 input_location = saved_location;
10744 /* Main entry point. */
10746 static unsigned int
10747 execute_lower_omp (void)
10749 gimple_seq body;
10750 int i;
10751 omp_context *ctx;
10753 /* This pass always runs, to provide PROP_gimple_lomp.
10754 But there is nothing to do unless -fopenmp is given. */
10755 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10756 return 0;
10758 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10759 delete_omp_context);
10761 body = gimple_body (current_function_decl);
10762 scan_omp (&body, NULL);
10763 gcc_assert (taskreg_nesting_level == 0);
10764 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
10765 finish_taskreg_scan (ctx);
10766 taskreg_contexts.release ();
10768 if (all_contexts->root)
10770 if (task_shared_vars)
10771 push_gimplify_context ();
10772 lower_omp (&body, NULL);
10773 if (task_shared_vars)
10774 pop_gimplify_context (NULL);
10777 if (all_contexts)
10779 splay_tree_delete (all_contexts);
10780 all_contexts = NULL;
10782 BITMAP_FREE (task_shared_vars);
10783 return 0;
10786 namespace {
10788 const pass_data pass_data_lower_omp =
10790 GIMPLE_PASS, /* type */
10791 "omplower", /* name */
10792 OPTGROUP_NONE, /* optinfo_flags */
10793 TV_NONE, /* tv_id */
10794 PROP_gimple_any, /* properties_required */
10795 PROP_gimple_lomp, /* properties_provided */
10796 0, /* properties_destroyed */
10797 0, /* todo_flags_start */
10798 0, /* todo_flags_finish */
10801 class pass_lower_omp : public gimple_opt_pass
10803 public:
10804 pass_lower_omp (gcc::context *ctxt)
10805 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10808 /* opt_pass methods: */
10809 virtual unsigned int execute (function *) { return execute_lower_omp (); }
10811 }; // class pass_lower_omp
10813 } // anon namespace
10815 gimple_opt_pass *
10816 make_pass_lower_omp (gcc::context *ctxt)
10818 return new pass_lower_omp (ctxt);
10821 /* The following is a utility to diagnose OpenMP structured block violations.
10822 It is not part of the "omplower" pass, as that's invoked too late. It
10823 should be invoked by the respective front ends after gimplification. */
10825 static splay_tree all_labels;
10827 /* Check for mismatched contexts and generate an error if needed. Return
10828 true if an error is detected. */
10830 static bool
10831 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10832 gimple branch_ctx, gimple label_ctx)
10834 if (label_ctx == branch_ctx)
10835 return false;
10839 Previously we kept track of the label's entire context in diagnose_sb_[12]
10840 so we could traverse it and issue a correct "exit" or "enter" error
10841 message upon a structured block violation.
10843 We built the context by building a list with tree_cons'ing, but there is
10844 no easy counterpart in gimple tuples. It seems like far too much work
10845 for issuing exit/enter error messages. If someone really misses the
10846 distinct error message... patches welcome.
10849 #if 0
10850 /* Try to avoid confusing the user by producing and error message
10851 with correct "exit" or "enter" verbiage. We prefer "exit"
10852 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10853 if (branch_ctx == NULL)
10854 exit_p = false;
10855 else
10857 while (label_ctx)
10859 if (TREE_VALUE (label_ctx) == branch_ctx)
10861 exit_p = false;
10862 break;
10864 label_ctx = TREE_CHAIN (label_ctx);
10868 if (exit_p)
10869 error ("invalid exit from OpenMP structured block");
10870 else
10871 error ("invalid entry to OpenMP structured block");
10872 #endif
10874 bool cilkplus_block = false;
10875 if (flag_cilkplus)
10877 if ((branch_ctx
10878 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10879 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10880 || (label_ctx
10881 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10882 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10883 cilkplus_block = true;
10886 /* If it's obvious we have an invalid entry, be specific about the error. */
10887 if (branch_ctx == NULL)
10889 if (cilkplus_block)
10890 error ("invalid entry to Cilk Plus structured block");
10891 else
10892 error ("invalid entry to OpenMP structured block");
10894 else
10896 /* Otherwise, be vague and lazy, but efficient. */
10897 if (cilkplus_block)
10898 error ("invalid branch to/from a Cilk Plus structured block");
10899 else
10900 error ("invalid branch to/from an OpenMP structured block");
10903 gsi_replace (gsi_p, gimple_build_nop (), false);
10904 return true;
10907 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10908 where each label is found. */
10910 static tree
10911 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10912 struct walk_stmt_info *wi)
10914 gimple context = (gimple) wi->info;
10915 gimple inner_context;
10916 gimple stmt = gsi_stmt (*gsi_p);
10918 *handled_ops_p = true;
10920 switch (gimple_code (stmt))
10922 WALK_SUBSTMTS;
10924 case GIMPLE_OMP_PARALLEL:
10925 case GIMPLE_OMP_TASK:
10926 case GIMPLE_OMP_SECTIONS:
10927 case GIMPLE_OMP_SINGLE:
10928 case GIMPLE_OMP_SECTION:
10929 case GIMPLE_OMP_MASTER:
10930 case GIMPLE_OMP_ORDERED:
10931 case GIMPLE_OMP_CRITICAL:
10932 case GIMPLE_OMP_TARGET:
10933 case GIMPLE_OMP_TEAMS:
10934 case GIMPLE_OMP_TASKGROUP:
10935 /* The minimal context here is just the current OMP construct. */
10936 inner_context = stmt;
10937 wi->info = inner_context;
10938 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10939 wi->info = context;
10940 break;
10942 case GIMPLE_OMP_FOR:
10943 inner_context = stmt;
10944 wi->info = inner_context;
10945 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10946 walk them. */
10947 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10948 diagnose_sb_1, NULL, wi);
10949 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10950 wi->info = context;
10951 break;
10953 case GIMPLE_LABEL:
10954 splay_tree_insert (all_labels,
10955 (splay_tree_key) gimple_label_label (
10956 as_a <glabel *> (stmt)),
10957 (splay_tree_value) context);
10958 break;
10960 default:
10961 break;
10964 return NULL_TREE;
10967 /* Pass 2: Check each branch and see if its context differs from that of
10968 the destination label's context. */
10970 static tree
10971 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10972 struct walk_stmt_info *wi)
10974 gimple context = (gimple) wi->info;
10975 splay_tree_node n;
10976 gimple stmt = gsi_stmt (*gsi_p);
10978 *handled_ops_p = true;
10980 switch (gimple_code (stmt))
10982 WALK_SUBSTMTS;
10984 case GIMPLE_OMP_PARALLEL:
10985 case GIMPLE_OMP_TASK:
10986 case GIMPLE_OMP_SECTIONS:
10987 case GIMPLE_OMP_SINGLE:
10988 case GIMPLE_OMP_SECTION:
10989 case GIMPLE_OMP_MASTER:
10990 case GIMPLE_OMP_ORDERED:
10991 case GIMPLE_OMP_CRITICAL:
10992 case GIMPLE_OMP_TARGET:
10993 case GIMPLE_OMP_TEAMS:
10994 case GIMPLE_OMP_TASKGROUP:
10995 wi->info = stmt;
10996 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10997 wi->info = context;
10998 break;
11000 case GIMPLE_OMP_FOR:
11001 wi->info = stmt;
11002 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
11003 walk them. */
11004 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
11005 diagnose_sb_2, NULL, wi);
11006 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
11007 wi->info = context;
11008 break;
11010 case GIMPLE_COND:
11012 gcond *cond_stmt = as_a <gcond *> (stmt);
11013 tree lab = gimple_cond_true_label (cond_stmt);
11014 if (lab)
11016 n = splay_tree_lookup (all_labels,
11017 (splay_tree_key) lab);
11018 diagnose_sb_0 (gsi_p, context,
11019 n ? (gimple) n->value : NULL);
11021 lab = gimple_cond_false_label (cond_stmt);
11022 if (lab)
11024 n = splay_tree_lookup (all_labels,
11025 (splay_tree_key) lab);
11026 diagnose_sb_0 (gsi_p, context,
11027 n ? (gimple) n->value : NULL);
11030 break;
11032 case GIMPLE_GOTO:
11034 tree lab = gimple_goto_dest (stmt);
11035 if (TREE_CODE (lab) != LABEL_DECL)
11036 break;
11038 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
11039 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
11041 break;
11043 case GIMPLE_SWITCH:
11045 gswitch *switch_stmt = as_a <gswitch *> (stmt);
11046 unsigned int i;
11047 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
11049 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
11050 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
11051 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
11052 break;
11055 break;
11057 case GIMPLE_RETURN:
11058 diagnose_sb_0 (gsi_p, context, NULL);
11059 break;
11061 default:
11062 break;
11065 return NULL_TREE;
11068 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
11069 codes. */
11070 bool
11071 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
11072 int *region_idx)
11074 gimple last = last_stmt (bb);
11075 enum gimple_code code = gimple_code (last);
11076 struct omp_region *cur_region = *region;
11077 bool fallthru = false;
11079 switch (code)
11081 case GIMPLE_OMP_PARALLEL:
11082 case GIMPLE_OMP_TASK:
11083 case GIMPLE_OMP_FOR:
11084 case GIMPLE_OMP_SINGLE:
11085 case GIMPLE_OMP_TEAMS:
11086 case GIMPLE_OMP_MASTER:
11087 case GIMPLE_OMP_TASKGROUP:
11088 case GIMPLE_OMP_ORDERED:
11089 case GIMPLE_OMP_CRITICAL:
11090 case GIMPLE_OMP_SECTION:
11091 cur_region = new_omp_region (bb, code, cur_region);
11092 fallthru = true;
11093 break;
11095 case GIMPLE_OMP_TARGET:
11096 cur_region = new_omp_region (bb, code, cur_region);
11097 fallthru = true;
11098 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
11099 cur_region = cur_region->outer;
11100 break;
11102 case GIMPLE_OMP_SECTIONS:
11103 cur_region = new_omp_region (bb, code, cur_region);
11104 fallthru = true;
11105 break;
11107 case GIMPLE_OMP_SECTIONS_SWITCH:
11108 fallthru = false;
11109 break;
11111 case GIMPLE_OMP_ATOMIC_LOAD:
11112 case GIMPLE_OMP_ATOMIC_STORE:
11113 fallthru = true;
11114 break;
11116 case GIMPLE_OMP_RETURN:
11117 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
11118 somewhere other than the next block. This will be
11119 created later. */
11120 cur_region->exit = bb;
11121 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
11122 cur_region = cur_region->outer;
11123 break;
11125 case GIMPLE_OMP_CONTINUE:
11126 cur_region->cont = bb;
11127 switch (cur_region->type)
11129 case GIMPLE_OMP_FOR:
11130 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11131 succs edges as abnormal to prevent splitting
11132 them. */
11133 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
11134 /* Make the loopback edge. */
11135 make_edge (bb, single_succ (cur_region->entry),
11136 EDGE_ABNORMAL);
11138 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11139 corresponds to the case that the body of the loop
11140 is not executed at all. */
11141 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
11142 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
11143 fallthru = false;
11144 break;
11146 case GIMPLE_OMP_SECTIONS:
11147 /* Wire up the edges into and out of the nested sections. */
11149 basic_block switch_bb = single_succ (cur_region->entry);
11151 struct omp_region *i;
11152 for (i = cur_region->inner; i ; i = i->next)
11154 gcc_assert (i->type == GIMPLE_OMP_SECTION);
11155 make_edge (switch_bb, i->entry, 0);
11156 make_edge (i->exit, bb, EDGE_FALLTHRU);
11159 /* Make the loopback edge to the block with
11160 GIMPLE_OMP_SECTIONS_SWITCH. */
11161 make_edge (bb, switch_bb, 0);
11163 /* Make the edge from the switch to exit. */
11164 make_edge (switch_bb, bb->next_bb, 0);
11165 fallthru = false;
11167 break;
11169 default:
11170 gcc_unreachable ();
11172 break;
11174 default:
11175 gcc_unreachable ();
11178 if (*region != cur_region)
11180 *region = cur_region;
11181 if (cur_region)
11182 *region_idx = cur_region->entry->index;
11183 else
11184 *region_idx = 0;
11187 return fallthru;
11190 static unsigned int
11191 diagnose_omp_structured_block_errors (void)
11193 struct walk_stmt_info wi;
11194 gimple_seq body = gimple_body (current_function_decl);
11196 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
11198 memset (&wi, 0, sizeof (wi));
11199 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
11201 memset (&wi, 0, sizeof (wi));
11202 wi.want_locations = true;
11203 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
11205 gimple_set_body (current_function_decl, body);
11207 splay_tree_delete (all_labels);
11208 all_labels = NULL;
11210 return 0;
11213 namespace {
11215 const pass_data pass_data_diagnose_omp_blocks =
11217 GIMPLE_PASS, /* type */
11218 "*diagnose_omp_blocks", /* name */
11219 OPTGROUP_NONE, /* optinfo_flags */
11220 TV_NONE, /* tv_id */
11221 PROP_gimple_any, /* properties_required */
11222 0, /* properties_provided */
11223 0, /* properties_destroyed */
11224 0, /* todo_flags_start */
11225 0, /* todo_flags_finish */
11228 class pass_diagnose_omp_blocks : public gimple_opt_pass
11230 public:
11231 pass_diagnose_omp_blocks (gcc::context *ctxt)
11232 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
11235 /* opt_pass methods: */
11236 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
11237 virtual unsigned int execute (function *)
11239 return diagnose_omp_structured_block_errors ();
11242 }; // class pass_diagnose_omp_blocks
11244 } // anon namespace
11246 gimple_opt_pass *
11247 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
11249 return new pass_diagnose_omp_blocks (ctxt);
11252 /* SIMD clone supporting code. */
11254 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11255 of arguments to reserve space for. */
11257 static struct cgraph_simd_clone *
11258 simd_clone_struct_alloc (int nargs)
11260 struct cgraph_simd_clone *clone_info;
11261 size_t len = (sizeof (struct cgraph_simd_clone)
11262 + nargs * sizeof (struct cgraph_simd_clone_arg));
11263 clone_info = (struct cgraph_simd_clone *)
11264 ggc_internal_cleared_alloc (len);
11265 return clone_info;
11268 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11270 static inline void
11271 simd_clone_struct_copy (struct cgraph_simd_clone *to,
11272 struct cgraph_simd_clone *from)
11274 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
11275 + ((from->nargs - from->inbranch)
11276 * sizeof (struct cgraph_simd_clone_arg))));
11279 /* Return vector of parameter types of function FNDECL. This uses
11280 TYPE_ARG_TYPES if available, otherwise falls back to types of
11281 DECL_ARGUMENTS types. */
11283 vec<tree>
11284 simd_clone_vector_of_formal_parm_types (tree fndecl)
11286 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
11287 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
11288 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
11289 unsigned int i;
11290 tree arg;
11291 FOR_EACH_VEC_ELT (args, i, arg)
11292 args[i] = TREE_TYPE (args[i]);
11293 return args;
11296 /* Given a simd function in NODE, extract the simd specific
11297 information from the OMP clauses passed in CLAUSES, and return
11298 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11299 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11300 otherwise set to FALSE. */
11302 static struct cgraph_simd_clone *
11303 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
11304 bool *inbranch_specified)
11306 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
11307 tree t;
11308 int n;
11309 *inbranch_specified = false;
11311 n = args.length ();
11312 if (n > 0 && args.last () == void_type_node)
11313 n--;
11315 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11316 be cloned have a distinctive artificial label in addition to "omp
11317 declare simd". */
11318 bool cilk_clone
11319 = (flag_cilkplus
11320 && lookup_attribute ("cilk simd function",
11321 DECL_ATTRIBUTES (node->decl)));
11323 /* Allocate one more than needed just in case this is an in-branch
11324 clone which will require a mask argument. */
11325 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
11326 clone_info->nargs = n;
11327 clone_info->cilk_elemental = cilk_clone;
11329 if (!clauses)
11331 args.release ();
11332 return clone_info;
11334 clauses = TREE_VALUE (clauses);
11335 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
11336 return clone_info;
11338 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
11340 switch (OMP_CLAUSE_CODE (t))
11342 case OMP_CLAUSE_INBRANCH:
11343 clone_info->inbranch = 1;
11344 *inbranch_specified = true;
11345 break;
11346 case OMP_CLAUSE_NOTINBRANCH:
11347 clone_info->inbranch = 0;
11348 *inbranch_specified = true;
11349 break;
11350 case OMP_CLAUSE_SIMDLEN:
11351 clone_info->simdlen
11352 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
11353 break;
11354 case OMP_CLAUSE_LINEAR:
11356 tree decl = OMP_CLAUSE_DECL (t);
11357 tree step = OMP_CLAUSE_LINEAR_STEP (t);
11358 int argno = TREE_INT_CST_LOW (decl);
11359 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
11361 clone_info->args[argno].arg_type
11362 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
11363 clone_info->args[argno].linear_step = tree_to_shwi (step);
11364 gcc_assert (clone_info->args[argno].linear_step >= 0
11365 && clone_info->args[argno].linear_step < n);
11367 else
11369 if (POINTER_TYPE_P (args[argno]))
11370 step = fold_convert (ssizetype, step);
11371 if (!tree_fits_shwi_p (step))
11373 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11374 "ignoring large linear step");
11375 args.release ();
11376 return NULL;
11378 else if (integer_zerop (step))
11380 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11381 "ignoring zero linear step");
11382 args.release ();
11383 return NULL;
11385 else
11387 clone_info->args[argno].arg_type
11388 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
11389 clone_info->args[argno].linear_step = tree_to_shwi (step);
11392 break;
11394 case OMP_CLAUSE_UNIFORM:
11396 tree decl = OMP_CLAUSE_DECL (t);
11397 int argno = tree_to_uhwi (decl);
11398 clone_info->args[argno].arg_type
11399 = SIMD_CLONE_ARG_TYPE_UNIFORM;
11400 break;
11402 case OMP_CLAUSE_ALIGNED:
11404 tree decl = OMP_CLAUSE_DECL (t);
11405 int argno = tree_to_uhwi (decl);
11406 clone_info->args[argno].alignment
11407 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
11408 break;
11410 default:
11411 break;
11414 args.release ();
11415 return clone_info;
11418 /* Given a SIMD clone in NODE, calculate the characteristic data
11419 type and return the coresponding type. The characteristic data
11420 type is computed as described in the Intel Vector ABI. */
11422 static tree
11423 simd_clone_compute_base_data_type (struct cgraph_node *node,
11424 struct cgraph_simd_clone *clone_info)
11426 tree type = integer_type_node;
11427 tree fndecl = node->decl;
11429 /* a) For non-void function, the characteristic data type is the
11430 return type. */
11431 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
11432 type = TREE_TYPE (TREE_TYPE (fndecl));
11434 /* b) If the function has any non-uniform, non-linear parameters,
11435 then the characteristic data type is the type of the first
11436 such parameter. */
11437 else
11439 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
11440 for (unsigned int i = 0; i < clone_info->nargs; ++i)
11441 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
11443 type = map[i];
11444 break;
11446 map.release ();
11449 /* c) If the characteristic data type determined by a) or b) above
11450 is struct, union, or class type which is pass-by-value (except
11451 for the type that maps to the built-in complex data type), the
11452 characteristic data type is int. */
11453 if (RECORD_OR_UNION_TYPE_P (type)
11454 && !aggregate_value_p (type, NULL)
11455 && TREE_CODE (type) != COMPLEX_TYPE)
11456 return integer_type_node;
11458 /* d) If none of the above three classes is applicable, the
11459 characteristic data type is int. */
11461 return type;
11463 /* e) For Intel Xeon Phi native and offload compilation, if the
11464 resulting characteristic data type is 8-bit or 16-bit integer
11465 data type, the characteristic data type is int. */
11466 /* Well, we don't handle Xeon Phi yet. */
11469 static tree
11470 simd_clone_mangle (struct cgraph_node *node,
11471 struct cgraph_simd_clone *clone_info)
11473 char vecsize_mangle = clone_info->vecsize_mangle;
11474 char mask = clone_info->inbranch ? 'M' : 'N';
11475 unsigned int simdlen = clone_info->simdlen;
11476 unsigned int n;
11477 pretty_printer pp;
11479 gcc_assert (vecsize_mangle && simdlen);
11481 pp_string (&pp, "_ZGV");
11482 pp_character (&pp, vecsize_mangle);
11483 pp_character (&pp, mask);
11484 pp_decimal_int (&pp, simdlen);
11486 for (n = 0; n < clone_info->nargs; ++n)
11488 struct cgraph_simd_clone_arg arg = clone_info->args[n];
11490 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
11491 pp_character (&pp, 'u');
11492 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11494 gcc_assert (arg.linear_step != 0);
11495 pp_character (&pp, 'l');
11496 if (arg.linear_step > 1)
11497 pp_unsigned_wide_integer (&pp, arg.linear_step);
11498 else if (arg.linear_step < 0)
11500 pp_character (&pp, 'n');
11501 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
11502 arg.linear_step));
11505 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11507 pp_character (&pp, 's');
11508 pp_unsigned_wide_integer (&pp, arg.linear_step);
11510 else
11511 pp_character (&pp, 'v');
11512 if (arg.alignment)
11514 pp_character (&pp, 'a');
11515 pp_decimal_int (&pp, arg.alignment);
11519 pp_underscore (&pp);
11520 pp_string (&pp,
11521 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11522 const char *str = pp_formatted_text (&pp);
11524 /* If there already is a SIMD clone with the same mangled name, don't
11525 add another one. This can happen e.g. for
11526 #pragma omp declare simd
11527 #pragma omp declare simd simdlen(8)
11528 int foo (int, int);
11529 if the simdlen is assumed to be 8 for the first one, etc. */
11530 for (struct cgraph_node *clone = node->simd_clones; clone;
11531 clone = clone->simdclone->next_clone)
11532 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11533 str) == 0)
11534 return NULL_TREE;
11536 return get_identifier (str);
11539 /* Create a simd clone of OLD_NODE and return it. */
11541 static struct cgraph_node *
11542 simd_clone_create (struct cgraph_node *old_node)
11544 struct cgraph_node *new_node;
11545 if (old_node->definition)
11547 if (!old_node->has_gimple_body_p ())
11548 return NULL;
11549 old_node->get_body ();
11550 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
11551 false, NULL, NULL,
11552 "simdclone");
11554 else
11556 tree old_decl = old_node->decl;
11557 tree new_decl = copy_node (old_node->decl);
11558 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11559 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11560 SET_DECL_RTL (new_decl, NULL);
11561 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11562 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11563 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
11564 symtab->call_cgraph_insertion_hooks (new_node);
11566 if (new_node == NULL)
11567 return new_node;
11569 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11571 /* The function cgraph_function_versioning () will force the new
11572 symbol local. Undo this, and inherit external visability from
11573 the old node. */
11574 new_node->local.local = old_node->local.local;
11575 new_node->externally_visible = old_node->externally_visible;
11577 return new_node;
11580 /* Adjust the return type of the given function to its appropriate
11581 vector counterpart. Returns a simd array to be used throughout the
11582 function as a return value. */
11584 static tree
11585 simd_clone_adjust_return_type (struct cgraph_node *node)
11587 tree fndecl = node->decl;
11588 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11589 unsigned int veclen;
11590 tree t;
11592 /* Adjust the function return type. */
11593 if (orig_rettype == void_type_node)
11594 return NULL_TREE;
11595 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11596 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11597 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11598 veclen = node->simdclone->vecsize_int;
11599 else
11600 veclen = node->simdclone->vecsize_float;
11601 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11602 if (veclen > node->simdclone->simdlen)
11603 veclen = node->simdclone->simdlen;
11604 if (veclen == node->simdclone->simdlen)
11605 TREE_TYPE (TREE_TYPE (fndecl))
11606 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11607 node->simdclone->simdlen);
11608 else
11610 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11611 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11612 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11614 if (!node->definition)
11615 return NULL_TREE;
11617 t = DECL_RESULT (fndecl);
11618 /* Adjust the DECL_RESULT. */
11619 gcc_assert (TREE_TYPE (t) != void_type_node);
11620 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11621 relayout_decl (t);
11623 tree atype = build_array_type_nelts (orig_rettype,
11624 node->simdclone->simdlen);
11625 if (veclen != node->simdclone->simdlen)
11626 return build1 (VIEW_CONVERT_EXPR, atype, t);
11628 /* Set up a SIMD array to use as the return value. */
11629 tree retval = create_tmp_var_raw (atype, "retval");
11630 gimple_add_tmp_var (retval);
11631 return retval;
11634 /* Each vector argument has a corresponding array to be used locally
11635 as part of the eventual loop. Create such temporary array and
11636 return it.
11638 PREFIX is the prefix to be used for the temporary.
11640 TYPE is the inner element type.
11642 SIMDLEN is the number of elements. */
11644 static tree
11645 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11647 tree atype = build_array_type_nelts (type, simdlen);
11648 tree avar = create_tmp_var_raw (atype, prefix);
11649 gimple_add_tmp_var (avar);
11650 return avar;
11653 /* Modify the function argument types to their corresponding vector
11654 counterparts if appropriate. Also, create one array for each simd
11655 argument to be used locally when using the function arguments as
11656 part of the loop.
11658 NODE is the function whose arguments are to be adjusted.
11660 Returns an adjustment vector that will be filled describing how the
11661 argument types will be adjusted. */
11663 static ipa_parm_adjustment_vec
11664 simd_clone_adjust_argument_types (struct cgraph_node *node)
11666 vec<tree> args;
11667 ipa_parm_adjustment_vec adjustments;
11669 if (node->definition)
11670 args = ipa_get_vector_of_formal_parms (node->decl);
11671 else
11672 args = simd_clone_vector_of_formal_parm_types (node->decl);
11673 adjustments.create (args.length ());
11674 unsigned i, j, veclen;
11675 struct ipa_parm_adjustment adj;
11676 for (i = 0; i < node->simdclone->nargs; ++i)
11678 memset (&adj, 0, sizeof (adj));
11679 tree parm = args[i];
11680 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11681 adj.base_index = i;
11682 adj.base = parm;
11684 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11685 node->simdclone->args[i].orig_type = parm_type;
11687 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11689 /* No adjustment necessary for scalar arguments. */
11690 adj.op = IPA_PARM_OP_COPY;
11692 else
11694 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11695 veclen = node->simdclone->vecsize_int;
11696 else
11697 veclen = node->simdclone->vecsize_float;
11698 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11699 if (veclen > node->simdclone->simdlen)
11700 veclen = node->simdclone->simdlen;
11701 adj.arg_prefix = "simd";
11702 adj.type = build_vector_type (parm_type, veclen);
11703 node->simdclone->args[i].vector_type = adj.type;
11704 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11706 adjustments.safe_push (adj);
11707 if (j == veclen)
11709 memset (&adj, 0, sizeof (adj));
11710 adj.op = IPA_PARM_OP_NEW;
11711 adj.arg_prefix = "simd";
11712 adj.base_index = i;
11713 adj.type = node->simdclone->args[i].vector_type;
11717 if (node->definition)
11718 node->simdclone->args[i].simd_array
11719 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11720 parm_type, node->simdclone->simdlen);
11722 adjustments.safe_push (adj);
11725 if (node->simdclone->inbranch)
11727 tree base_type
11728 = simd_clone_compute_base_data_type (node->simdclone->origin,
11729 node->simdclone);
11731 memset (&adj, 0, sizeof (adj));
11732 adj.op = IPA_PARM_OP_NEW;
11733 adj.arg_prefix = "mask";
11735 adj.base_index = i;
11736 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11737 veclen = node->simdclone->vecsize_int;
11738 else
11739 veclen = node->simdclone->vecsize_float;
11740 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11741 if (veclen > node->simdclone->simdlen)
11742 veclen = node->simdclone->simdlen;
11743 adj.type = build_vector_type (base_type, veclen);
11744 adjustments.safe_push (adj);
11746 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11747 adjustments.safe_push (adj);
11749 /* We have previously allocated one extra entry for the mask. Use
11750 it and fill it. */
11751 struct cgraph_simd_clone *sc = node->simdclone;
11752 sc->nargs++;
11753 if (node->definition)
11755 sc->args[i].orig_arg
11756 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11757 sc->args[i].simd_array
11758 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11760 sc->args[i].orig_type = base_type;
11761 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11764 if (node->definition)
11765 ipa_modify_formal_parameters (node->decl, adjustments);
11766 else
11768 tree new_arg_types = NULL_TREE, new_reversed;
11769 bool last_parm_void = false;
11770 if (args.length () > 0 && args.last () == void_type_node)
11771 last_parm_void = true;
11773 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11774 j = adjustments.length ();
11775 for (i = 0; i < j; i++)
11777 struct ipa_parm_adjustment *adj = &adjustments[i];
11778 tree ptype;
11779 if (adj->op == IPA_PARM_OP_COPY)
11780 ptype = args[adj->base_index];
11781 else
11782 ptype = adj->type;
11783 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11785 new_reversed = nreverse (new_arg_types);
11786 if (last_parm_void)
11788 if (new_reversed)
11789 TREE_CHAIN (new_arg_types) = void_list_node;
11790 else
11791 new_reversed = void_list_node;
11794 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11795 TYPE_ARG_TYPES (new_type) = new_reversed;
11796 TREE_TYPE (node->decl) = new_type;
11798 adjustments.release ();
11800 args.release ();
11801 return adjustments;
11804 /* Initialize and copy the function arguments in NODE to their
11805 corresponding local simd arrays. Returns a fresh gimple_seq with
11806 the instruction sequence generated. */
11808 static gimple_seq
11809 simd_clone_init_simd_arrays (struct cgraph_node *node,
11810 ipa_parm_adjustment_vec adjustments)
11812 gimple_seq seq = NULL;
11813 unsigned i = 0, j = 0, k;
11815 for (tree arg = DECL_ARGUMENTS (node->decl);
11816 arg;
11817 arg = DECL_CHAIN (arg), i++, j++)
11819 if (adjustments[j].op == IPA_PARM_OP_COPY)
11820 continue;
11822 node->simdclone->args[i].vector_arg = arg;
11824 tree array = node->simdclone->args[i].simd_array;
11825 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11827 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11828 tree ptr = build_fold_addr_expr (array);
11829 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11830 build_int_cst (ptype, 0));
11831 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11832 gimplify_and_add (t, &seq);
11834 else
11836 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11837 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11838 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11840 tree ptr = build_fold_addr_expr (array);
11841 int elemsize;
11842 if (k)
11844 arg = DECL_CHAIN (arg);
11845 j++;
11847 elemsize
11848 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11849 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11850 build_int_cst (ptype, k * elemsize));
11851 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11852 gimplify_and_add (t, &seq);
11856 return seq;
11859 /* Callback info for ipa_simd_modify_stmt_ops below. */
11861 struct modify_stmt_info {
11862 ipa_parm_adjustment_vec adjustments;
11863 gimple stmt;
11864 /* True if the parent statement was modified by
11865 ipa_simd_modify_stmt_ops. */
11866 bool modified;
11869 /* Callback for walk_gimple_op.
11871 Adjust operands from a given statement as specified in the
11872 adjustments vector in the callback data. */
11874 static tree
11875 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11877 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11878 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11879 tree *orig_tp = tp;
11880 if (TREE_CODE (*tp) == ADDR_EXPR)
11881 tp = &TREE_OPERAND (*tp, 0);
11882 struct ipa_parm_adjustment *cand = NULL;
11883 if (TREE_CODE (*tp) == PARM_DECL)
11884 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11885 else
11887 if (TYPE_P (*tp))
11888 *walk_subtrees = 0;
11891 tree repl = NULL_TREE;
11892 if (cand)
11893 repl = unshare_expr (cand->new_decl);
11894 else
11896 if (tp != orig_tp)
11898 *walk_subtrees = 0;
11899 bool modified = info->modified;
11900 info->modified = false;
11901 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11902 if (!info->modified)
11904 info->modified = modified;
11905 return NULL_TREE;
11907 info->modified = modified;
11908 repl = *tp;
11910 else
11911 return NULL_TREE;
11914 if (tp != orig_tp)
11916 repl = build_fold_addr_expr (repl);
11917 gimple stmt;
11918 if (is_gimple_debug (info->stmt))
11920 tree vexpr = make_node (DEBUG_EXPR_DECL);
11921 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
11922 DECL_ARTIFICIAL (vexpr) = 1;
11923 TREE_TYPE (vexpr) = TREE_TYPE (repl);
11924 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
11925 repl = vexpr;
11927 else
11929 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl),
11930 NULL), repl);
11931 repl = gimple_assign_lhs (stmt);
11933 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11934 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11935 *orig_tp = repl;
11937 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11939 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11940 *tp = vce;
11942 else
11943 *tp = repl;
11945 info->modified = true;
11946 return NULL_TREE;
11949 /* Traverse the function body and perform all modifications as
11950 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11951 modified such that the replacement/reduction value will now be an
11952 offset into the corresponding simd_array.
11954 This function will replace all function argument uses with their
11955 corresponding simd array elements, and ajust the return values
11956 accordingly. */
11958 static void
11959 ipa_simd_modify_function_body (struct cgraph_node *node,
11960 ipa_parm_adjustment_vec adjustments,
11961 tree retval_array, tree iter)
11963 basic_block bb;
11964 unsigned int i, j, l;
11966 /* Re-use the adjustments array, but this time use it to replace
11967 every function argument use to an offset into the corresponding
11968 simd_array. */
11969 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11971 if (!node->simdclone->args[i].vector_arg)
11972 continue;
11974 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11975 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11976 adjustments[j].new_decl
11977 = build4 (ARRAY_REF,
11978 basetype,
11979 node->simdclone->args[i].simd_array,
11980 iter,
11981 NULL_TREE, NULL_TREE);
11982 if (adjustments[j].op == IPA_PARM_OP_NONE
11983 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11984 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11987 l = adjustments.length ();
11988 for (i = 1; i < num_ssa_names; i++)
11990 tree name = ssa_name (i);
11991 if (name
11992 && SSA_NAME_VAR (name)
11993 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11995 for (j = 0; j < l; j++)
11996 if (SSA_NAME_VAR (name) == adjustments[j].base
11997 && adjustments[j].new_decl)
11999 tree base_var;
12000 if (adjustments[j].new_ssa_base == NULL_TREE)
12002 base_var
12003 = copy_var_decl (adjustments[j].base,
12004 DECL_NAME (adjustments[j].base),
12005 TREE_TYPE (adjustments[j].base));
12006 adjustments[j].new_ssa_base = base_var;
12008 else
12009 base_var = adjustments[j].new_ssa_base;
12010 if (SSA_NAME_IS_DEFAULT_DEF (name))
12012 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12013 gimple_stmt_iterator gsi = gsi_after_labels (bb);
12014 tree new_decl = unshare_expr (adjustments[j].new_decl);
12015 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
12016 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
12017 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
12018 gimple stmt = gimple_build_assign (name, new_decl);
12019 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
12021 else
12022 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
12027 struct modify_stmt_info info;
12028 info.adjustments = adjustments;
12030 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
12032 gimple_stmt_iterator gsi;
12034 gsi = gsi_start_bb (bb);
12035 while (!gsi_end_p (gsi))
12037 gimple stmt = gsi_stmt (gsi);
12038 info.stmt = stmt;
12039 struct walk_stmt_info wi;
12041 memset (&wi, 0, sizeof (wi));
12042 info.modified = false;
12043 wi.info = &info;
12044 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
12046 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
12048 tree retval = gimple_return_retval (return_stmt);
12049 if (!retval)
12051 gsi_remove (&gsi, true);
12052 continue;
12055 /* Replace `return foo' with `retval_array[iter] = foo'. */
12056 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
12057 retval_array, iter, NULL, NULL);
12058 stmt = gimple_build_assign (ref, retval);
12059 gsi_replace (&gsi, stmt, true);
12060 info.modified = true;
12063 if (info.modified)
12065 update_stmt (stmt);
12066 if (maybe_clean_eh_stmt (stmt))
12067 gimple_purge_dead_eh_edges (gimple_bb (stmt));
12069 gsi_next (&gsi);
12074 /* Adjust the argument types in NODE to their appropriate vector
12075 counterparts. */
12077 static void
12078 simd_clone_adjust (struct cgraph_node *node)
12080 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
12082 targetm.simd_clone.adjust (node);
12084 tree retval = simd_clone_adjust_return_type (node);
12085 ipa_parm_adjustment_vec adjustments
12086 = simd_clone_adjust_argument_types (node);
12088 push_gimplify_context ();
12090 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
12092 /* Adjust all uses of vector arguments accordingly. Adjust all
12093 return values accordingly. */
12094 tree iter = create_tmp_var (unsigned_type_node, "iter");
12095 tree iter1 = make_ssa_name (iter, NULL);
12096 tree iter2 = make_ssa_name (iter, NULL);
12097 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
12099 /* Initialize the iteration variable. */
12100 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12101 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
12102 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
12103 /* Insert the SIMD array and iv initialization at function
12104 entry. */
12105 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
12107 pop_gimplify_context (NULL);
12109 /* Create a new BB right before the original exit BB, to hold the
12110 iteration increment and the condition/branch. */
12111 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
12112 basic_block incr_bb = create_empty_bb (orig_exit);
12113 add_bb_to_loop (incr_bb, body_bb->loop_father);
12114 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
12115 flag. Set it now to be a FALLTHRU_EDGE. */
12116 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
12117 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
12118 for (unsigned i = 0;
12119 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
12121 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
12122 redirect_edge_succ (e, incr_bb);
12124 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
12125 e->probability = REG_BR_PROB_BASE;
12126 gsi = gsi_last_bb (incr_bb);
12127 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
12128 build_int_cst (unsigned_type_node,
12129 1));
12130 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12132 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12133 struct loop *loop = alloc_loop ();
12134 cfun->has_force_vectorize_loops = true;
12135 loop->safelen = node->simdclone->simdlen;
12136 loop->force_vectorize = true;
12137 loop->header = body_bb;
12139 /* Branch around the body if the mask applies. */
12140 if (node->simdclone->inbranch)
12142 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
12143 tree mask_array
12144 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
12145 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
12146 tree aref = build4 (ARRAY_REF,
12147 TREE_TYPE (TREE_TYPE (mask_array)),
12148 mask_array, iter1,
12149 NULL, NULL);
12150 g = gimple_build_assign (mask, aref);
12151 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12152 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
12153 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
12155 aref = build1 (VIEW_CONVERT_EXPR,
12156 build_nonstandard_integer_type (bitsize, 0), mask);
12157 mask = make_ssa_name (TREE_TYPE (aref), NULL);
12158 g = gimple_build_assign (mask, aref);
12159 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12162 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
12163 NULL, NULL);
12164 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12165 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
12166 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
12169 /* Generate the condition. */
12170 g = gimple_build_cond (LT_EXPR,
12171 iter2,
12172 build_int_cst (unsigned_type_node,
12173 node->simdclone->simdlen),
12174 NULL, NULL);
12175 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12176 e = split_block (incr_bb, gsi_stmt (gsi));
12177 basic_block latch_bb = e->dest;
12178 basic_block new_exit_bb;
12179 new_exit_bb = split_block (latch_bb, NULL)->dest;
12180 loop->latch = latch_bb;
12182 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
12184 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
12185 /* The successor of incr_bb is already pointing to latch_bb; just
12186 change the flags.
12187 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12188 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
12190 gphi *phi = create_phi_node (iter1, body_bb);
12191 edge preheader_edge = find_edge (entry_bb, body_bb);
12192 edge latch_edge = single_succ_edge (latch_bb);
12193 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
12194 UNKNOWN_LOCATION);
12195 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12197 /* Generate the new return. */
12198 gsi = gsi_last_bb (new_exit_bb);
12199 if (retval
12200 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
12201 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
12202 retval = TREE_OPERAND (retval, 0);
12203 else if (retval)
12205 retval = build1 (VIEW_CONVERT_EXPR,
12206 TREE_TYPE (TREE_TYPE (node->decl)),
12207 retval);
12208 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
12209 false, GSI_CONTINUE_LINKING);
12211 g = gimple_build_return (retval);
12212 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12214 /* Handle aligned clauses by replacing default defs of the aligned
12215 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12216 lhs. Handle linear by adding PHIs. */
12217 for (unsigned i = 0; i < node->simdclone->nargs; i++)
12218 if (node->simdclone->args[i].alignment
12219 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
12220 && (node->simdclone->args[i].alignment
12221 & (node->simdclone->args[i].alignment - 1)) == 0
12222 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
12223 == POINTER_TYPE)
12225 unsigned int alignment = node->simdclone->args[i].alignment;
12226 tree orig_arg = node->simdclone->args[i].orig_arg;
12227 tree def = ssa_default_def (cfun, orig_arg);
12228 if (def && !has_zero_uses (def))
12230 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
12231 gimple_seq seq = NULL;
12232 bool need_cvt = false;
12233 gcall *call
12234 = gimple_build_call (fn, 2, def, size_int (alignment));
12235 g = call;
12236 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
12237 ptr_type_node))
12238 need_cvt = true;
12239 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
12240 gimple_call_set_lhs (g, t);
12241 gimple_seq_add_stmt_without_update (&seq, g);
12242 if (need_cvt)
12244 t = make_ssa_name (orig_arg, NULL);
12245 g = gimple_build_assign_with_ops (NOP_EXPR, t,
12246 gimple_call_lhs (g));
12247 gimple_seq_add_stmt_without_update (&seq, g);
12249 gsi_insert_seq_on_edge_immediate
12250 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
12252 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12253 int freq = compute_call_stmt_bb_frequency (current_function_decl,
12254 entry_bb);
12255 node->create_edge (cgraph_node::get_create (fn),
12256 call, entry_bb->count, freq);
12258 imm_use_iterator iter;
12259 use_operand_p use_p;
12260 gimple use_stmt;
12261 tree repl = gimple_get_lhs (g);
12262 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12263 if (is_gimple_debug (use_stmt) || use_stmt == call)
12264 continue;
12265 else
12266 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12267 SET_USE (use_p, repl);
12270 else if (node->simdclone->args[i].arg_type
12271 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12273 tree orig_arg = node->simdclone->args[i].orig_arg;
12274 tree def = ssa_default_def (cfun, orig_arg);
12275 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12276 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
12277 if (def && !has_zero_uses (def))
12279 iter1 = make_ssa_name (orig_arg, NULL);
12280 iter2 = make_ssa_name (orig_arg, NULL);
12281 phi = create_phi_node (iter1, body_bb);
12282 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
12283 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12284 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12285 ? PLUS_EXPR : POINTER_PLUS_EXPR;
12286 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12287 ? TREE_TYPE (orig_arg) : sizetype;
12288 tree addcst
12289 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
12290 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
12291 gsi = gsi_last_bb (incr_bb);
12292 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12294 imm_use_iterator iter;
12295 use_operand_p use_p;
12296 gimple use_stmt;
12297 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12298 if (use_stmt == phi)
12299 continue;
12300 else
12301 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12302 SET_USE (use_p, iter1);
12306 calculate_dominance_info (CDI_DOMINATORS);
12307 add_loop (loop, loop->header->loop_father);
12308 update_ssa (TODO_update_ssa);
12310 pop_cfun ();
12313 /* If the function in NODE is tagged as an elemental SIMD function,
12314 create the appropriate SIMD clones. */
12316 static void
12317 expand_simd_clones (struct cgraph_node *node)
12319 tree attr = lookup_attribute ("omp declare simd",
12320 DECL_ATTRIBUTES (node->decl));
12321 if (attr == NULL_TREE
12322 || node->global.inlined_to
12323 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
12324 return;
12326 /* Ignore
12327 #pragma omp declare simd
12328 extern int foo ();
12329 in C, there we don't know the argument types at all. */
12330 if (!node->definition
12331 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
12332 return;
12336 /* Start with parsing the "omp declare simd" attribute(s). */
12337 bool inbranch_clause_specified;
12338 struct cgraph_simd_clone *clone_info
12339 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
12340 &inbranch_clause_specified);
12341 if (clone_info == NULL)
12342 continue;
12344 int orig_simdlen = clone_info->simdlen;
12345 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
12346 /* The target can return 0 (no simd clones should be created),
12347 1 (just one ISA of simd clones should be created) or higher
12348 count of ISA variants. In that case, clone_info is initialized
12349 for the first ISA variant. */
12350 int count
12351 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
12352 base_type, 0);
12353 if (count == 0)
12354 continue;
12356 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12357 also create one inbranch and one !inbranch clone of it. */
12358 for (int i = 0; i < count * 2; i++)
12360 struct cgraph_simd_clone *clone = clone_info;
12361 if (inbranch_clause_specified && (i & 1) != 0)
12362 continue;
12364 if (i != 0)
12366 clone = simd_clone_struct_alloc (clone_info->nargs
12367 + ((i & 1) != 0));
12368 simd_clone_struct_copy (clone, clone_info);
12369 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12370 and simd_clone_adjust_argument_types did to the first
12371 clone's info. */
12372 clone->nargs -= clone_info->inbranch;
12373 clone->simdlen = orig_simdlen;
12374 /* And call the target hook again to get the right ISA. */
12375 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
12376 base_type,
12377 i / 2);
12378 if ((i & 1) != 0)
12379 clone->inbranch = 1;
12382 /* simd_clone_mangle might fail if such a clone has been created
12383 already. */
12384 tree id = simd_clone_mangle (node, clone);
12385 if (id == NULL_TREE)
12386 continue;
12388 /* Only when we are sure we want to create the clone actually
12389 clone the function (or definitions) or create another
12390 extern FUNCTION_DECL (for prototypes without definitions). */
12391 struct cgraph_node *n = simd_clone_create (node);
12392 if (n == NULL)
12393 continue;
12395 n->simdclone = clone;
12396 clone->origin = node;
12397 clone->next_clone = NULL;
12398 if (node->simd_clones == NULL)
12400 clone->prev_clone = n;
12401 node->simd_clones = n;
12403 else
12405 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
12406 clone->prev_clone->simdclone->next_clone = n;
12407 node->simd_clones->simdclone->prev_clone = n;
12409 symtab->change_decl_assembler_name (n->decl, id);
12410 /* And finally adjust the return type, parameters and for
12411 definitions also function body. */
12412 if (node->definition)
12413 simd_clone_adjust (n);
12414 else
12416 simd_clone_adjust_return_type (n);
12417 simd_clone_adjust_argument_types (n);
12421 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
12424 /* Entry point for IPA simd clone creation pass. */
12426 static unsigned int
12427 ipa_omp_simd_clone (void)
12429 struct cgraph_node *node;
12430 FOR_EACH_FUNCTION (node)
12431 expand_simd_clones (node);
12432 return 0;
12435 namespace {
12437 const pass_data pass_data_omp_simd_clone =
12439 SIMPLE_IPA_PASS, /* type */
12440 "simdclone", /* name */
12441 OPTGROUP_NONE, /* optinfo_flags */
12442 TV_NONE, /* tv_id */
12443 ( PROP_ssa | PROP_cfg ), /* properties_required */
12444 0, /* properties_provided */
12445 0, /* properties_destroyed */
12446 0, /* todo_flags_start */
12447 0, /* todo_flags_finish */
12450 class pass_omp_simd_clone : public simple_ipa_opt_pass
12452 public:
12453 pass_omp_simd_clone(gcc::context *ctxt)
12454 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
12457 /* opt_pass methods: */
12458 virtual bool gate (function *);
12459 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
12462 bool
12463 pass_omp_simd_clone::gate (function *)
12465 return ((flag_openmp || flag_openmp_simd
12466 || flag_cilkplus
12467 || (in_lto_p && !flag_wpa))
12468 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
12471 } // anon namespace
12473 simple_ipa_opt_pass *
12474 make_pass_omp_simd_clone (gcc::context *ctxt)
12476 return new pass_omp_simd_clone (ctxt);
12479 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
12480 adds their addresses and sizes to constructor-vector V_CTOR. */
12481 static void
12482 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
12483 vec<constructor_elt, va_gc> *v_ctor)
12485 unsigned len = vec_safe_length (v_decls);
12486 for (unsigned i = 0; i < len; i++)
12488 tree it = (*v_decls)[i];
12489 bool is_function = TREE_CODE (it) != VAR_DECL;
12491 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
12492 if (!is_function)
12493 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
12494 fold_convert (const_ptr_type_node,
12495 DECL_SIZE_UNIT (it)));
12499 /* Create new symbols containing (address, size) pairs for global variables,
12500 marked with "omp declare target" attribute, as well as addresses for the
12501 functions, which are outlined target regions. */
12502 void
12503 omp_finish_file (void)
12505 unsigned num_funcs = vec_safe_length (offload_funcs);
12506 unsigned num_vars = vec_safe_length (offload_vars);
12508 if (num_funcs == 0 && num_vars == 0)
12509 return;
12511 if (targetm_common.have_named_sections)
12513 vec<constructor_elt, va_gc> *v_f, *v_v;
12514 vec_alloc (v_f, num_funcs);
12515 vec_alloc (v_v, num_vars * 2);
12517 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
12518 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
12520 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
12521 num_vars * 2);
12522 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
12523 num_funcs);
12524 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
12525 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
12526 tree ctor_v = build_constructor (vars_decl_type, v_v);
12527 tree ctor_f = build_constructor (funcs_decl_type, v_f);
12528 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
12529 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
12530 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
12531 get_identifier (".offload_func_table"),
12532 funcs_decl_type);
12533 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
12534 get_identifier (".offload_var_table"),
12535 vars_decl_type);
12536 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
12537 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
12538 otherwise a joint table in a binary will contain padding between
12539 tables from multiple object files. */
12540 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
12541 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
12542 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
12543 DECL_INITIAL (funcs_decl) = ctor_f;
12544 DECL_INITIAL (vars_decl) = ctor_v;
12545 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
12546 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
12548 varpool_node::finalize_decl (vars_decl);
12549 varpool_node::finalize_decl (funcs_decl);
12551 else
12553 for (unsigned i = 0; i < num_funcs; i++)
12555 tree it = (*offload_funcs)[i];
12556 targetm.record_offload_symbol (it);
12558 for (unsigned i = 0; i < num_vars; i++)
12560 tree it = (*offload_vars)[i];
12561 targetm.record_offload_symbol (it);
12566 #include "gt-omp-low.h"