Merge branch 'master' r216746-r217593 into gimple-classes-v2-option-3
[official-gcc.git] / gcc / omp-low.c
blobc9bf9bd155392bd6ff39a7cf245e81454830a352
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) = build_pointer_type (type);
1523 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1524 specified by CLAUSES. */
1526 static void
1527 scan_sharing_clauses (tree clauses, omp_context *ctx)
1529 tree c, decl;
1530 bool scan_array_reductions = false;
1532 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1534 bool by_ref;
1536 switch (OMP_CLAUSE_CODE (c))
1538 case OMP_CLAUSE_PRIVATE:
1539 decl = OMP_CLAUSE_DECL (c);
1540 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1541 goto do_private;
1542 else if (!is_variable_sized (decl))
1543 install_var_local (decl, ctx);
1544 break;
1546 case OMP_CLAUSE_SHARED:
1547 decl = OMP_CLAUSE_DECL (c);
1548 /* Ignore shared directives in teams construct. */
1549 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1551 /* Global variables don't need to be copied,
1552 the receiver side will use them directly. */
1553 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1554 if (is_global_var (odecl))
1555 break;
1556 insert_decl_map (&ctx->cb, decl, odecl);
1557 break;
1559 gcc_assert (is_taskreg_ctx (ctx));
1560 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1561 || !is_variable_sized (decl));
1562 /* Global variables don't need to be copied,
1563 the receiver side will use them directly. */
1564 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1565 break;
1566 by_ref = use_pointer_for_field (decl, ctx);
1567 if (! TREE_READONLY (decl)
1568 || TREE_ADDRESSABLE (decl)
1569 || by_ref
1570 || is_reference (decl))
1572 install_var_field (decl, by_ref, 3, ctx);
1573 install_var_local (decl, ctx);
1574 break;
1576 /* We don't need to copy const scalar vars back. */
1577 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1578 goto do_private;
1580 case OMP_CLAUSE_LASTPRIVATE:
1581 /* Let the corresponding firstprivate clause create
1582 the variable. */
1583 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1584 break;
1585 /* FALLTHRU */
1587 case OMP_CLAUSE_FIRSTPRIVATE:
1588 case OMP_CLAUSE_REDUCTION:
1589 case OMP_CLAUSE_LINEAR:
1590 decl = OMP_CLAUSE_DECL (c);
1591 do_private:
1592 if (is_variable_sized (decl))
1594 if (is_task_ctx (ctx))
1595 install_var_field (decl, false, 1, ctx);
1596 break;
1598 else if (is_taskreg_ctx (ctx))
1600 bool global
1601 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1602 by_ref = use_pointer_for_field (decl, NULL);
1604 if (is_task_ctx (ctx)
1605 && (global || by_ref || is_reference (decl)))
1607 install_var_field (decl, false, 1, ctx);
1608 if (!global)
1609 install_var_field (decl, by_ref, 2, ctx);
1611 else if (!global)
1612 install_var_field (decl, by_ref, 3, ctx);
1614 install_var_local (decl, ctx);
1615 break;
1617 case OMP_CLAUSE__LOOPTEMP_:
1618 gcc_assert (is_parallel_ctx (ctx));
1619 decl = OMP_CLAUSE_DECL (c);
1620 install_var_field (decl, false, 3, ctx);
1621 install_var_local (decl, ctx);
1622 break;
1624 case OMP_CLAUSE_COPYPRIVATE:
1625 case OMP_CLAUSE_COPYIN:
1626 decl = OMP_CLAUSE_DECL (c);
1627 by_ref = use_pointer_for_field (decl, NULL);
1628 install_var_field (decl, by_ref, 3, ctx);
1629 break;
1631 case OMP_CLAUSE_DEFAULT:
1632 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1633 break;
1635 case OMP_CLAUSE_FINAL:
1636 case OMP_CLAUSE_IF:
1637 case OMP_CLAUSE_NUM_THREADS:
1638 case OMP_CLAUSE_NUM_TEAMS:
1639 case OMP_CLAUSE_THREAD_LIMIT:
1640 case OMP_CLAUSE_DEVICE:
1641 case OMP_CLAUSE_SCHEDULE:
1642 case OMP_CLAUSE_DIST_SCHEDULE:
1643 case OMP_CLAUSE_DEPEND:
1644 case OMP_CLAUSE__CILK_FOR_COUNT_:
1645 if (ctx->outer)
1646 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1647 break;
1649 case OMP_CLAUSE_TO:
1650 case OMP_CLAUSE_FROM:
1651 case OMP_CLAUSE_MAP:
1652 if (ctx->outer)
1653 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1654 decl = OMP_CLAUSE_DECL (c);
1655 /* Global variables with "omp declare target" attribute
1656 don't need to be copied, the receiver side will use them
1657 directly. */
1658 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1659 && DECL_P (decl)
1660 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1661 && varpool_node::get_create (decl)->offloadable)
1662 break;
1663 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1664 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1666 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1667 #pragma omp target data, there is nothing to map for
1668 those. */
1669 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1670 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1671 break;
1673 if (DECL_P (decl))
1675 if (DECL_SIZE (decl)
1676 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1678 tree decl2 = DECL_VALUE_EXPR (decl);
1679 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1680 decl2 = TREE_OPERAND (decl2, 0);
1681 gcc_assert (DECL_P (decl2));
1682 install_var_field (decl2, true, 3, ctx);
1683 install_var_local (decl2, ctx);
1684 install_var_local (decl, ctx);
1686 else
1688 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1689 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1690 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1691 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1692 install_var_field (decl, true, 7, ctx);
1693 else
1694 install_var_field (decl, true, 3, ctx);
1695 if (gimple_omp_target_kind (ctx->stmt)
1696 == GF_OMP_TARGET_KIND_REGION)
1697 install_var_local (decl, ctx);
1700 else
1702 tree base = get_base_address (decl);
1703 tree nc = OMP_CLAUSE_CHAIN (c);
1704 if (DECL_P (base)
1705 && nc != NULL_TREE
1706 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1707 && OMP_CLAUSE_DECL (nc) == base
1708 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1709 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1711 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1712 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1714 else
1716 if (ctx->outer)
1718 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1719 decl = OMP_CLAUSE_DECL (c);
1721 gcc_assert (!splay_tree_lookup (ctx->field_map,
1722 (splay_tree_key) decl));
1723 tree field
1724 = build_decl (OMP_CLAUSE_LOCATION (c),
1725 FIELD_DECL, NULL_TREE, ptr_type_node);
1726 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1727 insert_field_into_struct (ctx->record_type, field);
1728 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1729 (splay_tree_value) field);
1732 break;
1734 case OMP_CLAUSE_NOWAIT:
1735 case OMP_CLAUSE_ORDERED:
1736 case OMP_CLAUSE_COLLAPSE:
1737 case OMP_CLAUSE_UNTIED:
1738 case OMP_CLAUSE_MERGEABLE:
1739 case OMP_CLAUSE_PROC_BIND:
1740 case OMP_CLAUSE_SAFELEN:
1741 break;
1743 case OMP_CLAUSE_ALIGNED:
1744 decl = OMP_CLAUSE_DECL (c);
1745 if (is_global_var (decl)
1746 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1747 install_var_local (decl, ctx);
1748 break;
1750 default:
1751 gcc_unreachable ();
1755 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1757 switch (OMP_CLAUSE_CODE (c))
1759 case OMP_CLAUSE_LASTPRIVATE:
1760 /* Let the corresponding firstprivate clause create
1761 the variable. */
1762 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1763 scan_array_reductions = true;
1764 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1765 break;
1766 /* FALLTHRU */
1768 case OMP_CLAUSE_PRIVATE:
1769 case OMP_CLAUSE_FIRSTPRIVATE:
1770 case OMP_CLAUSE_REDUCTION:
1771 case OMP_CLAUSE_LINEAR:
1772 decl = OMP_CLAUSE_DECL (c);
1773 if (is_variable_sized (decl))
1774 install_var_local (decl, ctx);
1775 fixup_remapped_decl (decl, ctx,
1776 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1777 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1778 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1779 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1780 scan_array_reductions = true;
1781 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1782 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1783 scan_array_reductions = true;
1784 break;
1786 case OMP_CLAUSE_SHARED:
1787 /* Ignore shared directives in teams construct. */
1788 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1789 break;
1790 decl = OMP_CLAUSE_DECL (c);
1791 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1792 fixup_remapped_decl (decl, ctx, false);
1793 break;
1795 case OMP_CLAUSE_MAP:
1796 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1797 break;
1798 decl = OMP_CLAUSE_DECL (c);
1799 if (DECL_P (decl)
1800 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1801 && varpool_node::get_create (decl)->offloadable)
1802 break;
1803 if (DECL_P (decl))
1805 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1806 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1807 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1809 tree new_decl = lookup_decl (decl, ctx);
1810 TREE_TYPE (new_decl)
1811 = remap_type (TREE_TYPE (decl), &ctx->cb);
1813 else if (DECL_SIZE (decl)
1814 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1816 tree decl2 = DECL_VALUE_EXPR (decl);
1817 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1818 decl2 = TREE_OPERAND (decl2, 0);
1819 gcc_assert (DECL_P (decl2));
1820 fixup_remapped_decl (decl2, ctx, false);
1821 fixup_remapped_decl (decl, ctx, true);
1823 else
1824 fixup_remapped_decl (decl, ctx, false);
1826 break;
1828 case OMP_CLAUSE_COPYPRIVATE:
1829 case OMP_CLAUSE_COPYIN:
1830 case OMP_CLAUSE_DEFAULT:
1831 case OMP_CLAUSE_IF:
1832 case OMP_CLAUSE_NUM_THREADS:
1833 case OMP_CLAUSE_NUM_TEAMS:
1834 case OMP_CLAUSE_THREAD_LIMIT:
1835 case OMP_CLAUSE_DEVICE:
1836 case OMP_CLAUSE_SCHEDULE:
1837 case OMP_CLAUSE_DIST_SCHEDULE:
1838 case OMP_CLAUSE_NOWAIT:
1839 case OMP_CLAUSE_ORDERED:
1840 case OMP_CLAUSE_COLLAPSE:
1841 case OMP_CLAUSE_UNTIED:
1842 case OMP_CLAUSE_FINAL:
1843 case OMP_CLAUSE_MERGEABLE:
1844 case OMP_CLAUSE_PROC_BIND:
1845 case OMP_CLAUSE_SAFELEN:
1846 case OMP_CLAUSE_ALIGNED:
1847 case OMP_CLAUSE_DEPEND:
1848 case OMP_CLAUSE__LOOPTEMP_:
1849 case OMP_CLAUSE_TO:
1850 case OMP_CLAUSE_FROM:
1851 case OMP_CLAUSE__CILK_FOR_COUNT_:
1852 break;
1854 default:
1855 gcc_unreachable ();
1859 if (scan_array_reductions)
1860 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1861 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1862 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1864 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1865 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1867 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1868 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1869 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1870 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1871 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1872 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1875 /* Create a new name for omp child function. Returns an identifier. If
1876 IS_CILK_FOR is true then the suffix for the child function is
1877 "_cilk_for_fn." */
1879 static tree
1880 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1882 if (is_cilk_for)
1883 return clone_function_name (current_function_decl, "_cilk_for_fn");
1884 return clone_function_name (current_function_decl,
1885 task_copy ? "_omp_cpyfn" : "_omp_fn");
1888 /* Returns the type of the induction variable for the child function for
1889 _Cilk_for and the types for _high and _low variables based on TYPE. */
1891 static tree
1892 cilk_for_check_loop_diff_type (tree type)
1894 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
1896 if (TYPE_UNSIGNED (type))
1897 return uint32_type_node;
1898 else
1899 return integer_type_node;
1901 else
1903 if (TYPE_UNSIGNED (type))
1904 return uint64_type_node;
1905 else
1906 return long_long_integer_type_node;
1910 /* Build a decl for the omp child function. It'll not contain a body
1911 yet, just the bare decl. */
1913 static void
1914 create_omp_child_function (omp_context *ctx, bool task_copy)
1916 tree decl, type, name, t;
1918 tree cilk_for_count
1919 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
1920 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1921 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
1922 tree cilk_var_type = NULL_TREE;
1924 name = create_omp_child_function_name (task_copy,
1925 cilk_for_count != NULL_TREE);
1926 if (task_copy)
1927 type = build_function_type_list (void_type_node, ptr_type_node,
1928 ptr_type_node, NULL_TREE);
1929 else if (cilk_for_count)
1931 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
1932 cilk_var_type = cilk_for_check_loop_diff_type (type);
1933 type = build_function_type_list (void_type_node, ptr_type_node,
1934 cilk_var_type, cilk_var_type, NULL_TREE);
1936 else
1937 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1939 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1941 if (!task_copy)
1942 ctx->cb.dst_fn = decl;
1943 else
1944 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1946 TREE_STATIC (decl) = 1;
1947 TREE_USED (decl) = 1;
1948 DECL_ARTIFICIAL (decl) = 1;
1949 DECL_IGNORED_P (decl) = 0;
1950 TREE_PUBLIC (decl) = 0;
1951 DECL_UNINLINABLE (decl) = 1;
1952 DECL_EXTERNAL (decl) = 0;
1953 DECL_CONTEXT (decl) = NULL_TREE;
1954 DECL_INITIAL (decl) = make_node (BLOCK);
1955 if (cgraph_node::get (current_function_decl)->offloadable)
1956 cgraph_node::get_create (decl)->offloadable = 1;
1957 else
1959 omp_context *octx;
1960 for (octx = ctx; octx; octx = octx->outer)
1961 if (is_targetreg_ctx (octx))
1963 cgraph_node::get_create (decl)->offloadable = 1;
1964 g->have_offload = true;
1965 break;
1969 t = build_decl (DECL_SOURCE_LOCATION (decl),
1970 RESULT_DECL, NULL_TREE, void_type_node);
1971 DECL_ARTIFICIAL (t) = 1;
1972 DECL_IGNORED_P (t) = 1;
1973 DECL_CONTEXT (t) = decl;
1974 DECL_RESULT (decl) = t;
1976 /* _Cilk_for's child function requires two extra parameters called
1977 __low and __high that are set the by Cilk runtime when it calls this
1978 function. */
1979 if (cilk_for_count)
1981 t = build_decl (DECL_SOURCE_LOCATION (decl),
1982 PARM_DECL, get_identifier ("__high"), cilk_var_type);
1983 DECL_ARTIFICIAL (t) = 1;
1984 DECL_NAMELESS (t) = 1;
1985 DECL_ARG_TYPE (t) = ptr_type_node;
1986 DECL_CONTEXT (t) = current_function_decl;
1987 TREE_USED (t) = 1;
1988 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1989 DECL_ARGUMENTS (decl) = t;
1991 t = build_decl (DECL_SOURCE_LOCATION (decl),
1992 PARM_DECL, get_identifier ("__low"), cilk_var_type);
1993 DECL_ARTIFICIAL (t) = 1;
1994 DECL_NAMELESS (t) = 1;
1995 DECL_ARG_TYPE (t) = ptr_type_node;
1996 DECL_CONTEXT (t) = current_function_decl;
1997 TREE_USED (t) = 1;
1998 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1999 DECL_ARGUMENTS (decl) = t;
2002 tree data_name = get_identifier (".omp_data_i");
2003 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2004 ptr_type_node);
2005 DECL_ARTIFICIAL (t) = 1;
2006 DECL_NAMELESS (t) = 1;
2007 DECL_ARG_TYPE (t) = ptr_type_node;
2008 DECL_CONTEXT (t) = current_function_decl;
2009 TREE_USED (t) = 1;
2010 if (cilk_for_count)
2011 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2012 DECL_ARGUMENTS (decl) = t;
2013 if (!task_copy)
2014 ctx->receiver_decl = t;
2015 else
2017 t = build_decl (DECL_SOURCE_LOCATION (decl),
2018 PARM_DECL, get_identifier (".omp_data_o"),
2019 ptr_type_node);
2020 DECL_ARTIFICIAL (t) = 1;
2021 DECL_NAMELESS (t) = 1;
2022 DECL_ARG_TYPE (t) = ptr_type_node;
2023 DECL_CONTEXT (t) = current_function_decl;
2024 TREE_USED (t) = 1;
2025 TREE_ADDRESSABLE (t) = 1;
2026 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2027 DECL_ARGUMENTS (decl) = t;
2030 /* Allocate memory for the function structure. The call to
2031 allocate_struct_function clobbers CFUN, so we need to restore
2032 it afterward. */
2033 push_struct_function (decl);
2034 cfun->function_end_locus = gimple_location (ctx->stmt);
2035 pop_cfun ();
2038 /* Callback for walk_gimple_seq. Check if combined parallel
2039 contains gimple_omp_for_combined_into_p OMP_FOR. */
2041 static tree
2042 find_combined_for (gimple_stmt_iterator *gsi_p,
2043 bool *handled_ops_p,
2044 struct walk_stmt_info *wi)
2046 gimple stmt = gsi_stmt (*gsi_p);
2048 *handled_ops_p = true;
2049 switch (gimple_code (stmt))
2051 WALK_SUBSTMTS;
2053 case GIMPLE_OMP_FOR:
2054 if (gimple_omp_for_combined_into_p (stmt)
2055 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2057 wi->info = stmt;
2058 return integer_zero_node;
2060 break;
2061 default:
2062 break;
2064 return NULL;
2067 /* Scan an OpenMP parallel directive. */
2069 static void
2070 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2072 omp_context *ctx;
2073 tree name;
2074 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2076 /* Ignore parallel directives with empty bodies, unless there
2077 are copyin clauses. */
2078 if (optimize > 0
2079 && empty_body_p (gimple_omp_body (stmt))
2080 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2081 OMP_CLAUSE_COPYIN) == NULL)
2083 gsi_replace (gsi, gimple_build_nop (), false);
2084 return;
2087 if (gimple_omp_parallel_combined_p (stmt))
2089 struct walk_stmt_info wi;
2091 memset (&wi, 0, sizeof (wi));
2092 wi.val_only = true;
2093 walk_gimple_seq (gimple_omp_body (stmt),
2094 find_combined_for, NULL, &wi);
2095 if (wi.info)
2097 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2098 struct omp_for_data fd;
2099 extract_omp_for_data (for_stmt, &fd, NULL);
2100 /* We need two temporaries with fd.loop.v type (istart/iend)
2101 and then (fd.collapse - 1) temporaries with the same
2102 type for count2 ... countN-1 vars if not constant. */
2103 size_t count = 2, i;
2104 tree type = fd.iter_type;
2105 if (fd.collapse > 1
2106 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2107 count += fd.collapse - 1;
2108 for (i = 0; i < count; i++)
2110 tree temp = create_tmp_var (type, NULL);
2111 tree c = build_omp_clause (UNKNOWN_LOCATION,
2112 OMP_CLAUSE__LOOPTEMP_);
2113 insert_decl_map (&outer_ctx->cb, temp, temp);
2114 OMP_CLAUSE_DECL (c) = temp;
2115 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2116 gimple_omp_parallel_set_clauses (stmt, c);
2121 ctx = new_omp_context (stmt, outer_ctx);
2122 taskreg_contexts.safe_push (ctx);
2123 if (taskreg_nesting_level > 1)
2124 ctx->is_nested = true;
2125 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2126 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2127 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2128 name = create_tmp_var_name (".omp_data_s");
2129 name = build_decl (gimple_location (stmt),
2130 TYPE_DECL, name, ctx->record_type);
2131 DECL_ARTIFICIAL (name) = 1;
2132 DECL_NAMELESS (name) = 1;
2133 TYPE_NAME (ctx->record_type) = name;
2134 create_omp_child_function (ctx, false);
2135 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2137 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2138 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2140 if (TYPE_FIELDS (ctx->record_type) == NULL)
2141 ctx->record_type = ctx->receiver_decl = NULL;
2144 /* Scan an OpenMP task directive. */
2146 static void
2147 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2149 omp_context *ctx;
2150 tree name, t;
2151 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2153 /* Ignore task directives with empty bodies. */
2154 if (optimize > 0
2155 && empty_body_p (gimple_omp_body (stmt)))
2157 gsi_replace (gsi, gimple_build_nop (), false);
2158 return;
2161 ctx = new_omp_context (stmt, outer_ctx);
2162 taskreg_contexts.safe_push (ctx);
2163 if (taskreg_nesting_level > 1)
2164 ctx->is_nested = true;
2165 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2166 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2167 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2168 name = create_tmp_var_name (".omp_data_s");
2169 name = build_decl (gimple_location (stmt),
2170 TYPE_DECL, name, ctx->record_type);
2171 DECL_ARTIFICIAL (name) = 1;
2172 DECL_NAMELESS (name) = 1;
2173 TYPE_NAME (ctx->record_type) = name;
2174 create_omp_child_function (ctx, false);
2175 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2177 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2179 if (ctx->srecord_type)
2181 name = create_tmp_var_name (".omp_data_a");
2182 name = build_decl (gimple_location (stmt),
2183 TYPE_DECL, name, ctx->srecord_type);
2184 DECL_ARTIFICIAL (name) = 1;
2185 DECL_NAMELESS (name) = 1;
2186 TYPE_NAME (ctx->srecord_type) = name;
2187 create_omp_child_function (ctx, true);
2190 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2192 if (TYPE_FIELDS (ctx->record_type) == NULL)
2194 ctx->record_type = ctx->receiver_decl = NULL;
2195 t = build_int_cst (long_integer_type_node, 0);
2196 gimple_omp_task_set_arg_size (stmt, t);
2197 t = build_int_cst (long_integer_type_node, 1);
2198 gimple_omp_task_set_arg_align (stmt, t);
2203 /* If any decls have been made addressable during scan_omp,
2204 adjust their fields if needed, and layout record types
2205 of parallel/task constructs. */
2207 static void
2208 finish_taskreg_scan (omp_context *ctx)
2210 if (ctx->record_type == NULL_TREE)
2211 return;
2213 /* If any task_shared_vars were needed, verify all
2214 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2215 statements if use_pointer_for_field hasn't changed
2216 because of that. If it did, update field types now. */
2217 if (task_shared_vars)
2219 tree c;
2221 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2222 c; c = OMP_CLAUSE_CHAIN (c))
2223 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2225 tree decl = OMP_CLAUSE_DECL (c);
2227 /* Global variables don't need to be copied,
2228 the receiver side will use them directly. */
2229 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2230 continue;
2231 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2232 || !use_pointer_for_field (decl, ctx))
2233 continue;
2234 tree field = lookup_field (decl, ctx);
2235 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2236 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2237 continue;
2238 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2239 TREE_THIS_VOLATILE (field) = 0;
2240 DECL_USER_ALIGN (field) = 0;
2241 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2242 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2243 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2244 if (ctx->srecord_type)
2246 tree sfield = lookup_sfield (decl, ctx);
2247 TREE_TYPE (sfield) = TREE_TYPE (field);
2248 TREE_THIS_VOLATILE (sfield) = 0;
2249 DECL_USER_ALIGN (sfield) = 0;
2250 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2251 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2252 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2257 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2259 layout_type (ctx->record_type);
2260 fixup_child_record_type (ctx);
2262 else
2264 location_t loc = gimple_location (ctx->stmt);
2265 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2266 /* Move VLA fields to the end. */
2267 p = &TYPE_FIELDS (ctx->record_type);
2268 while (*p)
2269 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2270 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2272 *q = *p;
2273 *p = TREE_CHAIN (*p);
2274 TREE_CHAIN (*q) = NULL_TREE;
2275 q = &TREE_CHAIN (*q);
2277 else
2278 p = &DECL_CHAIN (*p);
2279 *p = vla_fields;
2280 layout_type (ctx->record_type);
2281 fixup_child_record_type (ctx);
2282 if (ctx->srecord_type)
2283 layout_type (ctx->srecord_type);
2284 tree t = fold_convert_loc (loc, long_integer_type_node,
2285 TYPE_SIZE_UNIT (ctx->record_type));
2286 gimple_omp_task_set_arg_size (ctx->stmt, t);
2287 t = build_int_cst (long_integer_type_node,
2288 TYPE_ALIGN_UNIT (ctx->record_type));
2289 gimple_omp_task_set_arg_align (ctx->stmt, t);
2294 /* Scan an OpenMP loop directive. */
2296 static void
2297 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2299 omp_context *ctx;
2300 size_t i;
2302 ctx = new_omp_context (stmt, outer_ctx);
2304 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2306 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2307 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2309 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2310 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2311 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2312 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2314 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2317 /* Scan an OpenMP sections directive. */
2319 static void
2320 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2322 omp_context *ctx;
2324 ctx = new_omp_context (stmt, outer_ctx);
2325 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2326 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2329 /* Scan an OpenMP single directive. */
2331 static void
2332 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2334 omp_context *ctx;
2335 tree name;
2337 ctx = new_omp_context (stmt, outer_ctx);
2338 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2339 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2340 name = create_tmp_var_name (".omp_copy_s");
2341 name = build_decl (gimple_location (stmt),
2342 TYPE_DECL, name, ctx->record_type);
2343 TYPE_NAME (ctx->record_type) = name;
2345 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2346 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2348 if (TYPE_FIELDS (ctx->record_type) == NULL)
2349 ctx->record_type = NULL;
2350 else
2351 layout_type (ctx->record_type);
2354 /* Scan an OpenMP target{, data, update} directive. */
2356 static void
2357 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2359 omp_context *ctx;
2360 tree name;
2361 int kind = gimple_omp_target_kind (stmt);
2363 ctx = new_omp_context (stmt, outer_ctx);
2364 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2365 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2366 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2367 name = create_tmp_var_name (".omp_data_t");
2368 name = build_decl (gimple_location (stmt),
2369 TYPE_DECL, name, ctx->record_type);
2370 DECL_ARTIFICIAL (name) = 1;
2371 DECL_NAMELESS (name) = 1;
2372 TYPE_NAME (ctx->record_type) = name;
2373 if (kind == GF_OMP_TARGET_KIND_REGION)
2375 create_omp_child_function (ctx, false);
2376 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2379 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2380 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2382 if (TYPE_FIELDS (ctx->record_type) == NULL)
2383 ctx->record_type = ctx->receiver_decl = NULL;
2384 else
2386 TYPE_FIELDS (ctx->record_type)
2387 = nreverse (TYPE_FIELDS (ctx->record_type));
2388 #ifdef ENABLE_CHECKING
2389 tree field;
2390 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2391 for (field = TYPE_FIELDS (ctx->record_type);
2392 field;
2393 field = DECL_CHAIN (field))
2394 gcc_assert (DECL_ALIGN (field) == align);
2395 #endif
2396 layout_type (ctx->record_type);
2397 if (kind == GF_OMP_TARGET_KIND_REGION)
2398 fixup_child_record_type (ctx);
2402 /* Scan an OpenMP teams directive. */
2404 static void
2405 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2407 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2408 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2409 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2412 /* Check OpenMP nesting restrictions. */
2413 static bool
2414 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2416 if (ctx != NULL)
2418 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2419 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2421 error_at (gimple_location (stmt),
2422 "OpenMP constructs may not be nested inside simd region");
2423 return false;
2425 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2427 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2428 || (gimple_omp_for_kind (stmt)
2429 != GF_OMP_FOR_KIND_DISTRIBUTE))
2430 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2432 error_at (gimple_location (stmt),
2433 "only distribute or parallel constructs are allowed to "
2434 "be closely nested inside teams construct");
2435 return false;
2439 switch (gimple_code (stmt))
2441 case GIMPLE_OMP_FOR:
2442 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2443 return true;
2444 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2446 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2448 error_at (gimple_location (stmt),
2449 "distribute construct must be closely nested inside "
2450 "teams construct");
2451 return false;
2453 return true;
2455 /* FALLTHRU */
2456 case GIMPLE_CALL:
2457 if (is_gimple_call (stmt)
2458 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2459 == BUILT_IN_GOMP_CANCEL
2460 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2461 == BUILT_IN_GOMP_CANCELLATION_POINT))
2463 const char *bad = NULL;
2464 const char *kind = NULL;
2465 if (ctx == NULL)
2467 error_at (gimple_location (stmt), "orphaned %qs construct",
2468 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2469 == BUILT_IN_GOMP_CANCEL
2470 ? "#pragma omp cancel"
2471 : "#pragma omp cancellation point");
2472 return false;
2474 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2475 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2476 : 0)
2478 case 1:
2479 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2480 bad = "#pragma omp parallel";
2481 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2482 == BUILT_IN_GOMP_CANCEL
2483 && !integer_zerop (gimple_call_arg (stmt, 1)))
2484 ctx->cancellable = true;
2485 kind = "parallel";
2486 break;
2487 case 2:
2488 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2489 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2490 bad = "#pragma omp for";
2491 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2492 == BUILT_IN_GOMP_CANCEL
2493 && !integer_zerop (gimple_call_arg (stmt, 1)))
2495 ctx->cancellable = true;
2496 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2497 OMP_CLAUSE_NOWAIT))
2498 warning_at (gimple_location (stmt), 0,
2499 "%<#pragma omp cancel for%> inside "
2500 "%<nowait%> for construct");
2501 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2502 OMP_CLAUSE_ORDERED))
2503 warning_at (gimple_location (stmt), 0,
2504 "%<#pragma omp cancel for%> inside "
2505 "%<ordered%> for construct");
2507 kind = "for";
2508 break;
2509 case 4:
2510 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2511 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2512 bad = "#pragma omp sections";
2513 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2514 == BUILT_IN_GOMP_CANCEL
2515 && !integer_zerop (gimple_call_arg (stmt, 1)))
2517 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2519 ctx->cancellable = true;
2520 if (find_omp_clause (gimple_omp_sections_clauses
2521 (ctx->stmt),
2522 OMP_CLAUSE_NOWAIT))
2523 warning_at (gimple_location (stmt), 0,
2524 "%<#pragma omp cancel sections%> inside "
2525 "%<nowait%> sections construct");
2527 else
2529 gcc_assert (ctx->outer
2530 && gimple_code (ctx->outer->stmt)
2531 == GIMPLE_OMP_SECTIONS);
2532 ctx->outer->cancellable = true;
2533 if (find_omp_clause (gimple_omp_sections_clauses
2534 (ctx->outer->stmt),
2535 OMP_CLAUSE_NOWAIT))
2536 warning_at (gimple_location (stmt), 0,
2537 "%<#pragma omp cancel sections%> inside "
2538 "%<nowait%> sections construct");
2541 kind = "sections";
2542 break;
2543 case 8:
2544 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2545 bad = "#pragma omp task";
2546 else
2547 ctx->cancellable = true;
2548 kind = "taskgroup";
2549 break;
2550 default:
2551 error_at (gimple_location (stmt), "invalid arguments");
2552 return false;
2554 if (bad)
2556 error_at (gimple_location (stmt),
2557 "%<%s %s%> construct not closely nested inside of %qs",
2558 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2559 == BUILT_IN_GOMP_CANCEL
2560 ? "#pragma omp cancel"
2561 : "#pragma omp cancellation point", kind, bad);
2562 return false;
2565 /* FALLTHRU */
2566 case GIMPLE_OMP_SECTIONS:
2567 case GIMPLE_OMP_SINGLE:
2568 for (; ctx != NULL; ctx = ctx->outer)
2569 switch (gimple_code (ctx->stmt))
2571 case GIMPLE_OMP_FOR:
2572 case GIMPLE_OMP_SECTIONS:
2573 case GIMPLE_OMP_SINGLE:
2574 case GIMPLE_OMP_ORDERED:
2575 case GIMPLE_OMP_MASTER:
2576 case GIMPLE_OMP_TASK:
2577 case GIMPLE_OMP_CRITICAL:
2578 if (is_gimple_call (stmt))
2580 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2581 != BUILT_IN_GOMP_BARRIER)
2582 return true;
2583 error_at (gimple_location (stmt),
2584 "barrier region may not be closely nested inside "
2585 "of work-sharing, critical, ordered, master or "
2586 "explicit task region");
2587 return false;
2589 error_at (gimple_location (stmt),
2590 "work-sharing region may not be closely nested inside "
2591 "of work-sharing, critical, ordered, master or explicit "
2592 "task region");
2593 return false;
2594 case GIMPLE_OMP_PARALLEL:
2595 return true;
2596 default:
2597 break;
2599 break;
2600 case GIMPLE_OMP_MASTER:
2601 for (; ctx != NULL; ctx = ctx->outer)
2602 switch (gimple_code (ctx->stmt))
2604 case GIMPLE_OMP_FOR:
2605 case GIMPLE_OMP_SECTIONS:
2606 case GIMPLE_OMP_SINGLE:
2607 case GIMPLE_OMP_TASK:
2608 error_at (gimple_location (stmt),
2609 "master region may not be closely nested inside "
2610 "of work-sharing or explicit task region");
2611 return false;
2612 case GIMPLE_OMP_PARALLEL:
2613 return true;
2614 default:
2615 break;
2617 break;
2618 case GIMPLE_OMP_ORDERED:
2619 for (; ctx != NULL; ctx = ctx->outer)
2620 switch (gimple_code (ctx->stmt))
2622 case GIMPLE_OMP_CRITICAL:
2623 case GIMPLE_OMP_TASK:
2624 error_at (gimple_location (stmt),
2625 "ordered region may not be closely nested inside "
2626 "of critical or explicit task region");
2627 return false;
2628 case GIMPLE_OMP_FOR:
2629 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2630 OMP_CLAUSE_ORDERED) == NULL)
2632 error_at (gimple_location (stmt),
2633 "ordered region must be closely nested inside "
2634 "a loop region with an ordered clause");
2635 return false;
2637 return true;
2638 case GIMPLE_OMP_PARALLEL:
2639 error_at (gimple_location (stmt),
2640 "ordered region must be closely nested inside "
2641 "a loop region with an ordered clause");
2642 return false;
2643 default:
2644 break;
2646 break;
2647 case GIMPLE_OMP_CRITICAL:
2649 tree this_stmt_name =
2650 gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2651 for (; ctx != NULL; ctx = ctx->outer)
2652 if (gomp_critical *other_crit =
2653 dyn_cast <gomp_critical *> (ctx->stmt))
2654 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2656 error_at (gimple_location (stmt),
2657 "critical region may not be nested inside a critical "
2658 "region with the same name");
2659 return false;
2662 break;
2663 case GIMPLE_OMP_TEAMS:
2664 if (ctx == NULL
2665 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2666 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2668 error_at (gimple_location (stmt),
2669 "teams construct not closely nested inside of target "
2670 "region");
2671 return false;
2673 break;
2674 case GIMPLE_OMP_TARGET:
2675 for (; ctx != NULL; ctx = ctx->outer)
2676 if (is_targetreg_ctx (ctx))
2678 const char *name;
2679 switch (gimple_omp_target_kind (stmt))
2681 case GF_OMP_TARGET_KIND_REGION: name = "target"; break;
2682 case GF_OMP_TARGET_KIND_DATA: name = "target data"; break;
2683 case GF_OMP_TARGET_KIND_UPDATE: name = "target update"; break;
2684 default: gcc_unreachable ();
2686 warning_at (gimple_location (stmt), 0,
2687 "%s construct inside of target region", name);
2689 break;
2690 default:
2691 break;
2693 return true;
2697 /* Helper function scan_omp.
2699 Callback for walk_tree or operators in walk_gimple_stmt used to
2700 scan for OpenMP directives in TP. */
2702 static tree
2703 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2705 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2706 omp_context *ctx = (omp_context *) wi->info;
2707 tree t = *tp;
2709 switch (TREE_CODE (t))
2711 case VAR_DECL:
2712 case PARM_DECL:
2713 case LABEL_DECL:
2714 case RESULT_DECL:
2715 if (ctx)
2716 *tp = remap_decl (t, &ctx->cb);
2717 break;
2719 default:
2720 if (ctx && TYPE_P (t))
2721 *tp = remap_type (t, &ctx->cb);
2722 else if (!DECL_P (t))
2724 *walk_subtrees = 1;
2725 if (ctx)
2727 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2728 if (tem != TREE_TYPE (t))
2730 if (TREE_CODE (t) == INTEGER_CST)
2731 *tp = wide_int_to_tree (tem, t);
2732 else
2733 TREE_TYPE (t) = tem;
2737 break;
2740 return NULL_TREE;
2743 /* Return true if FNDECL is a setjmp or a longjmp. */
2745 static bool
2746 setjmp_or_longjmp_p (const_tree fndecl)
2748 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2749 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2750 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2751 return true;
2753 tree declname = DECL_NAME (fndecl);
2754 if (!declname)
2755 return false;
2756 const char *name = IDENTIFIER_POINTER (declname);
2757 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2761 /* Helper function for scan_omp.
2763 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2764 the current statement in GSI. */
2766 static tree
2767 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2768 struct walk_stmt_info *wi)
2770 gimple stmt = gsi_stmt (*gsi);
2771 omp_context *ctx = (omp_context *) wi->info;
2773 if (gimple_has_location (stmt))
2774 input_location = gimple_location (stmt);
2776 /* Check the OpenMP nesting restrictions. */
2777 bool remove = false;
2778 if (is_gimple_omp (stmt))
2779 remove = !check_omp_nesting_restrictions (stmt, ctx);
2780 else if (is_gimple_call (stmt))
2782 tree fndecl = gimple_call_fndecl (stmt);
2783 if (fndecl)
2785 if (setjmp_or_longjmp_p (fndecl)
2786 && ctx
2787 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2788 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2790 remove = true;
2791 error_at (gimple_location (stmt),
2792 "setjmp/longjmp inside simd construct");
2794 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2795 switch (DECL_FUNCTION_CODE (fndecl))
2797 case BUILT_IN_GOMP_BARRIER:
2798 case BUILT_IN_GOMP_CANCEL:
2799 case BUILT_IN_GOMP_CANCELLATION_POINT:
2800 case BUILT_IN_GOMP_TASKYIELD:
2801 case BUILT_IN_GOMP_TASKWAIT:
2802 case BUILT_IN_GOMP_TASKGROUP_START:
2803 case BUILT_IN_GOMP_TASKGROUP_END:
2804 remove = !check_omp_nesting_restrictions (stmt, ctx);
2805 break;
2806 default:
2807 break;
2811 if (remove)
2813 stmt = gimple_build_nop ();
2814 gsi_replace (gsi, stmt, false);
2817 *handled_ops_p = true;
2819 switch (gimple_code (stmt))
2821 case GIMPLE_OMP_PARALLEL:
2822 taskreg_nesting_level++;
2823 scan_omp_parallel (gsi, ctx);
2824 taskreg_nesting_level--;
2825 break;
2827 case GIMPLE_OMP_TASK:
2828 taskreg_nesting_level++;
2829 scan_omp_task (gsi, ctx);
2830 taskreg_nesting_level--;
2831 break;
2833 case GIMPLE_OMP_FOR:
2834 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
2835 break;
2837 case GIMPLE_OMP_SECTIONS:
2838 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
2839 break;
2841 case GIMPLE_OMP_SINGLE:
2842 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
2843 break;
2845 case GIMPLE_OMP_SECTION:
2846 case GIMPLE_OMP_MASTER:
2847 case GIMPLE_OMP_TASKGROUP:
2848 case GIMPLE_OMP_ORDERED:
2849 case GIMPLE_OMP_CRITICAL:
2850 ctx = new_omp_context (stmt, ctx);
2851 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2852 break;
2854 case GIMPLE_OMP_TARGET:
2855 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
2856 break;
2858 case GIMPLE_OMP_TEAMS:
2859 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
2860 break;
2862 case GIMPLE_BIND:
2864 tree var;
2866 *handled_ops_p = false;
2867 if (ctx)
2868 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
2869 var ;
2870 var = DECL_CHAIN (var))
2871 insert_decl_map (&ctx->cb, var, var);
2873 break;
2874 default:
2875 *handled_ops_p = false;
2876 break;
2879 return NULL_TREE;
2883 /* Scan all the statements starting at the current statement. CTX
2884 contains context information about the OpenMP directives and
2885 clauses found during the scan. */
2887 static void
2888 scan_omp (gimple_seq *body_p, omp_context *ctx)
2890 location_t saved_location;
2891 struct walk_stmt_info wi;
2893 memset (&wi, 0, sizeof (wi));
2894 wi.info = ctx;
2895 wi.want_locations = true;
2897 saved_location = input_location;
2898 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2899 input_location = saved_location;
2902 /* Re-gimplification and code generation routines. */
2904 /* Build a call to GOMP_barrier. */
2906 static gimple
2907 build_omp_barrier (tree lhs)
2909 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2910 : BUILT_IN_GOMP_BARRIER);
2911 gcall *g = gimple_build_call (fndecl, 0);
2912 if (lhs)
2913 gimple_call_set_lhs (g, lhs);
2914 return g;
2917 /* If a context was created for STMT when it was scanned, return it. */
2919 static omp_context *
2920 maybe_lookup_ctx (gimple stmt)
2922 splay_tree_node n;
2923 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2924 return n ? (omp_context *) n->value : NULL;
2928 /* Find the mapping for DECL in CTX or the immediately enclosing
2929 context that has a mapping for DECL.
2931 If CTX is a nested parallel directive, we may have to use the decl
2932 mappings created in CTX's parent context. Suppose that we have the
2933 following parallel nesting (variable UIDs showed for clarity):
2935 iD.1562 = 0;
2936 #omp parallel shared(iD.1562) -> outer parallel
2937 iD.1562 = iD.1562 + 1;
2939 #omp parallel shared (iD.1562) -> inner parallel
2940 iD.1562 = iD.1562 - 1;
2942 Each parallel structure will create a distinct .omp_data_s structure
2943 for copying iD.1562 in/out of the directive:
2945 outer parallel .omp_data_s.1.i -> iD.1562
2946 inner parallel .omp_data_s.2.i -> iD.1562
2948 A shared variable mapping will produce a copy-out operation before
2949 the parallel directive and a copy-in operation after it. So, in
2950 this case we would have:
2952 iD.1562 = 0;
2953 .omp_data_o.1.i = iD.1562;
2954 #omp parallel shared(iD.1562) -> outer parallel
2955 .omp_data_i.1 = &.omp_data_o.1
2956 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2958 .omp_data_o.2.i = iD.1562; -> **
2959 #omp parallel shared(iD.1562) -> inner parallel
2960 .omp_data_i.2 = &.omp_data_o.2
2961 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2964 ** This is a problem. The symbol iD.1562 cannot be referenced
2965 inside the body of the outer parallel region. But since we are
2966 emitting this copy operation while expanding the inner parallel
2967 directive, we need to access the CTX structure of the outer
2968 parallel directive to get the correct mapping:
2970 .omp_data_o.2.i = .omp_data_i.1->i
2972 Since there may be other workshare or parallel directives enclosing
2973 the parallel directive, it may be necessary to walk up the context
2974 parent chain. This is not a problem in general because nested
2975 parallelism happens only rarely. */
2977 static tree
2978 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2980 tree t;
2981 omp_context *up;
2983 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2984 t = maybe_lookup_decl (decl, up);
2986 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2988 return t ? t : decl;
2992 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2993 in outer contexts. */
2995 static tree
2996 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2998 tree t = NULL;
2999 omp_context *up;
3001 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3002 t = maybe_lookup_decl (decl, up);
3004 return t ? t : decl;
3008 /* Construct the initialization value for reduction CLAUSE. */
3010 tree
3011 omp_reduction_init (tree clause, tree type)
3013 location_t loc = OMP_CLAUSE_LOCATION (clause);
3014 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3016 case PLUS_EXPR:
3017 case MINUS_EXPR:
3018 case BIT_IOR_EXPR:
3019 case BIT_XOR_EXPR:
3020 case TRUTH_OR_EXPR:
3021 case TRUTH_ORIF_EXPR:
3022 case TRUTH_XOR_EXPR:
3023 case NE_EXPR:
3024 return build_zero_cst (type);
3026 case MULT_EXPR:
3027 case TRUTH_AND_EXPR:
3028 case TRUTH_ANDIF_EXPR:
3029 case EQ_EXPR:
3030 return fold_convert_loc (loc, type, integer_one_node);
3032 case BIT_AND_EXPR:
3033 return fold_convert_loc (loc, type, integer_minus_one_node);
3035 case MAX_EXPR:
3036 if (SCALAR_FLOAT_TYPE_P (type))
3038 REAL_VALUE_TYPE max, min;
3039 if (HONOR_INFINITIES (TYPE_MODE (type)))
3041 real_inf (&max);
3042 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3044 else
3045 real_maxval (&min, 1, TYPE_MODE (type));
3046 return build_real (type, min);
3048 else
3050 gcc_assert (INTEGRAL_TYPE_P (type));
3051 return TYPE_MIN_VALUE (type);
3054 case MIN_EXPR:
3055 if (SCALAR_FLOAT_TYPE_P (type))
3057 REAL_VALUE_TYPE max;
3058 if (HONOR_INFINITIES (TYPE_MODE (type)))
3059 real_inf (&max);
3060 else
3061 real_maxval (&max, 0, TYPE_MODE (type));
3062 return build_real (type, max);
3064 else
3066 gcc_assert (INTEGRAL_TYPE_P (type));
3067 return TYPE_MAX_VALUE (type);
3070 default:
3071 gcc_unreachable ();
3075 /* Return alignment to be assumed for var in CLAUSE, which should be
3076 OMP_CLAUSE_ALIGNED. */
3078 static tree
3079 omp_clause_aligned_alignment (tree clause)
3081 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3082 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3084 /* Otherwise return implementation defined alignment. */
3085 unsigned int al = 1;
3086 machine_mode mode, vmode;
3087 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3088 if (vs)
3089 vs = 1 << floor_log2 (vs);
3090 static enum mode_class classes[]
3091 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3092 for (int i = 0; i < 4; i += 2)
3093 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3094 mode != VOIDmode;
3095 mode = GET_MODE_WIDER_MODE (mode))
3097 vmode = targetm.vectorize.preferred_simd_mode (mode);
3098 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3099 continue;
3100 while (vs
3101 && GET_MODE_SIZE (vmode) < vs
3102 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3103 vmode = GET_MODE_2XWIDER_MODE (vmode);
3105 tree type = lang_hooks.types.type_for_mode (mode, 1);
3106 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3107 continue;
3108 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3109 / GET_MODE_SIZE (mode));
3110 if (TYPE_MODE (type) != vmode)
3111 continue;
3112 if (TYPE_ALIGN_UNIT (type) > al)
3113 al = TYPE_ALIGN_UNIT (type);
3115 return build_int_cst (integer_type_node, al);
3118 /* Return maximum possible vectorization factor for the target. */
3120 static int
3121 omp_max_vf (void)
3123 if (!optimize
3124 || optimize_debug
3125 || !flag_tree_loop_optimize
3126 || (!flag_tree_loop_vectorize
3127 && (global_options_set.x_flag_tree_loop_vectorize
3128 || global_options_set.x_flag_tree_vectorize)))
3129 return 1;
3131 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3132 if (vs)
3134 vs = 1 << floor_log2 (vs);
3135 return vs;
3137 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3138 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3139 return GET_MODE_NUNITS (vqimode);
3140 return 1;
3143 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3144 privatization. */
3146 static bool
3147 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3148 tree &idx, tree &lane, tree &ivar, tree &lvar)
3150 if (max_vf == 0)
3152 max_vf = omp_max_vf ();
3153 if (max_vf > 1)
3155 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3156 OMP_CLAUSE_SAFELEN);
3157 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3158 max_vf = 1;
3159 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3160 max_vf) == -1)
3161 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3163 if (max_vf > 1)
3165 idx = create_tmp_var (unsigned_type_node, NULL);
3166 lane = create_tmp_var (unsigned_type_node, NULL);
3169 if (max_vf == 1)
3170 return false;
3172 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3173 tree avar = create_tmp_var_raw (atype, NULL);
3174 if (TREE_ADDRESSABLE (new_var))
3175 TREE_ADDRESSABLE (avar) = 1;
3176 DECL_ATTRIBUTES (avar)
3177 = tree_cons (get_identifier ("omp simd array"), NULL,
3178 DECL_ATTRIBUTES (avar));
3179 gimple_add_tmp_var (avar);
3180 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3181 NULL_TREE, NULL_TREE);
3182 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3183 NULL_TREE, NULL_TREE);
3184 if (DECL_P (new_var))
3186 SET_DECL_VALUE_EXPR (new_var, lvar);
3187 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3189 return true;
3192 /* Helper function of lower_rec_input_clauses. For a reference
3193 in simd reduction, add an underlying variable it will reference. */
3195 static void
3196 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3198 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3199 if (TREE_CONSTANT (z))
3201 const char *name = NULL;
3202 if (DECL_NAME (new_vard))
3203 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3205 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3206 gimple_add_tmp_var (z);
3207 TREE_ADDRESSABLE (z) = 1;
3208 z = build_fold_addr_expr_loc (loc, z);
3209 gimplify_assign (new_vard, z, ilist);
3213 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3214 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3215 private variables. Initialization statements go in ILIST, while calls
3216 to destructors go in DLIST. */
3218 static void
3219 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3220 omp_context *ctx, struct omp_for_data *fd)
3222 tree c, dtor, copyin_seq, x, ptr;
3223 bool copyin_by_ref = false;
3224 bool lastprivate_firstprivate = false;
3225 bool reduction_omp_orig_ref = false;
3226 int pass;
3227 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3228 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3229 int max_vf = 0;
3230 tree lane = NULL_TREE, idx = NULL_TREE;
3231 tree ivar = NULL_TREE, lvar = NULL_TREE;
3232 gimple_seq llist[2] = { NULL, NULL };
3234 copyin_seq = NULL;
3236 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3237 with data sharing clauses referencing variable sized vars. That
3238 is unnecessarily hard to support and very unlikely to result in
3239 vectorized code anyway. */
3240 if (is_simd)
3241 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3242 switch (OMP_CLAUSE_CODE (c))
3244 case OMP_CLAUSE_LINEAR:
3245 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3246 max_vf = 1;
3247 /* FALLTHRU */
3248 case OMP_CLAUSE_REDUCTION:
3249 case OMP_CLAUSE_PRIVATE:
3250 case OMP_CLAUSE_FIRSTPRIVATE:
3251 case OMP_CLAUSE_LASTPRIVATE:
3252 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3253 max_vf = 1;
3254 break;
3255 default:
3256 continue;
3259 /* Do all the fixed sized types in the first pass, and the variable sized
3260 types in the second pass. This makes sure that the scalar arguments to
3261 the variable sized types are processed before we use them in the
3262 variable sized operations. */
3263 for (pass = 0; pass < 2; ++pass)
3265 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3267 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3268 tree var, new_var;
3269 bool by_ref;
3270 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3272 switch (c_kind)
3274 case OMP_CLAUSE_PRIVATE:
3275 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3276 continue;
3277 break;
3278 case OMP_CLAUSE_SHARED:
3279 /* Ignore shared directives in teams construct. */
3280 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3281 continue;
3282 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3284 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3285 continue;
3287 case OMP_CLAUSE_FIRSTPRIVATE:
3288 case OMP_CLAUSE_COPYIN:
3289 case OMP_CLAUSE_LINEAR:
3290 break;
3291 case OMP_CLAUSE_REDUCTION:
3292 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3293 reduction_omp_orig_ref = true;
3294 break;
3295 case OMP_CLAUSE__LOOPTEMP_:
3296 /* Handle _looptemp_ clauses only on parallel. */
3297 if (fd)
3298 continue;
3299 break;
3300 case OMP_CLAUSE_LASTPRIVATE:
3301 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3303 lastprivate_firstprivate = true;
3304 if (pass != 0)
3305 continue;
3307 /* Even without corresponding firstprivate, if
3308 decl is Fortran allocatable, it needs outer var
3309 reference. */
3310 else if (pass == 0
3311 && lang_hooks.decls.omp_private_outer_ref
3312 (OMP_CLAUSE_DECL (c)))
3313 lastprivate_firstprivate = true;
3314 break;
3315 case OMP_CLAUSE_ALIGNED:
3316 if (pass == 0)
3317 continue;
3318 var = OMP_CLAUSE_DECL (c);
3319 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3320 && !is_global_var (var))
3322 new_var = maybe_lookup_decl (var, ctx);
3323 if (new_var == NULL_TREE)
3324 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3325 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3326 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3327 omp_clause_aligned_alignment (c));
3328 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3329 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3330 gimplify_and_add (x, ilist);
3332 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3333 && is_global_var (var))
3335 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3336 new_var = lookup_decl (var, ctx);
3337 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3338 t = build_fold_addr_expr_loc (clause_loc, t);
3339 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3340 t = build_call_expr_loc (clause_loc, t2, 2, t,
3341 omp_clause_aligned_alignment (c));
3342 t = fold_convert_loc (clause_loc, ptype, t);
3343 x = create_tmp_var (ptype, NULL);
3344 t = build2 (MODIFY_EXPR, ptype, x, t);
3345 gimplify_and_add (t, ilist);
3346 t = build_simple_mem_ref_loc (clause_loc, x);
3347 SET_DECL_VALUE_EXPR (new_var, t);
3348 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3350 continue;
3351 default:
3352 continue;
3355 new_var = var = OMP_CLAUSE_DECL (c);
3356 if (c_kind != OMP_CLAUSE_COPYIN)
3357 new_var = lookup_decl (var, ctx);
3359 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3361 if (pass != 0)
3362 continue;
3364 else if (is_variable_sized (var))
3366 /* For variable sized types, we need to allocate the
3367 actual storage here. Call alloca and store the
3368 result in the pointer decl that we created elsewhere. */
3369 if (pass == 0)
3370 continue;
3372 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3374 gcall *stmt;
3375 tree tmp, atmp;
3377 ptr = DECL_VALUE_EXPR (new_var);
3378 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3379 ptr = TREE_OPERAND (ptr, 0);
3380 gcc_assert (DECL_P (ptr));
3381 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3383 /* void *tmp = __builtin_alloca */
3384 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3385 stmt = gimple_build_call (atmp, 1, x);
3386 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3387 gimple_add_tmp_var (tmp);
3388 gimple_call_set_lhs (stmt, tmp);
3390 gimple_seq_add_stmt (ilist, stmt);
3392 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3393 gimplify_assign (ptr, x, ilist);
3396 else if (is_reference (var))
3398 /* For references that are being privatized for Fortran,
3399 allocate new backing storage for the new pointer
3400 variable. This allows us to avoid changing all the
3401 code that expects a pointer to something that expects
3402 a direct variable. */
3403 if (pass == 0)
3404 continue;
3406 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3407 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3409 x = build_receiver_ref (var, false, ctx);
3410 x = build_fold_addr_expr_loc (clause_loc, x);
3412 else if (TREE_CONSTANT (x))
3414 /* For reduction in SIMD loop, defer adding the
3415 initialization of the reference, because if we decide
3416 to use SIMD array for it, the initilization could cause
3417 expansion ICE. */
3418 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3419 x = NULL_TREE;
3420 else
3422 const char *name = NULL;
3423 if (DECL_NAME (var))
3424 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3426 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3427 name);
3428 gimple_add_tmp_var (x);
3429 TREE_ADDRESSABLE (x) = 1;
3430 x = build_fold_addr_expr_loc (clause_loc, x);
3433 else
3435 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3436 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3439 if (x)
3441 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3442 gimplify_assign (new_var, x, ilist);
3445 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3447 else if (c_kind == OMP_CLAUSE_REDUCTION
3448 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3450 if (pass == 0)
3451 continue;
3453 else if (pass != 0)
3454 continue;
3456 switch (OMP_CLAUSE_CODE (c))
3458 case OMP_CLAUSE_SHARED:
3459 /* Ignore shared directives in teams construct. */
3460 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3461 continue;
3462 /* Shared global vars are just accessed directly. */
3463 if (is_global_var (new_var))
3464 break;
3465 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3466 needs to be delayed until after fixup_child_record_type so
3467 that we get the correct type during the dereference. */
3468 by_ref = use_pointer_for_field (var, ctx);
3469 x = build_receiver_ref (var, by_ref, ctx);
3470 SET_DECL_VALUE_EXPR (new_var, x);
3471 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3473 /* ??? If VAR is not passed by reference, and the variable
3474 hasn't been initialized yet, then we'll get a warning for
3475 the store into the omp_data_s structure. Ideally, we'd be
3476 able to notice this and not store anything at all, but
3477 we're generating code too early. Suppress the warning. */
3478 if (!by_ref)
3479 TREE_NO_WARNING (var) = 1;
3480 break;
3482 case OMP_CLAUSE_LASTPRIVATE:
3483 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3484 break;
3485 /* FALLTHRU */
3487 case OMP_CLAUSE_PRIVATE:
3488 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3489 x = build_outer_var_ref (var, ctx);
3490 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3492 if (is_task_ctx (ctx))
3493 x = build_receiver_ref (var, false, ctx);
3494 else
3495 x = build_outer_var_ref (var, ctx);
3497 else
3498 x = NULL;
3499 do_private:
3500 tree nx;
3501 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3502 if (is_simd)
3504 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3505 if ((TREE_ADDRESSABLE (new_var) || nx || y
3506 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3507 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3508 idx, lane, ivar, lvar))
3510 if (nx)
3511 x = lang_hooks.decls.omp_clause_default_ctor
3512 (c, unshare_expr (ivar), x);
3513 if (nx && x)
3514 gimplify_and_add (x, &llist[0]);
3515 if (y)
3517 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3518 if (y)
3520 gimple_seq tseq = NULL;
3522 dtor = y;
3523 gimplify_stmt (&dtor, &tseq);
3524 gimple_seq_add_seq (&llist[1], tseq);
3527 break;
3530 if (nx)
3531 gimplify_and_add (nx, ilist);
3532 /* FALLTHRU */
3534 do_dtor:
3535 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3536 if (x)
3538 gimple_seq tseq = NULL;
3540 dtor = x;
3541 gimplify_stmt (&dtor, &tseq);
3542 gimple_seq_add_seq (dlist, tseq);
3544 break;
3546 case OMP_CLAUSE_LINEAR:
3547 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3548 goto do_firstprivate;
3549 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3550 x = NULL;
3551 else
3552 x = build_outer_var_ref (var, ctx);
3553 goto do_private;
3555 case OMP_CLAUSE_FIRSTPRIVATE:
3556 if (is_task_ctx (ctx))
3558 if (is_reference (var) || is_variable_sized (var))
3559 goto do_dtor;
3560 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3561 ctx))
3562 || use_pointer_for_field (var, NULL))
3564 x = build_receiver_ref (var, false, ctx);
3565 SET_DECL_VALUE_EXPR (new_var, x);
3566 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3567 goto do_dtor;
3570 do_firstprivate:
3571 x = build_outer_var_ref (var, ctx);
3572 if (is_simd)
3574 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3575 && gimple_omp_for_combined_into_p (ctx->stmt))
3577 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3578 tree stept = TREE_TYPE (t);
3579 tree ct = find_omp_clause (clauses,
3580 OMP_CLAUSE__LOOPTEMP_);
3581 gcc_assert (ct);
3582 tree l = OMP_CLAUSE_DECL (ct);
3583 tree n1 = fd->loop.n1;
3584 tree step = fd->loop.step;
3585 tree itype = TREE_TYPE (l);
3586 if (POINTER_TYPE_P (itype))
3587 itype = signed_type_for (itype);
3588 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3589 if (TYPE_UNSIGNED (itype)
3590 && fd->loop.cond_code == GT_EXPR)
3591 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3592 fold_build1 (NEGATE_EXPR, itype, l),
3593 fold_build1 (NEGATE_EXPR,
3594 itype, step));
3595 else
3596 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3597 t = fold_build2 (MULT_EXPR, stept,
3598 fold_convert (stept, l), t);
3600 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3602 x = lang_hooks.decls.omp_clause_linear_ctor
3603 (c, new_var, x, t);
3604 gimplify_and_add (x, ilist);
3605 goto do_dtor;
3608 if (POINTER_TYPE_P (TREE_TYPE (x)))
3609 x = fold_build2 (POINTER_PLUS_EXPR,
3610 TREE_TYPE (x), x, t);
3611 else
3612 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3615 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3616 || TREE_ADDRESSABLE (new_var))
3617 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3618 idx, lane, ivar, lvar))
3620 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3622 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3623 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3624 gimplify_and_add (x, ilist);
3625 gimple_stmt_iterator gsi
3626 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3627 gassign *g
3628 = gimple_build_assign (unshare_expr (lvar), iv);
3629 gsi_insert_before_without_update (&gsi, g,
3630 GSI_SAME_STMT);
3631 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3632 enum tree_code code = PLUS_EXPR;
3633 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3634 code = POINTER_PLUS_EXPR;
3635 g = gimple_build_assign_with_ops (code, iv, iv, t);
3636 gsi_insert_before_without_update (&gsi, g,
3637 GSI_SAME_STMT);
3638 break;
3640 x = lang_hooks.decls.omp_clause_copy_ctor
3641 (c, unshare_expr (ivar), x);
3642 gimplify_and_add (x, &llist[0]);
3643 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3644 if (x)
3646 gimple_seq tseq = NULL;
3648 dtor = x;
3649 gimplify_stmt (&dtor, &tseq);
3650 gimple_seq_add_seq (&llist[1], tseq);
3652 break;
3655 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3656 gimplify_and_add (x, ilist);
3657 goto do_dtor;
3659 case OMP_CLAUSE__LOOPTEMP_:
3660 gcc_assert (is_parallel_ctx (ctx));
3661 x = build_outer_var_ref (var, ctx);
3662 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3663 gimplify_and_add (x, ilist);
3664 break;
3666 case OMP_CLAUSE_COPYIN:
3667 by_ref = use_pointer_for_field (var, NULL);
3668 x = build_receiver_ref (var, by_ref, ctx);
3669 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3670 append_to_statement_list (x, &copyin_seq);
3671 copyin_by_ref |= by_ref;
3672 break;
3674 case OMP_CLAUSE_REDUCTION:
3675 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3677 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3678 gimple tseq;
3679 x = build_outer_var_ref (var, ctx);
3681 if (is_reference (var)
3682 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3683 TREE_TYPE (x)))
3684 x = build_fold_addr_expr_loc (clause_loc, x);
3685 SET_DECL_VALUE_EXPR (placeholder, x);
3686 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3687 tree new_vard = new_var;
3688 if (is_reference (var))
3690 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3691 new_vard = TREE_OPERAND (new_var, 0);
3692 gcc_assert (DECL_P (new_vard));
3694 if (is_simd
3695 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3696 idx, lane, ivar, lvar))
3698 if (new_vard == new_var)
3700 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3701 SET_DECL_VALUE_EXPR (new_var, ivar);
3703 else
3705 SET_DECL_VALUE_EXPR (new_vard,
3706 build_fold_addr_expr (ivar));
3707 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3709 x = lang_hooks.decls.omp_clause_default_ctor
3710 (c, unshare_expr (ivar),
3711 build_outer_var_ref (var, ctx));
3712 if (x)
3713 gimplify_and_add (x, &llist[0]);
3714 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3716 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3717 lower_omp (&tseq, ctx);
3718 gimple_seq_add_seq (&llist[0], tseq);
3720 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3721 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3722 lower_omp (&tseq, ctx);
3723 gimple_seq_add_seq (&llist[1], tseq);
3724 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3725 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3726 if (new_vard == new_var)
3727 SET_DECL_VALUE_EXPR (new_var, lvar);
3728 else
3729 SET_DECL_VALUE_EXPR (new_vard,
3730 build_fold_addr_expr (lvar));
3731 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3732 if (x)
3734 tseq = NULL;
3735 dtor = x;
3736 gimplify_stmt (&dtor, &tseq);
3737 gimple_seq_add_seq (&llist[1], tseq);
3739 break;
3741 /* If this is a reference to constant size reduction var
3742 with placeholder, we haven't emitted the initializer
3743 for it because it is undesirable if SIMD arrays are used.
3744 But if they aren't used, we need to emit the deferred
3745 initialization now. */
3746 else if (is_reference (var) && is_simd)
3747 handle_simd_reference (clause_loc, new_vard, ilist);
3748 x = lang_hooks.decls.omp_clause_default_ctor
3749 (c, unshare_expr (new_var),
3750 build_outer_var_ref (var, ctx));
3751 if (x)
3752 gimplify_and_add (x, ilist);
3753 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3755 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3756 lower_omp (&tseq, ctx);
3757 gimple_seq_add_seq (ilist, tseq);
3759 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3760 if (is_simd)
3762 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3763 lower_omp (&tseq, ctx);
3764 gimple_seq_add_seq (dlist, tseq);
3765 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3767 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3768 goto do_dtor;
3770 else
3772 x = omp_reduction_init (c, TREE_TYPE (new_var));
3773 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3774 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3776 /* reduction(-:var) sums up the partial results, so it
3777 acts identically to reduction(+:var). */
3778 if (code == MINUS_EXPR)
3779 code = PLUS_EXPR;
3781 tree new_vard = new_var;
3782 if (is_simd && is_reference (var))
3784 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3785 new_vard = TREE_OPERAND (new_var, 0);
3786 gcc_assert (DECL_P (new_vard));
3788 if (is_simd
3789 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3790 idx, lane, ivar, lvar))
3792 tree ref = build_outer_var_ref (var, ctx);
3794 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3796 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3797 ref = build_outer_var_ref (var, ctx);
3798 gimplify_assign (ref, x, &llist[1]);
3800 if (new_vard != new_var)
3802 SET_DECL_VALUE_EXPR (new_vard,
3803 build_fold_addr_expr (lvar));
3804 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3807 else
3809 if (is_reference (var) && is_simd)
3810 handle_simd_reference (clause_loc, new_vard, ilist);
3811 gimplify_assign (new_var, x, ilist);
3812 if (is_simd)
3814 tree ref = build_outer_var_ref (var, ctx);
3816 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3817 ref = build_outer_var_ref (var, ctx);
3818 gimplify_assign (ref, x, dlist);
3822 break;
3824 default:
3825 gcc_unreachable ();
3830 if (lane)
3832 tree uid = create_tmp_var (ptr_type_node, "simduid");
3833 /* Don't want uninit warnings on simduid, it is always uninitialized,
3834 but we use it not for the value, but for the DECL_UID only. */
3835 TREE_NO_WARNING (uid) = 1;
3836 gimple g
3837 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3838 gimple_call_set_lhs (g, lane);
3839 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3840 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3841 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3842 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3843 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3844 gimple_omp_for_set_clauses (ctx->stmt, c);
3845 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3846 build_int_cst (unsigned_type_node, 0),
3847 NULL_TREE);
3848 gimple_seq_add_stmt (ilist, g);
3849 for (int i = 0; i < 2; i++)
3850 if (llist[i])
3852 tree vf = create_tmp_var (unsigned_type_node, NULL);
3853 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3854 gimple_call_set_lhs (g, vf);
3855 gimple_seq *seq = i == 0 ? ilist : dlist;
3856 gimple_seq_add_stmt (seq, g);
3857 tree t = build_int_cst (unsigned_type_node, 0);
3858 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3859 gimple_seq_add_stmt (seq, g);
3860 tree body = create_artificial_label (UNKNOWN_LOCATION);
3861 tree header = create_artificial_label (UNKNOWN_LOCATION);
3862 tree end = create_artificial_label (UNKNOWN_LOCATION);
3863 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3864 gimple_seq_add_stmt (seq, gimple_build_label (body));
3865 gimple_seq_add_seq (seq, llist[i]);
3866 t = build_int_cst (unsigned_type_node, 1);
3867 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3868 gimple_seq_add_stmt (seq, g);
3869 gimple_seq_add_stmt (seq, gimple_build_label (header));
3870 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3871 gimple_seq_add_stmt (seq, g);
3872 gimple_seq_add_stmt (seq, gimple_build_label (end));
3876 /* The copyin sequence is not to be executed by the main thread, since
3877 that would result in self-copies. Perhaps not visible to scalars,
3878 but it certainly is to C++ operator=. */
3879 if (copyin_seq)
3881 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3883 x = build2 (NE_EXPR, boolean_type_node, x,
3884 build_int_cst (TREE_TYPE (x), 0));
3885 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3886 gimplify_and_add (x, ilist);
3889 /* If any copyin variable is passed by reference, we must ensure the
3890 master thread doesn't modify it before it is copied over in all
3891 threads. Similarly for variables in both firstprivate and
3892 lastprivate clauses we need to ensure the lastprivate copying
3893 happens after firstprivate copying in all threads. And similarly
3894 for UDRs if initializer expression refers to omp_orig. */
3895 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3897 /* Don't add any barrier for #pragma omp simd or
3898 #pragma omp distribute. */
3899 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3900 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3901 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3904 /* If max_vf is non-zero, then we can use only a vectorization factor
3905 up to the max_vf we chose. So stick it into the safelen clause. */
3906 if (max_vf)
3908 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3909 OMP_CLAUSE_SAFELEN);
3910 if (c == NULL_TREE
3911 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
3912 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3913 max_vf) == 1))
3915 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3916 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3917 max_vf);
3918 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3919 gimple_omp_for_set_clauses (ctx->stmt, c);
3925 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3926 both parallel and workshare constructs. PREDICATE may be NULL if it's
3927 always true. */
3929 static void
3930 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3931 omp_context *ctx)
3933 tree x, c, label = NULL, orig_clauses = clauses;
3934 bool par_clauses = false;
3935 tree simduid = NULL, lastlane = NULL;
3937 /* Early exit if there are no lastprivate or linear clauses. */
3938 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3939 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3940 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3941 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3942 break;
3943 if (clauses == NULL)
3945 /* If this was a workshare clause, see if it had been combined
3946 with its parallel. In that case, look for the clauses on the
3947 parallel statement itself. */
3948 if (is_parallel_ctx (ctx))
3949 return;
3951 ctx = ctx->outer;
3952 if (ctx == NULL || !is_parallel_ctx (ctx))
3953 return;
3955 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3956 OMP_CLAUSE_LASTPRIVATE);
3957 if (clauses == NULL)
3958 return;
3959 par_clauses = true;
3962 if (predicate)
3964 gcond *stmt;
3965 tree label_true, arm1, arm2;
3967 label = create_artificial_label (UNKNOWN_LOCATION);
3968 label_true = create_artificial_label (UNKNOWN_LOCATION);
3969 arm1 = TREE_OPERAND (predicate, 0);
3970 arm2 = TREE_OPERAND (predicate, 1);
3971 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3972 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3973 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3974 label_true, label);
3975 gimple_seq_add_stmt (stmt_list, stmt);
3976 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3979 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3980 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3982 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3983 if (simduid)
3984 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3987 for (c = clauses; c ;)
3989 tree var, new_var;
3990 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3992 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3993 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3994 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3996 var = OMP_CLAUSE_DECL (c);
3997 new_var = lookup_decl (var, ctx);
3999 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4001 tree val = DECL_VALUE_EXPR (new_var);
4002 if (TREE_CODE (val) == ARRAY_REF
4003 && VAR_P (TREE_OPERAND (val, 0))
4004 && lookup_attribute ("omp simd array",
4005 DECL_ATTRIBUTES (TREE_OPERAND (val,
4006 0))))
4008 if (lastlane == NULL)
4010 lastlane = create_tmp_var (unsigned_type_node, NULL);
4011 gcall *g
4012 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4013 2, simduid,
4014 TREE_OPERAND (val, 1));
4015 gimple_call_set_lhs (g, lastlane);
4016 gimple_seq_add_stmt (stmt_list, g);
4018 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4019 TREE_OPERAND (val, 0), lastlane,
4020 NULL_TREE, NULL_TREE);
4024 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4025 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4027 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4028 gimple_seq_add_seq (stmt_list,
4029 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4030 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4032 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4033 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4035 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4036 gimple_seq_add_seq (stmt_list,
4037 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4038 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4041 x = build_outer_var_ref (var, ctx);
4042 if (is_reference (var))
4043 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4044 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4045 gimplify_and_add (x, stmt_list);
4047 c = OMP_CLAUSE_CHAIN (c);
4048 if (c == NULL && !par_clauses)
4050 /* If this was a workshare clause, see if it had been combined
4051 with its parallel. In that case, continue looking for the
4052 clauses also on the parallel statement itself. */
4053 if (is_parallel_ctx (ctx))
4054 break;
4056 ctx = ctx->outer;
4057 if (ctx == NULL || !is_parallel_ctx (ctx))
4058 break;
4060 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4061 OMP_CLAUSE_LASTPRIVATE);
4062 par_clauses = true;
4066 if (label)
4067 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4071 /* Generate code to implement the REDUCTION clauses. */
4073 static void
4074 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4076 gimple_seq sub_seq = NULL;
4077 gimple stmt;
4078 tree x, c;
4079 int count = 0;
4081 /* SIMD reductions are handled in lower_rec_input_clauses. */
4082 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4083 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4084 return;
4086 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4087 update in that case, otherwise use a lock. */
4088 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4089 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4091 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4093 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4094 count = -1;
4095 break;
4097 count++;
4100 if (count == 0)
4101 return;
4103 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4105 tree var, ref, new_var;
4106 enum tree_code code;
4107 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4109 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4110 continue;
4112 var = OMP_CLAUSE_DECL (c);
4113 new_var = lookup_decl (var, ctx);
4114 if (is_reference (var))
4115 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4116 ref = build_outer_var_ref (var, ctx);
4117 code = OMP_CLAUSE_REDUCTION_CODE (c);
4119 /* reduction(-:var) sums up the partial results, so it acts
4120 identically to reduction(+:var). */
4121 if (code == MINUS_EXPR)
4122 code = PLUS_EXPR;
4124 if (count == 1)
4126 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4128 addr = save_expr (addr);
4129 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4130 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4131 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4132 gimplify_and_add (x, stmt_seqp);
4133 return;
4136 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4138 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4140 if (is_reference (var)
4141 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4142 TREE_TYPE (ref)))
4143 ref = build_fold_addr_expr_loc (clause_loc, ref);
4144 SET_DECL_VALUE_EXPR (placeholder, ref);
4145 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4146 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4147 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4148 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4149 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4151 else
4153 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4154 ref = build_outer_var_ref (var, ctx);
4155 gimplify_assign (ref, x, &sub_seq);
4159 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4161 gimple_seq_add_stmt (stmt_seqp, stmt);
4163 gimple_seq_add_seq (stmt_seqp, sub_seq);
4165 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4167 gimple_seq_add_stmt (stmt_seqp, stmt);
4171 /* Generate code to implement the COPYPRIVATE clauses. */
4173 static void
4174 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4175 omp_context *ctx)
4177 tree c;
4179 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4181 tree var, new_var, ref, x;
4182 bool by_ref;
4183 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4185 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4186 continue;
4188 var = OMP_CLAUSE_DECL (c);
4189 by_ref = use_pointer_for_field (var, NULL);
4191 ref = build_sender_ref (var, ctx);
4192 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4193 if (by_ref)
4195 x = build_fold_addr_expr_loc (clause_loc, new_var);
4196 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4198 gimplify_assign (ref, x, slist);
4200 ref = build_receiver_ref (var, false, ctx);
4201 if (by_ref)
4203 ref = fold_convert_loc (clause_loc,
4204 build_pointer_type (TREE_TYPE (new_var)),
4205 ref);
4206 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4208 if (is_reference (var))
4210 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4211 ref = build_simple_mem_ref_loc (clause_loc, ref);
4212 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4214 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4215 gimplify_and_add (x, rlist);
4220 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4221 and REDUCTION from the sender (aka parent) side. */
4223 static void
4224 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4225 omp_context *ctx)
4227 tree c;
4229 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4231 tree val, ref, x, var;
4232 bool by_ref, do_in = false, do_out = false;
4233 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4235 switch (OMP_CLAUSE_CODE (c))
4237 case OMP_CLAUSE_PRIVATE:
4238 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4239 break;
4240 continue;
4241 case OMP_CLAUSE_FIRSTPRIVATE:
4242 case OMP_CLAUSE_COPYIN:
4243 case OMP_CLAUSE_LASTPRIVATE:
4244 case OMP_CLAUSE_REDUCTION:
4245 case OMP_CLAUSE__LOOPTEMP_:
4246 break;
4247 default:
4248 continue;
4251 val = OMP_CLAUSE_DECL (c);
4252 var = lookup_decl_in_outer_ctx (val, ctx);
4254 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4255 && is_global_var (var))
4256 continue;
4257 if (is_variable_sized (val))
4258 continue;
4259 by_ref = use_pointer_for_field (val, NULL);
4261 switch (OMP_CLAUSE_CODE (c))
4263 case OMP_CLAUSE_PRIVATE:
4264 case OMP_CLAUSE_FIRSTPRIVATE:
4265 case OMP_CLAUSE_COPYIN:
4266 case OMP_CLAUSE__LOOPTEMP_:
4267 do_in = true;
4268 break;
4270 case OMP_CLAUSE_LASTPRIVATE:
4271 if (by_ref || is_reference (val))
4273 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4274 continue;
4275 do_in = true;
4277 else
4279 do_out = true;
4280 if (lang_hooks.decls.omp_private_outer_ref (val))
4281 do_in = true;
4283 break;
4285 case OMP_CLAUSE_REDUCTION:
4286 do_in = true;
4287 do_out = !(by_ref || is_reference (val));
4288 break;
4290 default:
4291 gcc_unreachable ();
4294 if (do_in)
4296 ref = build_sender_ref (val, ctx);
4297 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4298 gimplify_assign (ref, x, ilist);
4299 if (is_task_ctx (ctx))
4300 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4303 if (do_out)
4305 ref = build_sender_ref (val, ctx);
4306 gimplify_assign (var, ref, olist);
4311 /* Generate code to implement SHARED from the sender (aka parent)
4312 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4313 list things that got automatically shared. */
4315 static void
4316 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4318 tree var, ovar, nvar, f, x, record_type;
4320 if (ctx->record_type == NULL)
4321 return;
4323 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4324 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4326 ovar = DECL_ABSTRACT_ORIGIN (f);
4327 nvar = maybe_lookup_decl (ovar, ctx);
4328 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4329 continue;
4331 /* If CTX is a nested parallel directive. Find the immediately
4332 enclosing parallel or workshare construct that contains a
4333 mapping for OVAR. */
4334 var = lookup_decl_in_outer_ctx (ovar, ctx);
4336 if (use_pointer_for_field (ovar, ctx))
4338 x = build_sender_ref (ovar, ctx);
4339 var = build_fold_addr_expr (var);
4340 gimplify_assign (x, var, ilist);
4342 else
4344 x = build_sender_ref (ovar, ctx);
4345 gimplify_assign (x, var, ilist);
4347 if (!TREE_READONLY (var)
4348 /* We don't need to receive a new reference to a result
4349 or parm decl. In fact we may not store to it as we will
4350 invalidate any pending RSO and generate wrong gimple
4351 during inlining. */
4352 && !((TREE_CODE (var) == RESULT_DECL
4353 || TREE_CODE (var) == PARM_DECL)
4354 && DECL_BY_REFERENCE (var)))
4356 x = build_sender_ref (ovar, ctx);
4357 gimplify_assign (var, x, olist);
4364 /* A convenience function to build an empty GIMPLE_COND with just the
4365 condition. */
4367 static gcond *
4368 gimple_build_cond_empty (tree cond)
4370 enum tree_code pred_code;
4371 tree lhs, rhs;
4373 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4374 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4378 /* Build the function calls to GOMP_parallel_start etc to actually
4379 generate the parallel operation. REGION is the parallel region
4380 being expanded. BB is the block where to insert the code. WS_ARGS
4381 will be set if this is a call to a combined parallel+workshare
4382 construct, it contains the list of additional arguments needed by
4383 the workshare construct. */
4385 static void
4386 expand_parallel_call (struct omp_region *region, basic_block bb,
4387 gomp_parallel *entry_stmt,
4388 vec<tree, va_gc> *ws_args)
4390 tree t, t1, t2, val, cond, c, clauses, flags;
4391 gimple_stmt_iterator gsi;
4392 gimple stmt;
4393 enum built_in_function start_ix;
4394 int start_ix2;
4395 location_t clause_loc;
4396 vec<tree, va_gc> *args;
4398 clauses = gimple_omp_parallel_clauses (entry_stmt);
4400 /* Determine what flavor of GOMP_parallel we will be
4401 emitting. */
4402 start_ix = BUILT_IN_GOMP_PARALLEL;
4403 if (is_combined_parallel (region))
4405 switch (region->inner->type)
4407 case GIMPLE_OMP_FOR:
4408 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4409 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4410 + (region->inner->sched_kind
4411 == OMP_CLAUSE_SCHEDULE_RUNTIME
4412 ? 3 : region->inner->sched_kind));
4413 start_ix = (enum built_in_function)start_ix2;
4414 break;
4415 case GIMPLE_OMP_SECTIONS:
4416 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4417 break;
4418 default:
4419 gcc_unreachable ();
4423 /* By default, the value of NUM_THREADS is zero (selected at run time)
4424 and there is no conditional. */
4425 cond = NULL_TREE;
4426 val = build_int_cst (unsigned_type_node, 0);
4427 flags = build_int_cst (unsigned_type_node, 0);
4429 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4430 if (c)
4431 cond = OMP_CLAUSE_IF_EXPR (c);
4433 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4434 if (c)
4436 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4437 clause_loc = OMP_CLAUSE_LOCATION (c);
4439 else
4440 clause_loc = gimple_location (entry_stmt);
4442 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4443 if (c)
4444 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4446 /* Ensure 'val' is of the correct type. */
4447 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4449 /* If we found the clause 'if (cond)', build either
4450 (cond != 0) or (cond ? val : 1u). */
4451 if (cond)
4453 cond = gimple_boolify (cond);
4455 if (integer_zerop (val))
4456 val = fold_build2_loc (clause_loc,
4457 EQ_EXPR, unsigned_type_node, cond,
4458 build_int_cst (TREE_TYPE (cond), 0));
4459 else
4461 basic_block cond_bb, then_bb, else_bb;
4462 edge e, e_then, e_else;
4463 tree tmp_then, tmp_else, tmp_join, tmp_var;
4465 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4466 if (gimple_in_ssa_p (cfun))
4468 tmp_then = make_ssa_name (tmp_var, NULL);
4469 tmp_else = make_ssa_name (tmp_var, NULL);
4470 tmp_join = make_ssa_name (tmp_var, NULL);
4472 else
4474 tmp_then = tmp_var;
4475 tmp_else = tmp_var;
4476 tmp_join = tmp_var;
4479 e = split_block (bb, NULL);
4480 cond_bb = e->src;
4481 bb = e->dest;
4482 remove_edge (e);
4484 then_bb = create_empty_bb (cond_bb);
4485 else_bb = create_empty_bb (then_bb);
4486 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4487 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4489 stmt = gimple_build_cond_empty (cond);
4490 gsi = gsi_start_bb (cond_bb);
4491 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4493 gsi = gsi_start_bb (then_bb);
4494 stmt = gimple_build_assign (tmp_then, val);
4495 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4497 gsi = gsi_start_bb (else_bb);
4498 stmt = gimple_build_assign
4499 (tmp_else, build_int_cst (unsigned_type_node, 1));
4500 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4502 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4503 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4504 add_bb_to_loop (then_bb, cond_bb->loop_father);
4505 add_bb_to_loop (else_bb, cond_bb->loop_father);
4506 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4507 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4509 if (gimple_in_ssa_p (cfun))
4511 gphi *phi = create_phi_node (tmp_join, bb);
4512 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4513 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4516 val = tmp_join;
4519 gsi = gsi_start_bb (bb);
4520 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4521 false, GSI_CONTINUE_LINKING);
4524 gsi = gsi_last_bb (bb);
4525 t = gimple_omp_parallel_data_arg (entry_stmt);
4526 if (t == NULL)
4527 t1 = null_pointer_node;
4528 else
4529 t1 = build_fold_addr_expr (t);
4530 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4532 vec_alloc (args, 4 + vec_safe_length (ws_args));
4533 args->quick_push (t2);
4534 args->quick_push (t1);
4535 args->quick_push (val);
4536 if (ws_args)
4537 args->splice (*ws_args);
4538 args->quick_push (flags);
4540 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4541 builtin_decl_explicit (start_ix), args);
4543 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4544 false, GSI_CONTINUE_LINKING);
4547 /* Insert a function call whose name is FUNC_NAME with the information from
4548 ENTRY_STMT into the basic_block BB. */
4550 static void
4551 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
4552 vec <tree, va_gc> *ws_args)
4554 tree t, t1, t2;
4555 gimple_stmt_iterator gsi;
4556 vec <tree, va_gc> *args;
4558 gcc_assert (vec_safe_length (ws_args) == 2);
4559 tree func_name = (*ws_args)[0];
4560 tree grain = (*ws_args)[1];
4562 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
4563 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
4564 gcc_assert (count != NULL_TREE);
4565 count = OMP_CLAUSE_OPERAND (count, 0);
4567 gsi = gsi_last_bb (bb);
4568 t = gimple_omp_parallel_data_arg (entry_stmt);
4569 if (t == NULL)
4570 t1 = null_pointer_node;
4571 else
4572 t1 = build_fold_addr_expr (t);
4573 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4575 vec_alloc (args, 4);
4576 args->quick_push (t2);
4577 args->quick_push (t1);
4578 args->quick_push (count);
4579 args->quick_push (grain);
4580 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
4582 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
4583 GSI_CONTINUE_LINKING);
4586 /* Build the function call to GOMP_task to actually
4587 generate the task operation. BB is the block where to insert the code. */
4589 static void
4590 expand_task_call (basic_block bb, gomp_task *entry_stmt)
4592 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4593 gimple_stmt_iterator gsi;
4594 location_t loc = gimple_location (entry_stmt);
4596 clauses = gimple_omp_task_clauses (entry_stmt);
4598 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4599 if (c)
4600 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4601 else
4602 cond = boolean_true_node;
4604 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4605 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4606 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4607 flags = build_int_cst (unsigned_type_node,
4608 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4610 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4611 if (c)
4613 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4614 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4615 build_int_cst (unsigned_type_node, 2),
4616 build_int_cst (unsigned_type_node, 0));
4617 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4619 if (depend)
4620 depend = OMP_CLAUSE_DECL (depend);
4621 else
4622 depend = build_int_cst (ptr_type_node, 0);
4624 gsi = gsi_last_bb (bb);
4625 t = gimple_omp_task_data_arg (entry_stmt);
4626 if (t == NULL)
4627 t2 = null_pointer_node;
4628 else
4629 t2 = build_fold_addr_expr_loc (loc, t);
4630 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4631 t = gimple_omp_task_copy_fn (entry_stmt);
4632 if (t == NULL)
4633 t3 = null_pointer_node;
4634 else
4635 t3 = build_fold_addr_expr_loc (loc, t);
4637 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4638 8, t1, t2, t3,
4639 gimple_omp_task_arg_size (entry_stmt),
4640 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4641 depend);
4643 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4644 false, GSI_CONTINUE_LINKING);
4648 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4649 catch handler and return it. This prevents programs from violating the
4650 structured block semantics with throws. */
4652 static gimple_seq
4653 maybe_catch_exception (gimple_seq body)
4655 gimple g;
4656 tree decl;
4658 if (!flag_exceptions)
4659 return body;
4661 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4662 decl = lang_hooks.eh_protect_cleanup_actions ();
4663 else
4664 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4666 g = gimple_build_eh_must_not_throw (decl);
4667 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4668 GIMPLE_TRY_CATCH);
4670 return gimple_seq_alloc_with_stmt (g);
4673 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4675 static tree
4676 vec2chain (vec<tree, va_gc> *v)
4678 tree chain = NULL_TREE, t;
4679 unsigned ix;
4681 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4683 DECL_CHAIN (t) = chain;
4684 chain = t;
4687 return chain;
4691 /* Remove barriers in REGION->EXIT's block. Note that this is only
4692 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4693 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4694 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4695 removed. */
4697 static void
4698 remove_exit_barrier (struct omp_region *region)
4700 gimple_stmt_iterator gsi;
4701 basic_block exit_bb;
4702 edge_iterator ei;
4703 edge e;
4704 gimple stmt;
4705 int any_addressable_vars = -1;
4707 exit_bb = region->exit;
4709 /* If the parallel region doesn't return, we don't have REGION->EXIT
4710 block at all. */
4711 if (! exit_bb)
4712 return;
4714 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4715 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4716 statements that can appear in between are extremely limited -- no
4717 memory operations at all. Here, we allow nothing at all, so the
4718 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4719 gsi = gsi_last_bb (exit_bb);
4720 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4721 gsi_prev (&gsi);
4722 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4723 return;
4725 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4727 gsi = gsi_last_bb (e->src);
4728 if (gsi_end_p (gsi))
4729 continue;
4730 stmt = gsi_stmt (gsi);
4731 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4732 && !gimple_omp_return_nowait_p (stmt))
4734 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4735 in many cases. If there could be tasks queued, the barrier
4736 might be needed to let the tasks run before some local
4737 variable of the parallel that the task uses as shared
4738 runs out of scope. The task can be spawned either
4739 from within current function (this would be easy to check)
4740 or from some function it calls and gets passed an address
4741 of such a variable. */
4742 if (any_addressable_vars < 0)
4744 gomp_parallel *parallel_stmt =
4745 as_a <gomp_parallel *> (last_stmt (region->entry));
4746 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4747 tree local_decls, block, decl;
4748 unsigned ix;
4750 any_addressable_vars = 0;
4751 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4752 if (TREE_ADDRESSABLE (decl))
4754 any_addressable_vars = 1;
4755 break;
4757 for (block = gimple_block (stmt);
4758 !any_addressable_vars
4759 && block
4760 && TREE_CODE (block) == BLOCK;
4761 block = BLOCK_SUPERCONTEXT (block))
4763 for (local_decls = BLOCK_VARS (block);
4764 local_decls;
4765 local_decls = DECL_CHAIN (local_decls))
4766 if (TREE_ADDRESSABLE (local_decls))
4768 any_addressable_vars = 1;
4769 break;
4771 if (block == gimple_block (parallel_stmt))
4772 break;
4775 if (!any_addressable_vars)
4776 gimple_omp_return_set_nowait (stmt);
4781 static void
4782 remove_exit_barriers (struct omp_region *region)
4784 if (region->type == GIMPLE_OMP_PARALLEL)
4785 remove_exit_barrier (region);
4787 if (region->inner)
4789 region = region->inner;
4790 remove_exit_barriers (region);
4791 while (region->next)
4793 region = region->next;
4794 remove_exit_barriers (region);
4799 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4800 calls. These can't be declared as const functions, but
4801 within one parallel body they are constant, so they can be
4802 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4803 which are declared const. Similarly for task body, except
4804 that in untied task omp_get_thread_num () can change at any task
4805 scheduling point. */
4807 static void
4808 optimize_omp_library_calls (gimple entry_stmt)
4810 basic_block bb;
4811 gimple_stmt_iterator gsi;
4812 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4813 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4814 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4815 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4816 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4817 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4818 OMP_CLAUSE_UNTIED) != NULL);
4820 FOR_EACH_BB_FN (bb, cfun)
4821 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4823 gimple call = gsi_stmt (gsi);
4824 tree decl;
4826 if (is_gimple_call (call)
4827 && (decl = gimple_call_fndecl (call))
4828 && DECL_EXTERNAL (decl)
4829 && TREE_PUBLIC (decl)
4830 && DECL_INITIAL (decl) == NULL)
4832 tree built_in;
4834 if (DECL_NAME (decl) == thr_num_id)
4836 /* In #pragma omp task untied omp_get_thread_num () can change
4837 during the execution of the task region. */
4838 if (untied_task)
4839 continue;
4840 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4842 else if (DECL_NAME (decl) == num_thr_id)
4843 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4844 else
4845 continue;
4847 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4848 || gimple_call_num_args (call) != 0)
4849 continue;
4851 if (flag_exceptions && !TREE_NOTHROW (decl))
4852 continue;
4854 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4855 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4856 TREE_TYPE (TREE_TYPE (built_in))))
4857 continue;
4859 gimple_call_set_fndecl (call, built_in);
4864 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4865 regimplified. */
4867 static tree
4868 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4870 tree t = *tp;
4872 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4873 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4874 return t;
4876 if (TREE_CODE (t) == ADDR_EXPR)
4877 recompute_tree_invariant_for_addr_expr (t);
4879 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4880 return NULL_TREE;
4883 /* Prepend TO = FROM assignment before *GSI_P. */
4885 static void
4886 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4888 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4889 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4890 true, GSI_SAME_STMT);
4891 gimple stmt = gimple_build_assign (to, from);
4892 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4893 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4894 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4896 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4897 gimple_regimplify_operands (stmt, &gsi);
4901 /* Expand the OpenMP parallel or task directive starting at REGION. */
4903 static void
4904 expand_omp_taskreg (struct omp_region *region)
4906 basic_block entry_bb, exit_bb, new_bb;
4907 struct function *child_cfun;
4908 tree child_fn, block, t;
4909 gimple_stmt_iterator gsi;
4910 gimple entry_stmt, stmt;
4911 edge e;
4912 vec<tree, va_gc> *ws_args;
4914 entry_stmt = last_stmt (region->entry);
4915 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4916 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4918 entry_bb = region->entry;
4919 exit_bb = region->exit;
4921 bool is_cilk_for
4922 = (flag_cilkplus
4923 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
4924 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
4925 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
4927 if (is_cilk_for)
4928 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
4929 and the inner statement contains the name of the built-in function
4930 and grain. */
4931 ws_args = region->inner->ws_args;
4932 else if (is_combined_parallel (region))
4933 ws_args = region->ws_args;
4934 else
4935 ws_args = NULL;
4937 if (child_cfun->cfg)
4939 /* Due to inlining, it may happen that we have already outlined
4940 the region, in which case all we need to do is make the
4941 sub-graph unreachable and emit the parallel call. */
4942 edge entry_succ_e, exit_succ_e;
4944 entry_succ_e = single_succ_edge (entry_bb);
4946 gsi = gsi_last_bb (entry_bb);
4947 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4948 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4949 gsi_remove (&gsi, true);
4951 new_bb = entry_bb;
4952 if (exit_bb)
4954 exit_succ_e = single_succ_edge (exit_bb);
4955 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4957 remove_edge_and_dominated_blocks (entry_succ_e);
4959 else
4961 unsigned srcidx, dstidx, num;
4963 /* If the parallel region needs data sent from the parent
4964 function, then the very first statement (except possible
4965 tree profile counter updates) of the parallel body
4966 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4967 &.OMP_DATA_O is passed as an argument to the child function,
4968 we need to replace it with the argument as seen by the child
4969 function.
4971 In most cases, this will end up being the identity assignment
4972 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4973 a function call that has been inlined, the original PARM_DECL
4974 .OMP_DATA_I may have been converted into a different local
4975 variable. In which case, we need to keep the assignment. */
4976 if (gimple_omp_taskreg_data_arg (entry_stmt))
4978 basic_block entry_succ_bb = single_succ (entry_bb);
4979 tree arg, narg;
4980 gimple parcopy_stmt = NULL;
4982 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4984 gimple stmt;
4986 gcc_assert (!gsi_end_p (gsi));
4987 stmt = gsi_stmt (gsi);
4988 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4989 continue;
4991 if (gimple_num_ops (stmt) == 2)
4993 tree arg = gimple_assign_rhs1 (stmt);
4995 /* We're ignore the subcode because we're
4996 effectively doing a STRIP_NOPS. */
4998 if (TREE_CODE (arg) == ADDR_EXPR
4999 && TREE_OPERAND (arg, 0)
5000 == gimple_omp_taskreg_data_arg (entry_stmt))
5002 parcopy_stmt = stmt;
5003 break;
5008 gcc_assert (parcopy_stmt != NULL);
5009 arg = DECL_ARGUMENTS (child_fn);
5011 if (!gimple_in_ssa_p (cfun))
5013 if (gimple_assign_lhs (parcopy_stmt) == arg)
5014 gsi_remove (&gsi, true);
5015 else
5017 /* ?? Is setting the subcode really necessary ?? */
5018 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5019 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5022 else
5024 /* If we are in ssa form, we must load the value from the default
5025 definition of the argument. That should not be defined now,
5026 since the argument is not used uninitialized. */
5027 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5028 narg = make_ssa_name (arg, gimple_build_nop ());
5029 set_ssa_default_def (cfun, arg, narg);
5030 /* ?? Is setting the subcode really necessary ?? */
5031 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5032 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5033 update_stmt (parcopy_stmt);
5037 /* Declare local variables needed in CHILD_CFUN. */
5038 block = DECL_INITIAL (child_fn);
5039 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5040 /* The gimplifier could record temporaries in parallel/task block
5041 rather than in containing function's local_decls chain,
5042 which would mean cgraph missed finalizing them. Do it now. */
5043 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5044 if (TREE_CODE (t) == VAR_DECL
5045 && TREE_STATIC (t)
5046 && !DECL_EXTERNAL (t))
5047 varpool_node::finalize_decl (t);
5048 DECL_SAVED_TREE (child_fn) = NULL;
5049 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5050 gimple_set_body (child_fn, NULL);
5051 TREE_USED (block) = 1;
5053 /* Reset DECL_CONTEXT on function arguments. */
5054 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5055 DECL_CONTEXT (t) = child_fn;
5057 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5058 so that it can be moved to the child function. */
5059 gsi = gsi_last_bb (entry_bb);
5060 stmt = gsi_stmt (gsi);
5061 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5062 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5063 gsi_remove (&gsi, true);
5064 e = split_block (entry_bb, stmt);
5065 entry_bb = e->dest;
5066 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5068 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5069 if (exit_bb)
5071 gsi = gsi_last_bb (exit_bb);
5072 gcc_assert (!gsi_end_p (gsi)
5073 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5074 stmt = gimple_build_return (NULL);
5075 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5076 gsi_remove (&gsi, true);
5079 /* Move the parallel region into CHILD_CFUN. */
5081 if (gimple_in_ssa_p (cfun))
5083 init_tree_ssa (child_cfun);
5084 init_ssa_operands (child_cfun);
5085 child_cfun->gimple_df->in_ssa_p = true;
5086 block = NULL_TREE;
5088 else
5089 block = gimple_block (entry_stmt);
5091 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5092 if (exit_bb)
5093 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5094 /* When the OMP expansion process cannot guarantee an up-to-date
5095 loop tree arrange for the child function to fixup loops. */
5096 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5097 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5099 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5100 num = vec_safe_length (child_cfun->local_decls);
5101 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5103 t = (*child_cfun->local_decls)[srcidx];
5104 if (DECL_CONTEXT (t) == cfun->decl)
5105 continue;
5106 if (srcidx != dstidx)
5107 (*child_cfun->local_decls)[dstidx] = t;
5108 dstidx++;
5110 if (dstidx != num)
5111 vec_safe_truncate (child_cfun->local_decls, dstidx);
5113 /* Inform the callgraph about the new function. */
5114 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5115 cgraph_node::add_new_function (child_fn, true);
5117 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5118 fixed in a following pass. */
5119 push_cfun (child_cfun);
5120 if (optimize)
5121 optimize_omp_library_calls (entry_stmt);
5122 cgraph_edge::rebuild_edges ();
5124 /* Some EH regions might become dead, see PR34608. If
5125 pass_cleanup_cfg isn't the first pass to happen with the
5126 new child, these dead EH edges might cause problems.
5127 Clean them up now. */
5128 if (flag_exceptions)
5130 basic_block bb;
5131 bool changed = false;
5133 FOR_EACH_BB_FN (bb, cfun)
5134 changed |= gimple_purge_dead_eh_edges (bb);
5135 if (changed)
5136 cleanup_tree_cfg ();
5138 if (gimple_in_ssa_p (cfun))
5139 update_ssa (TODO_update_ssa);
5140 pop_cfun ();
5143 /* Emit a library call to launch the children threads. */
5144 if (is_cilk_for)
5145 expand_cilk_for_call (new_bb,
5146 as_a <gomp_parallel *> (entry_stmt), ws_args);
5147 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5148 expand_parallel_call (region, new_bb,
5149 as_a <gomp_parallel *> (entry_stmt), ws_args);
5150 else
5151 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5152 if (gimple_in_ssa_p (cfun))
5153 update_ssa (TODO_update_ssa_only_virtuals);
5157 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5158 of the combined collapse > 1 loop constructs, generate code like:
5159 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5160 if (cond3 is <)
5161 adj = STEP3 - 1;
5162 else
5163 adj = STEP3 + 1;
5164 count3 = (adj + N32 - N31) / STEP3;
5165 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5166 if (cond2 is <)
5167 adj = STEP2 - 1;
5168 else
5169 adj = STEP2 + 1;
5170 count2 = (adj + N22 - N21) / STEP2;
5171 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5172 if (cond1 is <)
5173 adj = STEP1 - 1;
5174 else
5175 adj = STEP1 + 1;
5176 count1 = (adj + N12 - N11) / STEP1;
5177 count = count1 * count2 * count3;
5178 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5179 count = 0;
5180 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5181 of the combined loop constructs, just initialize COUNTS array
5182 from the _looptemp_ clauses. */
5184 /* NOTE: It *could* be better to moosh all of the BBs together,
5185 creating one larger BB with all the computation and the unexpected
5186 jump at the end. I.e.
5188 bool zero3, zero2, zero1, zero;
5190 zero3 = N32 c3 N31;
5191 count3 = (N32 - N31) /[cl] STEP3;
5192 zero2 = N22 c2 N21;
5193 count2 = (N22 - N21) /[cl] STEP2;
5194 zero1 = N12 c1 N11;
5195 count1 = (N12 - N11) /[cl] STEP1;
5196 zero = zero3 || zero2 || zero1;
5197 count = count1 * count2 * count3;
5198 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5200 After all, we expect the zero=false, and thus we expect to have to
5201 evaluate all of the comparison expressions, so short-circuiting
5202 oughtn't be a win. Since the condition isn't protecting a
5203 denominator, we're not concerned about divide-by-zero, so we can
5204 fully evaluate count even if a numerator turned out to be wrong.
5206 It seems like putting this all together would create much better
5207 scheduling opportunities, and less pressure on the chip's branch
5208 predictor. */
5210 static void
5211 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5212 basic_block &entry_bb, tree *counts,
5213 basic_block &zero_iter_bb, int &first_zero_iter,
5214 basic_block &l2_dom_bb)
5216 tree t, type = TREE_TYPE (fd->loop.v);
5217 edge e, ne;
5218 int i;
5220 /* Collapsed loops need work for expansion into SSA form. */
5221 gcc_assert (!gimple_in_ssa_p (cfun));
5223 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5224 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5226 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5227 isn't supposed to be handled, as the inner loop doesn't
5228 use it. */
5229 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5230 OMP_CLAUSE__LOOPTEMP_);
5231 gcc_assert (innerc);
5232 for (i = 0; i < fd->collapse; i++)
5234 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5235 OMP_CLAUSE__LOOPTEMP_);
5236 gcc_assert (innerc);
5237 if (i)
5238 counts[i] = OMP_CLAUSE_DECL (innerc);
5239 else
5240 counts[0] = NULL_TREE;
5242 return;
5245 for (i = 0; i < fd->collapse; i++)
5247 tree itype = TREE_TYPE (fd->loops[i].v);
5249 if (SSA_VAR_P (fd->loop.n2)
5250 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5251 fold_convert (itype, fd->loops[i].n1),
5252 fold_convert (itype, fd->loops[i].n2)))
5253 == NULL_TREE || !integer_onep (t)))
5255 gcond *cond_stmt;
5256 tree n1, n2;
5257 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5258 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5259 true, GSI_SAME_STMT);
5260 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5261 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5262 true, GSI_SAME_STMT);
5263 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5264 NULL_TREE, NULL_TREE);
5265 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5266 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5267 expand_omp_regimplify_p, NULL, NULL)
5268 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5269 expand_omp_regimplify_p, NULL, NULL))
5271 *gsi = gsi_for_stmt (cond_stmt);
5272 gimple_regimplify_operands (cond_stmt, gsi);
5274 e = split_block (entry_bb, cond_stmt);
5275 if (zero_iter_bb == NULL)
5277 gassign *assign_stmt;
5278 first_zero_iter = i;
5279 zero_iter_bb = create_empty_bb (entry_bb);
5280 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5281 *gsi = gsi_after_labels (zero_iter_bb);
5282 assign_stmt = gimple_build_assign (fd->loop.n2,
5283 build_zero_cst (type));
5284 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5285 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5286 entry_bb);
5288 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5289 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5290 e->flags = EDGE_TRUE_VALUE;
5291 e->probability = REG_BR_PROB_BASE - ne->probability;
5292 if (l2_dom_bb == NULL)
5293 l2_dom_bb = entry_bb;
5294 entry_bb = e->dest;
5295 *gsi = gsi_last_bb (entry_bb);
5298 if (POINTER_TYPE_P (itype))
5299 itype = signed_type_for (itype);
5300 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5301 ? -1 : 1));
5302 t = fold_build2 (PLUS_EXPR, itype,
5303 fold_convert (itype, fd->loops[i].step), t);
5304 t = fold_build2 (PLUS_EXPR, itype, t,
5305 fold_convert (itype, fd->loops[i].n2));
5306 t = fold_build2 (MINUS_EXPR, itype, t,
5307 fold_convert (itype, fd->loops[i].n1));
5308 /* ?? We could probably use CEIL_DIV_EXPR instead of
5309 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5310 generate the same code in the end because generically we
5311 don't know that the values involved must be negative for
5312 GT?? */
5313 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5314 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5315 fold_build1 (NEGATE_EXPR, itype, t),
5316 fold_build1 (NEGATE_EXPR, itype,
5317 fold_convert (itype,
5318 fd->loops[i].step)));
5319 else
5320 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5321 fold_convert (itype, fd->loops[i].step));
5322 t = fold_convert (type, t);
5323 if (TREE_CODE (t) == INTEGER_CST)
5324 counts[i] = t;
5325 else
5327 counts[i] = create_tmp_reg (type, ".count");
5328 expand_omp_build_assign (gsi, counts[i], t);
5330 if (SSA_VAR_P (fd->loop.n2))
5332 if (i == 0)
5333 t = counts[0];
5334 else
5335 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5336 expand_omp_build_assign (gsi, fd->loop.n2, t);
5342 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5343 T = V;
5344 V3 = N31 + (T % count3) * STEP3;
5345 T = T / count3;
5346 V2 = N21 + (T % count2) * STEP2;
5347 T = T / count2;
5348 V1 = N11 + T * STEP1;
5349 if this loop doesn't have an inner loop construct combined with it.
5350 If it does have an inner loop construct combined with it and the
5351 iteration count isn't known constant, store values from counts array
5352 into its _looptemp_ temporaries instead. */
5354 static void
5355 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5356 tree *counts, gimple inner_stmt, tree startvar)
5358 int i;
5359 if (gimple_omp_for_combined_p (fd->for_stmt))
5361 /* If fd->loop.n2 is constant, then no propagation of the counts
5362 is needed, they are constant. */
5363 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5364 return;
5366 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5367 ? gimple_omp_parallel_clauses (inner_stmt)
5368 : gimple_omp_for_clauses (inner_stmt);
5369 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5370 isn't supposed to be handled, as the inner loop doesn't
5371 use it. */
5372 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5373 gcc_assert (innerc);
5374 for (i = 0; i < fd->collapse; i++)
5376 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5377 OMP_CLAUSE__LOOPTEMP_);
5378 gcc_assert (innerc);
5379 if (i)
5381 tree tem = OMP_CLAUSE_DECL (innerc);
5382 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5383 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5384 false, GSI_CONTINUE_LINKING);
5385 gassign *stmt = gimple_build_assign (tem, t);
5386 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5389 return;
5392 tree type = TREE_TYPE (fd->loop.v);
5393 tree tem = create_tmp_reg (type, ".tem");
5394 gassign *stmt = gimple_build_assign (tem, startvar);
5395 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5397 for (i = fd->collapse - 1; i >= 0; i--)
5399 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5400 itype = vtype;
5401 if (POINTER_TYPE_P (vtype))
5402 itype = signed_type_for (vtype);
5403 if (i != 0)
5404 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5405 else
5406 t = tem;
5407 t = fold_convert (itype, t);
5408 t = fold_build2 (MULT_EXPR, itype, t,
5409 fold_convert (itype, fd->loops[i].step));
5410 if (POINTER_TYPE_P (vtype))
5411 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5412 else
5413 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5414 t = force_gimple_operand_gsi (gsi, t,
5415 DECL_P (fd->loops[i].v)
5416 && TREE_ADDRESSABLE (fd->loops[i].v),
5417 NULL_TREE, false,
5418 GSI_CONTINUE_LINKING);
5419 stmt = gimple_build_assign (fd->loops[i].v, t);
5420 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5421 if (i != 0)
5423 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5424 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5425 false, GSI_CONTINUE_LINKING);
5426 stmt = gimple_build_assign (tem, t);
5427 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5433 /* Helper function for expand_omp_for_*. Generate code like:
5434 L10:
5435 V3 += STEP3;
5436 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5437 L11:
5438 V3 = N31;
5439 V2 += STEP2;
5440 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5441 L12:
5442 V2 = N21;
5443 V1 += STEP1;
5444 goto BODY_BB; */
5446 static basic_block
5447 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5448 basic_block body_bb)
5450 basic_block last_bb, bb, collapse_bb = NULL;
5451 int i;
5452 gimple_stmt_iterator gsi;
5453 edge e;
5454 tree t;
5455 gimple stmt;
5457 last_bb = cont_bb;
5458 for (i = fd->collapse - 1; i >= 0; i--)
5460 tree vtype = TREE_TYPE (fd->loops[i].v);
5462 bb = create_empty_bb (last_bb);
5463 add_bb_to_loop (bb, last_bb->loop_father);
5464 gsi = gsi_start_bb (bb);
5466 if (i < fd->collapse - 1)
5468 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5469 e->probability = REG_BR_PROB_BASE / 8;
5471 t = fd->loops[i + 1].n1;
5472 t = force_gimple_operand_gsi (&gsi, t,
5473 DECL_P (fd->loops[i + 1].v)
5474 && TREE_ADDRESSABLE (fd->loops[i
5475 + 1].v),
5476 NULL_TREE, false,
5477 GSI_CONTINUE_LINKING);
5478 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5479 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5481 else
5482 collapse_bb = bb;
5484 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5486 if (POINTER_TYPE_P (vtype))
5487 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5488 else
5489 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5490 t = force_gimple_operand_gsi (&gsi, t,
5491 DECL_P (fd->loops[i].v)
5492 && TREE_ADDRESSABLE (fd->loops[i].v),
5493 NULL_TREE, false, GSI_CONTINUE_LINKING);
5494 stmt = gimple_build_assign (fd->loops[i].v, t);
5495 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5497 if (i > 0)
5499 t = fd->loops[i].n2;
5500 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5501 false, GSI_CONTINUE_LINKING);
5502 tree v = fd->loops[i].v;
5503 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5504 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5505 false, GSI_CONTINUE_LINKING);
5506 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5507 stmt = gimple_build_cond_empty (t);
5508 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5509 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5510 e->probability = REG_BR_PROB_BASE * 7 / 8;
5512 else
5513 make_edge (bb, body_bb, EDGE_FALLTHRU);
5514 last_bb = bb;
5517 return collapse_bb;
5521 /* A subroutine of expand_omp_for. Generate code for a parallel
5522 loop with any schedule. Given parameters:
5524 for (V = N1; V cond N2; V += STEP) BODY;
5526 where COND is "<" or ">", we generate pseudocode
5528 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5529 if (more) goto L0; else goto L3;
5531 V = istart0;
5532 iend = iend0;
5534 BODY;
5535 V += STEP;
5536 if (V cond iend) goto L1; else goto L2;
5538 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5541 If this is a combined omp parallel loop, instead of the call to
5542 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5543 If this is gimple_omp_for_combined_p loop, then instead of assigning
5544 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5545 inner GIMPLE_OMP_FOR and V += STEP; and
5546 if (V cond iend) goto L1; else goto L2; are removed.
5548 For collapsed loops, given parameters:
5549 collapse(3)
5550 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5551 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5552 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5553 BODY;
5555 we generate pseudocode
5557 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5558 if (cond3 is <)
5559 adj = STEP3 - 1;
5560 else
5561 adj = STEP3 + 1;
5562 count3 = (adj + N32 - N31) / STEP3;
5563 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5564 if (cond2 is <)
5565 adj = STEP2 - 1;
5566 else
5567 adj = STEP2 + 1;
5568 count2 = (adj + N22 - N21) / STEP2;
5569 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5570 if (cond1 is <)
5571 adj = STEP1 - 1;
5572 else
5573 adj = STEP1 + 1;
5574 count1 = (adj + N12 - N11) / STEP1;
5575 count = count1 * count2 * count3;
5576 goto Z1;
5578 count = 0;
5580 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5581 if (more) goto L0; else goto L3;
5583 V = istart0;
5584 T = V;
5585 V3 = N31 + (T % count3) * STEP3;
5586 T = T / count3;
5587 V2 = N21 + (T % count2) * STEP2;
5588 T = T / count2;
5589 V1 = N11 + T * STEP1;
5590 iend = iend0;
5592 BODY;
5593 V += 1;
5594 if (V < iend) goto L10; else goto L2;
5595 L10:
5596 V3 += STEP3;
5597 if (V3 cond3 N32) goto L1; else goto L11;
5598 L11:
5599 V3 = N31;
5600 V2 += STEP2;
5601 if (V2 cond2 N22) goto L1; else goto L12;
5602 L12:
5603 V2 = N21;
5604 V1 += STEP1;
5605 goto L1;
5607 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5612 static void
5613 expand_omp_for_generic (struct omp_region *region,
5614 struct omp_for_data *fd,
5615 enum built_in_function start_fn,
5616 enum built_in_function next_fn,
5617 gimple inner_stmt)
5619 tree type, istart0, iend0, iend;
5620 tree t, vmain, vback, bias = NULL_TREE;
5621 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5622 basic_block l2_bb = NULL, l3_bb = NULL;
5623 gimple_stmt_iterator gsi;
5624 gassign *assign_stmt;
5625 bool in_combined_parallel = is_combined_parallel (region);
5626 bool broken_loop = region->cont == NULL;
5627 edge e, ne;
5628 tree *counts = NULL;
5629 int i;
5631 gcc_assert (!broken_loop || !in_combined_parallel);
5632 gcc_assert (fd->iter_type == long_integer_type_node
5633 || !in_combined_parallel);
5635 type = TREE_TYPE (fd->loop.v);
5636 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5637 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5638 TREE_ADDRESSABLE (istart0) = 1;
5639 TREE_ADDRESSABLE (iend0) = 1;
5641 /* See if we need to bias by LLONG_MIN. */
5642 if (fd->iter_type == long_long_unsigned_type_node
5643 && TREE_CODE (type) == INTEGER_TYPE
5644 && !TYPE_UNSIGNED (type))
5646 tree n1, n2;
5648 if (fd->loop.cond_code == LT_EXPR)
5650 n1 = fd->loop.n1;
5651 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5653 else
5655 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5656 n2 = fd->loop.n1;
5658 if (TREE_CODE (n1) != INTEGER_CST
5659 || TREE_CODE (n2) != INTEGER_CST
5660 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5661 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5664 entry_bb = region->entry;
5665 cont_bb = region->cont;
5666 collapse_bb = NULL;
5667 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5668 gcc_assert (broken_loop
5669 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5670 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5671 l1_bb = single_succ (l0_bb);
5672 if (!broken_loop)
5674 l2_bb = create_empty_bb (cont_bb);
5675 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5676 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5678 else
5679 l2_bb = NULL;
5680 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5681 exit_bb = region->exit;
5683 gsi = gsi_last_bb (entry_bb);
5685 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5686 if (fd->collapse > 1)
5688 int first_zero_iter = -1;
5689 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5691 counts = XALLOCAVEC (tree, fd->collapse);
5692 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5693 zero_iter_bb, first_zero_iter,
5694 l2_dom_bb);
5696 if (zero_iter_bb)
5698 /* Some counts[i] vars might be uninitialized if
5699 some loop has zero iterations. But the body shouldn't
5700 be executed in that case, so just avoid uninit warnings. */
5701 for (i = first_zero_iter; i < fd->collapse; i++)
5702 if (SSA_VAR_P (counts[i]))
5703 TREE_NO_WARNING (counts[i]) = 1;
5704 gsi_prev (&gsi);
5705 e = split_block (entry_bb, gsi_stmt (gsi));
5706 entry_bb = e->dest;
5707 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5708 gsi = gsi_last_bb (entry_bb);
5709 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5710 get_immediate_dominator (CDI_DOMINATORS,
5711 zero_iter_bb));
5714 if (in_combined_parallel)
5716 /* In a combined parallel loop, emit a call to
5717 GOMP_loop_foo_next. */
5718 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5719 build_fold_addr_expr (istart0),
5720 build_fold_addr_expr (iend0));
5722 else
5724 tree t0, t1, t2, t3, t4;
5725 /* If this is not a combined parallel loop, emit a call to
5726 GOMP_loop_foo_start in ENTRY_BB. */
5727 t4 = build_fold_addr_expr (iend0);
5728 t3 = build_fold_addr_expr (istart0);
5729 t2 = fold_convert (fd->iter_type, fd->loop.step);
5730 t1 = fd->loop.n2;
5731 t0 = fd->loop.n1;
5732 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5734 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5735 OMP_CLAUSE__LOOPTEMP_);
5736 gcc_assert (innerc);
5737 t0 = OMP_CLAUSE_DECL (innerc);
5738 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5739 OMP_CLAUSE__LOOPTEMP_);
5740 gcc_assert (innerc);
5741 t1 = OMP_CLAUSE_DECL (innerc);
5743 if (POINTER_TYPE_P (TREE_TYPE (t0))
5744 && TYPE_PRECISION (TREE_TYPE (t0))
5745 != TYPE_PRECISION (fd->iter_type))
5747 /* Avoid casting pointers to integer of a different size. */
5748 tree itype = signed_type_for (type);
5749 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5750 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5752 else
5754 t1 = fold_convert (fd->iter_type, t1);
5755 t0 = fold_convert (fd->iter_type, t0);
5757 if (bias)
5759 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5760 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5762 if (fd->iter_type == long_integer_type_node)
5764 if (fd->chunk_size)
5766 t = fold_convert (fd->iter_type, fd->chunk_size);
5767 t = build_call_expr (builtin_decl_explicit (start_fn),
5768 6, t0, t1, t2, t, t3, t4);
5770 else
5771 t = build_call_expr (builtin_decl_explicit (start_fn),
5772 5, t0, t1, t2, t3, t4);
5774 else
5776 tree t5;
5777 tree c_bool_type;
5778 tree bfn_decl;
5780 /* The GOMP_loop_ull_*start functions have additional boolean
5781 argument, true for < loops and false for > loops.
5782 In Fortran, the C bool type can be different from
5783 boolean_type_node. */
5784 bfn_decl = builtin_decl_explicit (start_fn);
5785 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5786 t5 = build_int_cst (c_bool_type,
5787 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5788 if (fd->chunk_size)
5790 tree bfn_decl = builtin_decl_explicit (start_fn);
5791 t = fold_convert (fd->iter_type, fd->chunk_size);
5792 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5794 else
5795 t = build_call_expr (builtin_decl_explicit (start_fn),
5796 6, t5, t0, t1, t2, t3, t4);
5799 if (TREE_TYPE (t) != boolean_type_node)
5800 t = fold_build2 (NE_EXPR, boolean_type_node,
5801 t, build_int_cst (TREE_TYPE (t), 0));
5802 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5803 true, GSI_SAME_STMT);
5804 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5806 /* Remove the GIMPLE_OMP_FOR statement. */
5807 gsi_remove (&gsi, true);
5809 /* Iteration setup for sequential loop goes in L0_BB. */
5810 tree startvar = fd->loop.v;
5811 tree endvar = NULL_TREE;
5813 if (gimple_omp_for_combined_p (fd->for_stmt))
5815 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5816 && gimple_omp_for_kind (inner_stmt)
5817 == GF_OMP_FOR_KIND_SIMD);
5818 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5819 OMP_CLAUSE__LOOPTEMP_);
5820 gcc_assert (innerc);
5821 startvar = OMP_CLAUSE_DECL (innerc);
5822 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5823 OMP_CLAUSE__LOOPTEMP_);
5824 gcc_assert (innerc);
5825 endvar = OMP_CLAUSE_DECL (innerc);
5828 gsi = gsi_start_bb (l0_bb);
5829 t = istart0;
5830 if (bias)
5831 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5832 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5833 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5834 t = fold_convert (TREE_TYPE (startvar), t);
5835 t = force_gimple_operand_gsi (&gsi, t,
5836 DECL_P (startvar)
5837 && TREE_ADDRESSABLE (startvar),
5838 NULL_TREE, false, GSI_CONTINUE_LINKING);
5839 assign_stmt = gimple_build_assign (startvar, t);
5840 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5842 t = iend0;
5843 if (bias)
5844 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5845 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5846 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5847 t = fold_convert (TREE_TYPE (startvar), t);
5848 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5849 false, GSI_CONTINUE_LINKING);
5850 if (endvar)
5852 assign_stmt = gimple_build_assign (endvar, iend);
5853 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5854 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
5855 assign_stmt = gimple_build_assign (fd->loop.v, iend);
5856 else
5857 assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend,
5858 NULL_TREE);
5859 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5861 if (fd->collapse > 1)
5862 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5864 if (!broken_loop)
5866 /* Code to control the increment and predicate for the sequential
5867 loop goes in the CONT_BB. */
5868 gsi = gsi_last_bb (cont_bb);
5869 gomp_continue *cont_stmt =
5870 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 NULL_TREE);
6281 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6283 if (fd->collapse > 1)
6284 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6286 if (!broken_loop)
6288 /* The code controlling the sequential loop replaces the
6289 GIMPLE_OMP_CONTINUE. */
6290 gsi = gsi_last_bb (cont_bb);
6291 gomp_continue *cont_stmt =
6292 as_a <gomp_continue *> (gsi_stmt (gsi));
6293 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6294 vmain = gimple_omp_continue_control_use (cont_stmt);
6295 vback = gimple_omp_continue_control_def (cont_stmt);
6297 if (!gimple_omp_for_combined_p (fd->for_stmt))
6299 if (POINTER_TYPE_P (type))
6300 t = fold_build_pointer_plus (vmain, step);
6301 else
6302 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6303 t = force_gimple_operand_gsi (&gsi, t,
6304 DECL_P (vback)
6305 && TREE_ADDRESSABLE (vback),
6306 NULL_TREE, true, GSI_SAME_STMT);
6307 assign_stmt = gimple_build_assign (vback, t);
6308 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6310 t = build2 (fd->loop.cond_code, boolean_type_node,
6311 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6312 ? t : vback, e);
6313 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6316 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6317 gsi_remove (&gsi, true);
6319 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6320 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6323 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6324 gsi = gsi_last_bb (exit_bb);
6325 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6327 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6328 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6330 gsi_remove (&gsi, true);
6332 /* Connect all the blocks. */
6333 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6334 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6335 ep = find_edge (entry_bb, second_bb);
6336 ep->flags = EDGE_TRUE_VALUE;
6337 ep->probability = REG_BR_PROB_BASE / 4;
6338 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6339 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6341 if (!broken_loop)
6343 ep = find_edge (cont_bb, body_bb);
6344 if (gimple_omp_for_combined_p (fd->for_stmt))
6346 remove_edge (ep);
6347 ep = NULL;
6349 else if (fd->collapse > 1)
6351 remove_edge (ep);
6352 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6354 else
6355 ep->flags = EDGE_TRUE_VALUE;
6356 find_edge (cont_bb, fin_bb)->flags
6357 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6360 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6361 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6362 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6364 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6365 recompute_dominator (CDI_DOMINATORS, body_bb));
6366 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6367 recompute_dominator (CDI_DOMINATORS, fin_bb));
6369 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6371 struct loop *loop = alloc_loop ();
6372 loop->header = body_bb;
6373 if (collapse_bb == NULL)
6374 loop->latch = cont_bb;
6375 add_loop (loop, body_bb->loop_father);
6380 /* A subroutine of expand_omp_for. Generate code for a parallel
6381 loop with static schedule and a specified chunk size. Given
6382 parameters:
6384 for (V = N1; V cond N2; V += STEP) BODY;
6386 where COND is "<" or ">", we generate pseudocode
6388 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6389 if (cond is <)
6390 adj = STEP - 1;
6391 else
6392 adj = STEP + 1;
6393 if ((__typeof (V)) -1 > 0 && cond is >)
6394 n = -(adj + N2 - N1) / -STEP;
6395 else
6396 n = (adj + N2 - N1) / STEP;
6397 trip = 0;
6398 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6399 here so that V is defined
6400 if the loop is not entered
6402 s0 = (trip * nthreads + threadid) * CHUNK;
6403 e0 = min(s0 + CHUNK, n);
6404 if (s0 < n) goto L1; else goto L4;
6406 V = s0 * STEP + N1;
6407 e = e0 * STEP + N1;
6409 BODY;
6410 V += STEP;
6411 if (V cond e) goto L2; else goto L3;
6413 trip += 1;
6414 goto L0;
6418 static void
6419 expand_omp_for_static_chunk (struct omp_region *region,
6420 struct omp_for_data *fd, gimple inner_stmt)
6422 tree n, s0, e0, e, t;
6423 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6424 tree type, itype, vmain, vback, vextra;
6425 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6426 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6427 gimple_stmt_iterator gsi;
6428 edge se;
6429 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6430 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6431 bool broken_loop = region->cont == NULL;
6432 tree *counts = NULL;
6433 tree n1, n2, step;
6435 itype = type = TREE_TYPE (fd->loop.v);
6436 if (POINTER_TYPE_P (type))
6437 itype = signed_type_for (type);
6439 entry_bb = region->entry;
6440 se = split_block (entry_bb, last_stmt (entry_bb));
6441 entry_bb = se->src;
6442 iter_part_bb = se->dest;
6443 cont_bb = region->cont;
6444 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6445 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6446 gcc_assert (broken_loop
6447 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6448 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6449 body_bb = single_succ (seq_start_bb);
6450 if (!broken_loop)
6452 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6453 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6454 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6456 exit_bb = region->exit;
6458 /* Trip and adjustment setup goes in ENTRY_BB. */
6459 gsi = gsi_last_bb (entry_bb);
6460 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6462 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6464 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6465 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6468 if (fd->collapse > 1)
6470 int first_zero_iter = -1;
6471 basic_block l2_dom_bb = NULL;
6473 counts = XALLOCAVEC (tree, fd->collapse);
6474 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6475 fin_bb, first_zero_iter,
6476 l2_dom_bb);
6477 t = NULL_TREE;
6479 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6480 t = integer_one_node;
6481 else
6482 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6483 fold_convert (type, fd->loop.n1),
6484 fold_convert (type, fd->loop.n2));
6485 if (fd->collapse == 1
6486 && TYPE_UNSIGNED (type)
6487 && (t == NULL_TREE || !integer_onep (t)))
6489 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6490 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6491 true, GSI_SAME_STMT);
6492 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6493 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6494 true, GSI_SAME_STMT);
6495 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6496 NULL_TREE, NULL_TREE);
6497 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6498 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6499 expand_omp_regimplify_p, NULL, NULL)
6500 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6501 expand_omp_regimplify_p, NULL, NULL))
6503 gsi = gsi_for_stmt (cond_stmt);
6504 gimple_regimplify_operands (cond_stmt, &gsi);
6506 se = split_block (entry_bb, cond_stmt);
6507 se->flags = EDGE_TRUE_VALUE;
6508 entry_bb = se->dest;
6509 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6510 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6511 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6512 if (gimple_in_ssa_p (cfun))
6514 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6515 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6516 !gsi_end_p (gpi); gsi_next (&gpi))
6518 gphi *phi = gpi.phi ();
6519 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6520 se, UNKNOWN_LOCATION);
6523 gsi = gsi_last_bb (entry_bb);
6526 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6527 t = fold_convert (itype, t);
6528 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6529 true, GSI_SAME_STMT);
6531 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6532 t = fold_convert (itype, t);
6533 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6534 true, GSI_SAME_STMT);
6536 n1 = fd->loop.n1;
6537 n2 = fd->loop.n2;
6538 step = fd->loop.step;
6539 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6541 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6542 OMP_CLAUSE__LOOPTEMP_);
6543 gcc_assert (innerc);
6544 n1 = OMP_CLAUSE_DECL (innerc);
6545 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6546 OMP_CLAUSE__LOOPTEMP_);
6547 gcc_assert (innerc);
6548 n2 = OMP_CLAUSE_DECL (innerc);
6550 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6551 true, NULL_TREE, true, GSI_SAME_STMT);
6552 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6553 true, NULL_TREE, true, GSI_SAME_STMT);
6554 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6555 true, NULL_TREE, true, GSI_SAME_STMT);
6556 fd->chunk_size
6557 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
6558 true, NULL_TREE, true, GSI_SAME_STMT);
6560 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6561 t = fold_build2 (PLUS_EXPR, itype, step, t);
6562 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6563 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6564 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6565 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6566 fold_build1 (NEGATE_EXPR, itype, t),
6567 fold_build1 (NEGATE_EXPR, itype, step));
6568 else
6569 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6570 t = fold_convert (itype, t);
6571 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6572 true, GSI_SAME_STMT);
6574 trip_var = create_tmp_reg (itype, ".trip");
6575 if (gimple_in_ssa_p (cfun))
6577 trip_init = make_ssa_name (trip_var, NULL);
6578 trip_main = make_ssa_name (trip_var, NULL);
6579 trip_back = make_ssa_name (trip_var, NULL);
6581 else
6583 trip_init = trip_var;
6584 trip_main = trip_var;
6585 trip_back = trip_var;
6588 gassign *assign_stmt =
6589 gimple_build_assign (trip_init, build_int_cst (itype, 0));
6590 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6592 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6593 t = fold_build2 (MULT_EXPR, itype, t, step);
6594 if (POINTER_TYPE_P (type))
6595 t = fold_build_pointer_plus (n1, t);
6596 else
6597 t = fold_build2 (PLUS_EXPR, type, t, n1);
6598 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6599 true, GSI_SAME_STMT);
6601 /* Remove the GIMPLE_OMP_FOR. */
6602 gsi_remove (&gsi, true);
6604 /* Iteration space partitioning goes in ITER_PART_BB. */
6605 gsi = gsi_last_bb (iter_part_bb);
6607 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6608 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6609 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6610 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6611 false, GSI_CONTINUE_LINKING);
6613 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6614 t = fold_build2 (MIN_EXPR, itype, t, n);
6615 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6616 false, GSI_CONTINUE_LINKING);
6618 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6619 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6621 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6622 gsi = gsi_start_bb (seq_start_bb);
6624 tree startvar = fd->loop.v;
6625 tree endvar = NULL_TREE;
6627 if (gimple_omp_for_combined_p (fd->for_stmt))
6629 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6630 ? gimple_omp_parallel_clauses (inner_stmt)
6631 : gimple_omp_for_clauses (inner_stmt);
6632 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6633 gcc_assert (innerc);
6634 startvar = OMP_CLAUSE_DECL (innerc);
6635 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6636 OMP_CLAUSE__LOOPTEMP_);
6637 gcc_assert (innerc);
6638 endvar = OMP_CLAUSE_DECL (innerc);
6641 t = fold_convert (itype, s0);
6642 t = fold_build2 (MULT_EXPR, itype, t, step);
6643 if (POINTER_TYPE_P (type))
6644 t = fold_build_pointer_plus (n1, t);
6645 else
6646 t = fold_build2 (PLUS_EXPR, type, t, n1);
6647 t = fold_convert (TREE_TYPE (startvar), t);
6648 t = force_gimple_operand_gsi (&gsi, t,
6649 DECL_P (startvar)
6650 && TREE_ADDRESSABLE (startvar),
6651 NULL_TREE, false, GSI_CONTINUE_LINKING);
6652 assign_stmt = gimple_build_assign (startvar, t);
6653 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6655 t = fold_convert (itype, e0);
6656 t = fold_build2 (MULT_EXPR, itype, t, step);
6657 if (POINTER_TYPE_P (type))
6658 t = fold_build_pointer_plus (n1, t);
6659 else
6660 t = fold_build2 (PLUS_EXPR, type, t, n1);
6661 t = fold_convert (TREE_TYPE (startvar), t);
6662 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6663 false, GSI_CONTINUE_LINKING);
6664 if (endvar)
6666 assign_stmt = gimple_build_assign (endvar, e);
6667 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6668 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6669 assign_stmt = gimple_build_assign (fd->loop.v, e);
6670 else
6671 assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6672 NULL_TREE);
6673 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6675 if (fd->collapse > 1)
6676 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6678 if (!broken_loop)
6680 /* The code controlling the sequential loop goes in CONT_BB,
6681 replacing the GIMPLE_OMP_CONTINUE. */
6682 gsi = gsi_last_bb (cont_bb);
6683 gomp_continue *cont_stmt =
6684 as_a <gomp_continue *> (gsi_stmt (gsi));
6685 vmain = gimple_omp_continue_control_use (cont_stmt);
6686 vback = gimple_omp_continue_control_def (cont_stmt);
6688 if (!gimple_omp_for_combined_p (fd->for_stmt))
6690 if (POINTER_TYPE_P (type))
6691 t = fold_build_pointer_plus (vmain, step);
6692 else
6693 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6694 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
6695 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6696 true, GSI_SAME_STMT);
6697 assign_stmt = gimple_build_assign (vback, t);
6698 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6700 t = build2 (fd->loop.cond_code, boolean_type_node,
6701 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6702 ? t : vback, e);
6703 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6706 /* Remove GIMPLE_OMP_CONTINUE. */
6707 gsi_remove (&gsi, true);
6709 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6710 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6712 /* Trip update code goes into TRIP_UPDATE_BB. */
6713 gsi = gsi_start_bb (trip_update_bb);
6715 t = build_int_cst (itype, 1);
6716 t = build2 (PLUS_EXPR, itype, trip_main, t);
6717 assign_stmt = gimple_build_assign (trip_back, t);
6718 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6721 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6722 gsi = gsi_last_bb (exit_bb);
6723 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6725 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6726 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6728 gsi_remove (&gsi, true);
6730 /* Connect the new blocks. */
6731 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6732 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6734 if (!broken_loop)
6736 se = find_edge (cont_bb, body_bb);
6737 if (gimple_omp_for_combined_p (fd->for_stmt))
6739 remove_edge (se);
6740 se = NULL;
6742 else if (fd->collapse > 1)
6744 remove_edge (se);
6745 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6747 else
6748 se->flags = EDGE_TRUE_VALUE;
6749 find_edge (cont_bb, trip_update_bb)->flags
6750 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6752 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6755 if (gimple_in_ssa_p (cfun))
6757 gphi_iterator psi;
6758 gphi *phi;
6759 edge re, ene;
6760 edge_var_map *vm;
6761 size_t i;
6763 gcc_assert (fd->collapse == 1 && !broken_loop);
6765 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6766 remove arguments of the phi nodes in fin_bb. We need to create
6767 appropriate phi nodes in iter_part_bb instead. */
6768 se = single_pred_edge (fin_bb);
6769 re = single_succ_edge (trip_update_bb);
6770 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
6771 ene = single_succ_edge (entry_bb);
6773 psi = gsi_start_phis (fin_bb);
6774 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6775 gsi_next (&psi), ++i)
6777 gphi *nphi;
6778 source_location locus;
6780 phi = psi.phi ();
6781 t = gimple_phi_result (phi);
6782 gcc_assert (t == redirect_edge_var_map_result (vm));
6783 nphi = create_phi_node (t, iter_part_bb);
6785 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6786 locus = gimple_phi_arg_location_from_edge (phi, se);
6788 /* A special case -- fd->loop.v is not yet computed in
6789 iter_part_bb, we need to use vextra instead. */
6790 if (t == fd->loop.v)
6791 t = vextra;
6792 add_phi_arg (nphi, t, ene, locus);
6793 locus = redirect_edge_var_map_location (vm);
6794 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6796 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6797 redirect_edge_var_map_clear (re);
6798 while (1)
6800 psi = gsi_start_phis (fin_bb);
6801 if (gsi_end_p (psi))
6802 break;
6803 remove_phi_node (&psi, false);
6806 /* Make phi node for trip. */
6807 phi = create_phi_node (trip_main, iter_part_bb);
6808 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6809 UNKNOWN_LOCATION);
6810 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6811 UNKNOWN_LOCATION);
6814 if (!broken_loop)
6815 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6816 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6817 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6818 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6819 recompute_dominator (CDI_DOMINATORS, fin_bb));
6820 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6821 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6822 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6823 recompute_dominator (CDI_DOMINATORS, body_bb));
6825 if (!broken_loop)
6827 struct loop *trip_loop = alloc_loop ();
6828 trip_loop->header = iter_part_bb;
6829 trip_loop->latch = trip_update_bb;
6830 add_loop (trip_loop, iter_part_bb->loop_father);
6832 if (!gimple_omp_for_combined_p (fd->for_stmt))
6834 struct loop *loop = alloc_loop ();
6835 loop->header = body_bb;
6836 if (collapse_bb == NULL)
6837 loop->latch = cont_bb;
6838 add_loop (loop, trip_loop);
6843 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
6844 Given parameters:
6845 for (V = N1; V cond N2; V += STEP) BODY;
6847 where COND is "<" or ">" or "!=", we generate pseudocode
6849 for (ind_var = low; ind_var < high; ind_var++)
6851 V = n1 + (ind_var * STEP)
6853 <BODY>
6856 In the above pseudocode, low and high are function parameters of the
6857 child function. In the function below, we are inserting a temp.
6858 variable that will be making a call to two OMP functions that will not be
6859 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
6860 with _Cilk_for). These functions are replaced with low and high
6861 by the function that handles taskreg. */
6864 static void
6865 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
6867 bool broken_loop = region->cont == NULL;
6868 basic_block entry_bb = region->entry;
6869 basic_block cont_bb = region->cont;
6871 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6872 gcc_assert (broken_loop
6873 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6874 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6875 basic_block l1_bb, l2_bb;
6877 if (!broken_loop)
6879 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6880 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6881 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6882 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6884 else
6886 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6887 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6888 l2_bb = single_succ (l1_bb);
6890 basic_block exit_bb = region->exit;
6891 basic_block l2_dom_bb = NULL;
6893 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
6895 /* Below statements until the "tree high_val = ..." are pseudo statements
6896 used to pass information to be used by expand_omp_taskreg.
6897 low_val and high_val will be replaced by the __low and __high
6898 parameter from the child function.
6900 The call_exprs part is a place-holder, it is mainly used
6901 to distinctly identify to the top-level part that this is
6902 where we should put low and high (reasoning given in header
6903 comment). */
6905 tree child_fndecl
6906 = gimple_omp_parallel_child_fn (
6907 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
6908 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
6909 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
6911 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
6912 high_val = t;
6913 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
6914 low_val = t;
6916 gcc_assert (low_val && high_val);
6918 tree type = TREE_TYPE (low_val);
6919 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
6920 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6922 /* Not needed in SSA form right now. */
6923 gcc_assert (!gimple_in_ssa_p (cfun));
6924 if (l2_dom_bb == NULL)
6925 l2_dom_bb = l1_bb;
6927 tree n1 = low_val;
6928 tree n2 = high_val;
6930 gimple stmt = gimple_build_assign (ind_var, n1);
6932 /* Replace the GIMPLE_OMP_FOR statement. */
6933 gsi_replace (&gsi, stmt, true);
6935 if (!broken_loop)
6937 /* Code to control the increment goes in the CONT_BB. */
6938 gsi = gsi_last_bb (cont_bb);
6939 stmt = gsi_stmt (gsi);
6940 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6941 stmt = gimple_build_assign_with_ops (PLUS_EXPR, ind_var, ind_var,
6942 build_one_cst (type));
6944 /* Replace GIMPLE_OMP_CONTINUE. */
6945 gsi_replace (&gsi, stmt, true);
6948 /* Emit the condition in L1_BB. */
6949 gsi = gsi_after_labels (l1_bb);
6950 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
6951 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
6952 fd->loop.step);
6953 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
6954 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6955 fd->loop.n1, fold_convert (sizetype, t));
6956 else
6957 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6958 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
6959 t = fold_convert (TREE_TYPE (fd->loop.v), t);
6960 expand_omp_build_assign (&gsi, fd->loop.v, t);
6962 /* The condition is always '<' since the runtime will fill in the low
6963 and high values. */
6964 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
6965 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6967 /* Remove GIMPLE_OMP_RETURN. */
6968 gsi = gsi_last_bb (exit_bb);
6969 gsi_remove (&gsi, true);
6971 /* Connect the new blocks. */
6972 remove_edge (FALLTHRU_EDGE (entry_bb));
6974 edge e, ne;
6975 if (!broken_loop)
6977 remove_edge (BRANCH_EDGE (entry_bb));
6978 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6980 e = BRANCH_EDGE (l1_bb);
6981 ne = FALLTHRU_EDGE (l1_bb);
6982 e->flags = EDGE_TRUE_VALUE;
6984 else
6986 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6988 ne = single_succ_edge (l1_bb);
6989 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6992 ne->flags = EDGE_FALSE_VALUE;
6993 e->probability = REG_BR_PROB_BASE * 7 / 8;
6994 ne->probability = REG_BR_PROB_BASE / 8;
6996 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6997 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6998 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7000 if (!broken_loop)
7002 struct loop *loop = alloc_loop ();
7003 loop->header = l1_bb;
7004 loop->latch = cont_bb;
7005 add_loop (loop, l1_bb->loop_father);
7006 loop->safelen = INT_MAX;
7009 /* Pick the correct library function based on the precision of the
7010 induction variable type. */
7011 tree lib_fun = NULL_TREE;
7012 if (TYPE_PRECISION (type) == 32)
7013 lib_fun = cilk_for_32_fndecl;
7014 else if (TYPE_PRECISION (type) == 64)
7015 lib_fun = cilk_for_64_fndecl;
7016 else
7017 gcc_unreachable ();
7019 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7021 /* WS_ARGS contains the library function flavor to call:
7022 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7023 user-defined grain value. If the user does not define one, then zero
7024 is passed in by the parser. */
7025 vec_alloc (region->ws_args, 2);
7026 region->ws_args->quick_push (lib_fun);
7027 region->ws_args->quick_push (fd->chunk_size);
7030 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7031 loop. Given parameters:
7033 for (V = N1; V cond N2; V += STEP) BODY;
7035 where COND is "<" or ">", we generate pseudocode
7037 V = N1;
7038 goto L1;
7040 BODY;
7041 V += STEP;
7043 if (V cond N2) goto L0; else goto L2;
7046 For collapsed loops, given parameters:
7047 collapse(3)
7048 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7049 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7050 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7051 BODY;
7053 we generate pseudocode
7055 if (cond3 is <)
7056 adj = STEP3 - 1;
7057 else
7058 adj = STEP3 + 1;
7059 count3 = (adj + N32 - N31) / STEP3;
7060 if (cond2 is <)
7061 adj = STEP2 - 1;
7062 else
7063 adj = STEP2 + 1;
7064 count2 = (adj + N22 - N21) / STEP2;
7065 if (cond1 is <)
7066 adj = STEP1 - 1;
7067 else
7068 adj = STEP1 + 1;
7069 count1 = (adj + N12 - N11) / STEP1;
7070 count = count1 * count2 * count3;
7071 V = 0;
7072 V1 = N11;
7073 V2 = N21;
7074 V3 = N31;
7075 goto L1;
7077 BODY;
7078 V += 1;
7079 V3 += STEP3;
7080 V2 += (V3 cond3 N32) ? 0 : STEP2;
7081 V3 = (V3 cond3 N32) ? V3 : N31;
7082 V1 += (V2 cond2 N22) ? 0 : STEP1;
7083 V2 = (V2 cond2 N22) ? V2 : N21;
7085 if (V < count) goto L0; else goto L2;
7090 static void
7091 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7093 tree type, t;
7094 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7095 gimple_stmt_iterator gsi;
7096 gimple stmt;
7097 gcond *cond_stmt;
7098 bool broken_loop = region->cont == NULL;
7099 edge e, ne;
7100 tree *counts = NULL;
7101 int i;
7102 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7103 OMP_CLAUSE_SAFELEN);
7104 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7105 OMP_CLAUSE__SIMDUID_);
7106 tree n1, n2;
7108 type = TREE_TYPE (fd->loop.v);
7109 entry_bb = region->entry;
7110 cont_bb = region->cont;
7111 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7112 gcc_assert (broken_loop
7113 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7114 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7115 if (!broken_loop)
7117 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7118 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7119 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7120 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7122 else
7124 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7125 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7126 l2_bb = single_succ (l1_bb);
7128 exit_bb = region->exit;
7129 l2_dom_bb = NULL;
7131 gsi = gsi_last_bb (entry_bb);
7133 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7134 /* Not needed in SSA form right now. */
7135 gcc_assert (!gimple_in_ssa_p (cfun));
7136 if (fd->collapse > 1)
7138 int first_zero_iter = -1;
7139 basic_block zero_iter_bb = l2_bb;
7141 counts = XALLOCAVEC (tree, fd->collapse);
7142 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7143 zero_iter_bb, first_zero_iter,
7144 l2_dom_bb);
7146 if (l2_dom_bb == NULL)
7147 l2_dom_bb = l1_bb;
7149 n1 = fd->loop.n1;
7150 n2 = fd->loop.n2;
7151 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7153 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7154 OMP_CLAUSE__LOOPTEMP_);
7155 gcc_assert (innerc);
7156 n1 = OMP_CLAUSE_DECL (innerc);
7157 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7158 OMP_CLAUSE__LOOPTEMP_);
7159 gcc_assert (innerc);
7160 n2 = OMP_CLAUSE_DECL (innerc);
7161 expand_omp_build_assign (&gsi, fd->loop.v,
7162 fold_convert (type, n1));
7163 if (fd->collapse > 1)
7165 gsi_prev (&gsi);
7166 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7167 gsi_next (&gsi);
7170 else
7172 expand_omp_build_assign (&gsi, fd->loop.v,
7173 fold_convert (type, fd->loop.n1));
7174 if (fd->collapse > 1)
7175 for (i = 0; i < fd->collapse; i++)
7177 tree itype = TREE_TYPE (fd->loops[i].v);
7178 if (POINTER_TYPE_P (itype))
7179 itype = signed_type_for (itype);
7180 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7181 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7185 /* Remove the GIMPLE_OMP_FOR statement. */
7186 gsi_remove (&gsi, true);
7188 if (!broken_loop)
7190 /* Code to control the increment goes in the CONT_BB. */
7191 gsi = gsi_last_bb (cont_bb);
7192 stmt = gsi_stmt (gsi);
7193 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7195 if (POINTER_TYPE_P (type))
7196 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7197 else
7198 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7199 expand_omp_build_assign (&gsi, fd->loop.v, t);
7201 if (fd->collapse > 1)
7203 i = fd->collapse - 1;
7204 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7206 t = fold_convert (sizetype, fd->loops[i].step);
7207 t = fold_build_pointer_plus (fd->loops[i].v, t);
7209 else
7211 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7212 fd->loops[i].step);
7213 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7214 fd->loops[i].v, t);
7216 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7218 for (i = fd->collapse - 1; i > 0; i--)
7220 tree itype = TREE_TYPE (fd->loops[i].v);
7221 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7222 if (POINTER_TYPE_P (itype2))
7223 itype2 = signed_type_for (itype2);
7224 t = build3 (COND_EXPR, itype2,
7225 build2 (fd->loops[i].cond_code, boolean_type_node,
7226 fd->loops[i].v,
7227 fold_convert (itype, fd->loops[i].n2)),
7228 build_int_cst (itype2, 0),
7229 fold_convert (itype2, fd->loops[i - 1].step));
7230 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7231 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7232 else
7233 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7234 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7236 t = build3 (COND_EXPR, itype,
7237 build2 (fd->loops[i].cond_code, boolean_type_node,
7238 fd->loops[i].v,
7239 fold_convert (itype, fd->loops[i].n2)),
7240 fd->loops[i].v,
7241 fold_convert (itype, fd->loops[i].n1));
7242 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7246 /* Remove GIMPLE_OMP_CONTINUE. */
7247 gsi_remove (&gsi, true);
7250 /* Emit the condition in L1_BB. */
7251 gsi = gsi_start_bb (l1_bb);
7253 t = fold_convert (type, n2);
7254 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7255 false, GSI_CONTINUE_LINKING);
7256 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7257 cond_stmt = gimple_build_cond_empty (t);
7258 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7259 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7260 NULL, NULL)
7261 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7262 NULL, NULL))
7264 gsi = gsi_for_stmt (cond_stmt);
7265 gimple_regimplify_operands (cond_stmt, &gsi);
7268 /* Remove GIMPLE_OMP_RETURN. */
7269 gsi = gsi_last_bb (exit_bb);
7270 gsi_remove (&gsi, true);
7272 /* Connect the new blocks. */
7273 remove_edge (FALLTHRU_EDGE (entry_bb));
7275 if (!broken_loop)
7277 remove_edge (BRANCH_EDGE (entry_bb));
7278 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7280 e = BRANCH_EDGE (l1_bb);
7281 ne = FALLTHRU_EDGE (l1_bb);
7282 e->flags = EDGE_TRUE_VALUE;
7284 else
7286 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7288 ne = single_succ_edge (l1_bb);
7289 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7292 ne->flags = EDGE_FALSE_VALUE;
7293 e->probability = REG_BR_PROB_BASE * 7 / 8;
7294 ne->probability = REG_BR_PROB_BASE / 8;
7296 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7297 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7298 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7300 if (!broken_loop)
7302 struct loop *loop = alloc_loop ();
7303 loop->header = l1_bb;
7304 loop->latch = cont_bb;
7305 add_loop (loop, l1_bb->loop_father);
7306 if (safelen == NULL_TREE)
7307 loop->safelen = INT_MAX;
7308 else
7310 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7311 if (TREE_CODE (safelen) != INTEGER_CST)
7312 loop->safelen = 0;
7313 else if (!tree_fits_uhwi_p (safelen)
7314 || tree_to_uhwi (safelen) > INT_MAX)
7315 loop->safelen = INT_MAX;
7316 else
7317 loop->safelen = tree_to_uhwi (safelen);
7318 if (loop->safelen == 1)
7319 loop->safelen = 0;
7321 if (simduid)
7323 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7324 cfun->has_simduid_loops = true;
7326 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7327 the loop. */
7328 if ((flag_tree_loop_vectorize
7329 || (!global_options_set.x_flag_tree_loop_vectorize
7330 && !global_options_set.x_flag_tree_vectorize))
7331 && flag_tree_loop_optimize
7332 && loop->safelen > 1)
7334 loop->force_vectorize = true;
7335 cfun->has_force_vectorize_loops = true;
7341 /* Expand the OpenMP loop defined by REGION. */
7343 static void
7344 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7346 struct omp_for_data fd;
7347 struct omp_for_data_loop *loops;
7349 loops
7350 = (struct omp_for_data_loop *)
7351 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7352 * sizeof (struct omp_for_data_loop));
7353 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7354 &fd, loops);
7355 region->sched_kind = fd.sched_kind;
7357 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7358 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7359 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7360 if (region->cont)
7362 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7363 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7364 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7366 else
7367 /* If there isn't a continue then this is a degerate case where
7368 the introduction of abnormal edges during lowering will prevent
7369 original loops from being detected. Fix that up. */
7370 loops_state_set (LOOPS_NEED_FIXUP);
7372 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7373 expand_omp_simd (region, &fd);
7374 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7375 expand_cilk_for (region, &fd);
7376 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7377 && !fd.have_ordered)
7379 if (fd.chunk_size == NULL)
7380 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7381 else
7382 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7384 else
7386 int fn_index, start_ix, next_ix;
7388 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7389 == GF_OMP_FOR_KIND_FOR);
7390 if (fd.chunk_size == NULL
7391 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7392 fd.chunk_size = integer_zero_node;
7393 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7394 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7395 ? 3 : fd.sched_kind;
7396 fn_index += fd.have_ordered * 4;
7397 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7398 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7399 if (fd.iter_type == long_long_unsigned_type_node)
7401 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7402 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7403 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7404 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7406 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7407 (enum built_in_function) next_ix, inner_stmt);
7410 if (gimple_in_ssa_p (cfun))
7411 update_ssa (TODO_update_ssa_only_virtuals);
7415 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7417 v = GOMP_sections_start (n);
7419 switch (v)
7421 case 0:
7422 goto L2;
7423 case 1:
7424 section 1;
7425 goto L1;
7426 case 2:
7428 case n:
7430 default:
7431 abort ();
7434 v = GOMP_sections_next ();
7435 goto L0;
7437 reduction;
7439 If this is a combined parallel sections, replace the call to
7440 GOMP_sections_start with call to GOMP_sections_next. */
7442 static void
7443 expand_omp_sections (struct omp_region *region)
7445 tree t, u, vin = NULL, vmain, vnext, l2;
7446 unsigned len;
7447 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7448 gimple_stmt_iterator si, switch_si;
7449 gomp_sections *sections_stmt;
7450 gimple stmt;
7451 gomp_continue *cont;
7452 edge_iterator ei;
7453 edge e;
7454 struct omp_region *inner;
7455 unsigned i, casei;
7456 bool exit_reachable = region->cont != NULL;
7458 gcc_assert (region->exit != NULL);
7459 entry_bb = region->entry;
7460 l0_bb = single_succ (entry_bb);
7461 l1_bb = region->cont;
7462 l2_bb = region->exit;
7463 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7464 l2 = gimple_block_label (l2_bb);
7465 else
7467 /* This can happen if there are reductions. */
7468 len = EDGE_COUNT (l0_bb->succs);
7469 gcc_assert (len > 0);
7470 e = EDGE_SUCC (l0_bb, len - 1);
7471 si = gsi_last_bb (e->dest);
7472 l2 = NULL_TREE;
7473 if (gsi_end_p (si)
7474 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7475 l2 = gimple_block_label (e->dest);
7476 else
7477 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7479 si = gsi_last_bb (e->dest);
7480 if (gsi_end_p (si)
7481 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7483 l2 = gimple_block_label (e->dest);
7484 break;
7488 if (exit_reachable)
7489 default_bb = create_empty_bb (l1_bb->prev_bb);
7490 else
7491 default_bb = create_empty_bb (l0_bb);
7493 /* We will build a switch() with enough cases for all the
7494 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7495 and a default case to abort if something goes wrong. */
7496 len = EDGE_COUNT (l0_bb->succs);
7498 /* Use vec::quick_push on label_vec throughout, since we know the size
7499 in advance. */
7500 auto_vec<tree> label_vec (len);
7502 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7503 GIMPLE_OMP_SECTIONS statement. */
7504 si = gsi_last_bb (entry_bb);
7505 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
7506 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7507 vin = gimple_omp_sections_control (sections_stmt);
7508 if (!is_combined_parallel (region))
7510 /* If we are not inside a combined parallel+sections region,
7511 call GOMP_sections_start. */
7512 t = build_int_cst (unsigned_type_node, len - 1);
7513 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7514 stmt = gimple_build_call (u, 1, t);
7516 else
7518 /* Otherwise, call GOMP_sections_next. */
7519 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7520 stmt = gimple_build_call (u, 0);
7522 gimple_call_set_lhs (stmt, vin);
7523 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7524 gsi_remove (&si, true);
7526 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7527 L0_BB. */
7528 switch_si = gsi_last_bb (l0_bb);
7529 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7530 if (exit_reachable)
7532 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
7533 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7534 vmain = gimple_omp_continue_control_use (cont);
7535 vnext = gimple_omp_continue_control_def (cont);
7537 else
7539 vmain = vin;
7540 vnext = NULL_TREE;
7543 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7544 label_vec.quick_push (t);
7545 i = 1;
7547 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7548 for (inner = region->inner, casei = 1;
7549 inner;
7550 inner = inner->next, i++, casei++)
7552 basic_block s_entry_bb, s_exit_bb;
7554 /* Skip optional reduction region. */
7555 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7557 --i;
7558 --casei;
7559 continue;
7562 s_entry_bb = inner->entry;
7563 s_exit_bb = inner->exit;
7565 t = gimple_block_label (s_entry_bb);
7566 u = build_int_cst (unsigned_type_node, casei);
7567 u = build_case_label (u, NULL, t);
7568 label_vec.quick_push (u);
7570 si = gsi_last_bb (s_entry_bb);
7571 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7572 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7573 gsi_remove (&si, true);
7574 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7576 if (s_exit_bb == NULL)
7577 continue;
7579 si = gsi_last_bb (s_exit_bb);
7580 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7581 gsi_remove (&si, true);
7583 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7586 /* Error handling code goes in DEFAULT_BB. */
7587 t = gimple_block_label (default_bb);
7588 u = build_case_label (NULL, NULL, t);
7589 make_edge (l0_bb, default_bb, 0);
7590 add_bb_to_loop (default_bb, current_loops->tree_root);
7592 stmt = gimple_build_switch (vmain, u, label_vec);
7593 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7594 gsi_remove (&switch_si, true);
7596 si = gsi_start_bb (default_bb);
7597 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7598 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7600 if (exit_reachable)
7602 tree bfn_decl;
7604 /* Code to get the next section goes in L1_BB. */
7605 si = gsi_last_bb (l1_bb);
7606 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7608 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7609 stmt = gimple_build_call (bfn_decl, 0);
7610 gimple_call_set_lhs (stmt, vnext);
7611 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7612 gsi_remove (&si, true);
7614 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7617 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7618 si = gsi_last_bb (l2_bb);
7619 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7620 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7621 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7622 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7623 else
7624 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7625 stmt = gimple_build_call (t, 0);
7626 if (gimple_omp_return_lhs (gsi_stmt (si)))
7627 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7628 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7629 gsi_remove (&si, true);
7631 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7635 /* Expand code for an OpenMP single directive. We've already expanded
7636 much of the code, here we simply place the GOMP_barrier call. */
7638 static void
7639 expand_omp_single (struct omp_region *region)
7641 basic_block entry_bb, exit_bb;
7642 gimple_stmt_iterator si;
7644 entry_bb = region->entry;
7645 exit_bb = region->exit;
7647 si = gsi_last_bb (entry_bb);
7648 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7649 gsi_remove (&si, true);
7650 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7652 si = gsi_last_bb (exit_bb);
7653 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7655 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7656 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7658 gsi_remove (&si, true);
7659 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7663 /* Generic expansion for OpenMP synchronization directives: master,
7664 ordered and critical. All we need to do here is remove the entry
7665 and exit markers for REGION. */
7667 static void
7668 expand_omp_synch (struct omp_region *region)
7670 basic_block entry_bb, exit_bb;
7671 gimple_stmt_iterator si;
7673 entry_bb = region->entry;
7674 exit_bb = region->exit;
7676 si = gsi_last_bb (entry_bb);
7677 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7678 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7679 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7680 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7681 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7682 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7683 gsi_remove (&si, true);
7684 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7686 if (exit_bb)
7688 si = gsi_last_bb (exit_bb);
7689 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7690 gsi_remove (&si, true);
7691 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7695 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7696 operation as a normal volatile load. */
7698 static bool
7699 expand_omp_atomic_load (basic_block load_bb, tree addr,
7700 tree loaded_val, int index)
7702 enum built_in_function tmpbase;
7703 gimple_stmt_iterator gsi;
7704 basic_block store_bb;
7705 location_t loc;
7706 gimple stmt;
7707 tree decl, call, type, itype;
7709 gsi = gsi_last_bb (load_bb);
7710 stmt = gsi_stmt (gsi);
7711 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7712 loc = gimple_location (stmt);
7714 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7715 is smaller than word size, then expand_atomic_load assumes that the load
7716 is atomic. We could avoid the builtin entirely in this case. */
7718 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7719 decl = builtin_decl_explicit (tmpbase);
7720 if (decl == NULL_TREE)
7721 return false;
7723 type = TREE_TYPE (loaded_val);
7724 itype = TREE_TYPE (TREE_TYPE (decl));
7726 call = build_call_expr_loc (loc, decl, 2, addr,
7727 build_int_cst (NULL,
7728 gimple_omp_atomic_seq_cst_p (stmt)
7729 ? MEMMODEL_SEQ_CST
7730 : MEMMODEL_RELAXED));
7731 if (!useless_type_conversion_p (type, itype))
7732 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7733 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7735 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7736 gsi_remove (&gsi, true);
7738 store_bb = single_succ (load_bb);
7739 gsi = gsi_last_bb (store_bb);
7740 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7741 gsi_remove (&gsi, true);
7743 if (gimple_in_ssa_p (cfun))
7744 update_ssa (TODO_update_ssa_no_phi);
7746 return true;
7749 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7750 operation as a normal volatile store. */
7752 static bool
7753 expand_omp_atomic_store (basic_block load_bb, tree addr,
7754 tree loaded_val, tree stored_val, int index)
7756 enum built_in_function tmpbase;
7757 gimple_stmt_iterator gsi;
7758 basic_block store_bb = single_succ (load_bb);
7759 location_t loc;
7760 gimple stmt;
7761 tree decl, call, type, itype;
7762 machine_mode imode;
7763 bool exchange;
7765 gsi = gsi_last_bb (load_bb);
7766 stmt = gsi_stmt (gsi);
7767 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7769 /* If the load value is needed, then this isn't a store but an exchange. */
7770 exchange = gimple_omp_atomic_need_value_p (stmt);
7772 gsi = gsi_last_bb (store_bb);
7773 stmt = gsi_stmt (gsi);
7774 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7775 loc = gimple_location (stmt);
7777 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7778 is smaller than word size, then expand_atomic_store assumes that the store
7779 is atomic. We could avoid the builtin entirely in this case. */
7781 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7782 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7783 decl = builtin_decl_explicit (tmpbase);
7784 if (decl == NULL_TREE)
7785 return false;
7787 type = TREE_TYPE (stored_val);
7789 /* Dig out the type of the function's second argument. */
7790 itype = TREE_TYPE (decl);
7791 itype = TYPE_ARG_TYPES (itype);
7792 itype = TREE_CHAIN (itype);
7793 itype = TREE_VALUE (itype);
7794 imode = TYPE_MODE (itype);
7796 if (exchange && !can_atomic_exchange_p (imode, true))
7797 return false;
7799 if (!useless_type_conversion_p (itype, type))
7800 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7801 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7802 build_int_cst (NULL,
7803 gimple_omp_atomic_seq_cst_p (stmt)
7804 ? MEMMODEL_SEQ_CST
7805 : MEMMODEL_RELAXED));
7806 if (exchange)
7808 if (!useless_type_conversion_p (type, itype))
7809 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7810 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7813 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7814 gsi_remove (&gsi, true);
7816 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7817 gsi = gsi_last_bb (load_bb);
7818 gsi_remove (&gsi, true);
7820 if (gimple_in_ssa_p (cfun))
7821 update_ssa (TODO_update_ssa_no_phi);
7823 return true;
7826 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7827 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7828 size of the data type, and thus usable to find the index of the builtin
7829 decl. Returns false if the expression is not of the proper form. */
7831 static bool
7832 expand_omp_atomic_fetch_op (basic_block load_bb,
7833 tree addr, tree loaded_val,
7834 tree stored_val, int index)
7836 enum built_in_function oldbase, newbase, tmpbase;
7837 tree decl, itype, call;
7838 tree lhs, rhs;
7839 basic_block store_bb = single_succ (load_bb);
7840 gimple_stmt_iterator gsi;
7841 gimple stmt;
7842 location_t loc;
7843 enum tree_code code;
7844 bool need_old, need_new;
7845 machine_mode imode;
7846 bool seq_cst;
7848 /* We expect to find the following sequences:
7850 load_bb:
7851 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7853 store_bb:
7854 val = tmp OP something; (or: something OP tmp)
7855 GIMPLE_OMP_STORE (val)
7857 ???FIXME: Allow a more flexible sequence.
7858 Perhaps use data flow to pick the statements.
7862 gsi = gsi_after_labels (store_bb);
7863 stmt = gsi_stmt (gsi);
7864 loc = gimple_location (stmt);
7865 if (!is_gimple_assign (stmt))
7866 return false;
7867 gsi_next (&gsi);
7868 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7869 return false;
7870 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7871 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7872 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7873 gcc_checking_assert (!need_old || !need_new);
7875 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7876 return false;
7878 /* Check for one of the supported fetch-op operations. */
7879 code = gimple_assign_rhs_code (stmt);
7880 switch (code)
7882 case PLUS_EXPR:
7883 case POINTER_PLUS_EXPR:
7884 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7885 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7886 break;
7887 case MINUS_EXPR:
7888 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7889 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7890 break;
7891 case BIT_AND_EXPR:
7892 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7893 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7894 break;
7895 case BIT_IOR_EXPR:
7896 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7897 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7898 break;
7899 case BIT_XOR_EXPR:
7900 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7901 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7902 break;
7903 default:
7904 return false;
7907 /* Make sure the expression is of the proper form. */
7908 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7909 rhs = gimple_assign_rhs2 (stmt);
7910 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7911 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7912 rhs = gimple_assign_rhs1 (stmt);
7913 else
7914 return false;
7916 tmpbase = ((enum built_in_function)
7917 ((need_new ? newbase : oldbase) + index + 1));
7918 decl = builtin_decl_explicit (tmpbase);
7919 if (decl == NULL_TREE)
7920 return false;
7921 itype = TREE_TYPE (TREE_TYPE (decl));
7922 imode = TYPE_MODE (itype);
7924 /* We could test all of the various optabs involved, but the fact of the
7925 matter is that (with the exception of i486 vs i586 and xadd) all targets
7926 that support any atomic operaton optab also implements compare-and-swap.
7927 Let optabs.c take care of expanding any compare-and-swap loop. */
7928 if (!can_compare_and_swap_p (imode, true))
7929 return false;
7931 gsi = gsi_last_bb (load_bb);
7932 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7934 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7935 It only requires that the operation happen atomically. Thus we can
7936 use the RELAXED memory model. */
7937 call = build_call_expr_loc (loc, decl, 3, addr,
7938 fold_convert_loc (loc, itype, rhs),
7939 build_int_cst (NULL,
7940 seq_cst ? MEMMODEL_SEQ_CST
7941 : MEMMODEL_RELAXED));
7943 if (need_old || need_new)
7945 lhs = need_old ? loaded_val : stored_val;
7946 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7947 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7949 else
7950 call = fold_convert_loc (loc, void_type_node, call);
7951 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7952 gsi_remove (&gsi, true);
7954 gsi = gsi_last_bb (store_bb);
7955 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7956 gsi_remove (&gsi, true);
7957 gsi = gsi_last_bb (store_bb);
7958 gsi_remove (&gsi, true);
7960 if (gimple_in_ssa_p (cfun))
7961 update_ssa (TODO_update_ssa_no_phi);
7963 return true;
7966 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7968 oldval = *addr;
7969 repeat:
7970 newval = rhs; // with oldval replacing *addr in rhs
7971 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7972 if (oldval != newval)
7973 goto repeat;
7975 INDEX is log2 of the size of the data type, and thus usable to find the
7976 index of the builtin decl. */
7978 static bool
7979 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7980 tree addr, tree loaded_val, tree stored_val,
7981 int index)
7983 tree loadedi, storedi, initial, new_storedi, old_vali;
7984 tree type, itype, cmpxchg, iaddr;
7985 gimple_stmt_iterator si;
7986 basic_block loop_header = single_succ (load_bb);
7987 gimple phi, stmt;
7988 edge e;
7989 enum built_in_function fncode;
7991 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7992 order to use the RELAXED memory model effectively. */
7993 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7994 + index + 1);
7995 cmpxchg = builtin_decl_explicit (fncode);
7996 if (cmpxchg == NULL_TREE)
7997 return false;
7998 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7999 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8001 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8002 return false;
8004 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8005 si = gsi_last_bb (load_bb);
8006 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8008 /* For floating-point values, we'll need to view-convert them to integers
8009 so that we can perform the atomic compare and swap. Simplify the
8010 following code by always setting up the "i"ntegral variables. */
8011 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8013 tree iaddr_val;
8015 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8016 true), NULL);
8017 iaddr_val
8018 = force_gimple_operand_gsi (&si,
8019 fold_convert (TREE_TYPE (iaddr), addr),
8020 false, NULL_TREE, true, GSI_SAME_STMT);
8021 stmt = gimple_build_assign (iaddr, iaddr_val);
8022 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8023 loadedi = create_tmp_var (itype, NULL);
8024 if (gimple_in_ssa_p (cfun))
8025 loadedi = make_ssa_name (loadedi, NULL);
8027 else
8029 iaddr = addr;
8030 loadedi = loaded_val;
8033 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8034 tree loaddecl = builtin_decl_explicit (fncode);
8035 if (loaddecl)
8036 initial
8037 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8038 build_call_expr (loaddecl, 2, iaddr,
8039 build_int_cst (NULL_TREE,
8040 MEMMODEL_RELAXED)));
8041 else
8042 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8043 build_int_cst (TREE_TYPE (iaddr), 0));
8045 initial
8046 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8047 GSI_SAME_STMT);
8049 /* Move the value to the LOADEDI temporary. */
8050 if (gimple_in_ssa_p (cfun))
8052 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8053 phi = create_phi_node (loadedi, loop_header);
8054 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8055 initial);
8057 else
8058 gsi_insert_before (&si,
8059 gimple_build_assign (loadedi, initial),
8060 GSI_SAME_STMT);
8061 if (loadedi != loaded_val)
8063 gimple_stmt_iterator gsi2;
8064 tree x;
8066 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8067 gsi2 = gsi_start_bb (loop_header);
8068 if (gimple_in_ssa_p (cfun))
8070 gassign *stmt;
8071 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8072 true, GSI_SAME_STMT);
8073 stmt = gimple_build_assign (loaded_val, x);
8074 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8076 else
8078 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8079 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8080 true, GSI_SAME_STMT);
8083 gsi_remove (&si, true);
8085 si = gsi_last_bb (store_bb);
8086 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8088 if (iaddr == addr)
8089 storedi = stored_val;
8090 else
8091 storedi =
8092 force_gimple_operand_gsi (&si,
8093 build1 (VIEW_CONVERT_EXPR, itype,
8094 stored_val), true, NULL_TREE, true,
8095 GSI_SAME_STMT);
8097 /* Build the compare&swap statement. */
8098 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8099 new_storedi = force_gimple_operand_gsi (&si,
8100 fold_convert (TREE_TYPE (loadedi),
8101 new_storedi),
8102 true, NULL_TREE,
8103 true, GSI_SAME_STMT);
8105 if (gimple_in_ssa_p (cfun))
8106 old_vali = loadedi;
8107 else
8109 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
8110 stmt = gimple_build_assign (old_vali, loadedi);
8111 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8113 stmt = gimple_build_assign (loadedi, new_storedi);
8114 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8117 /* Note that we always perform the comparison as an integer, even for
8118 floating point. This allows the atomic operation to properly
8119 succeed even with NaNs and -0.0. */
8120 stmt = gimple_build_cond_empty
8121 (build2 (NE_EXPR, boolean_type_node,
8122 new_storedi, old_vali));
8123 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8125 /* Update cfg. */
8126 e = single_succ_edge (store_bb);
8127 e->flags &= ~EDGE_FALLTHRU;
8128 e->flags |= EDGE_FALSE_VALUE;
8130 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8132 /* Copy the new value to loadedi (we already did that before the condition
8133 if we are not in SSA). */
8134 if (gimple_in_ssa_p (cfun))
8136 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8137 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8140 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8141 gsi_remove (&si, true);
8143 struct loop *loop = alloc_loop ();
8144 loop->header = loop_header;
8145 loop->latch = store_bb;
8146 add_loop (loop, loop_header->loop_father);
8148 if (gimple_in_ssa_p (cfun))
8149 update_ssa (TODO_update_ssa_no_phi);
8151 return true;
8154 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8156 GOMP_atomic_start ();
8157 *addr = rhs;
8158 GOMP_atomic_end ();
8160 The result is not globally atomic, but works so long as all parallel
8161 references are within #pragma omp atomic directives. According to
8162 responses received from omp@openmp.org, appears to be within spec.
8163 Which makes sense, since that's how several other compilers handle
8164 this situation as well.
8165 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8166 expanding. STORED_VAL is the operand of the matching
8167 GIMPLE_OMP_ATOMIC_STORE.
8169 We replace
8170 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8171 loaded_val = *addr;
8173 and replace
8174 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8175 *addr = stored_val;
8178 static bool
8179 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8180 tree addr, tree loaded_val, tree stored_val)
8182 gimple_stmt_iterator si;
8183 gassign *stmt;
8184 tree t;
8186 si = gsi_last_bb (load_bb);
8187 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8189 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8190 t = build_call_expr (t, 0);
8191 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8193 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8194 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8195 gsi_remove (&si, true);
8197 si = gsi_last_bb (store_bb);
8198 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8200 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8201 stored_val);
8202 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8204 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8205 t = build_call_expr (t, 0);
8206 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8207 gsi_remove (&si, true);
8209 if (gimple_in_ssa_p (cfun))
8210 update_ssa (TODO_update_ssa_no_phi);
8211 return true;
8214 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8215 using expand_omp_atomic_fetch_op. If it failed, we try to
8216 call expand_omp_atomic_pipeline, and if it fails too, the
8217 ultimate fallback is wrapping the operation in a mutex
8218 (expand_omp_atomic_mutex). REGION is the atomic region built
8219 by build_omp_regions_1(). */
8221 static void
8222 expand_omp_atomic (struct omp_region *region)
8224 basic_block load_bb = region->entry, store_bb = region->exit;
8225 gomp_atomic_load *load =
8226 as_a <gomp_atomic_load *> (last_stmt (load_bb));
8227 gomp_atomic_store *store =
8228 as_a <gomp_atomic_store *> (last_stmt (store_bb));
8229 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8230 tree addr = gimple_omp_atomic_load_rhs (load);
8231 tree stored_val = gimple_omp_atomic_store_val (store);
8232 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8233 HOST_WIDE_INT index;
8235 /* Make sure the type is one of the supported sizes. */
8236 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8237 index = exact_log2 (index);
8238 if (index >= 0 && index <= 4)
8240 unsigned int align = TYPE_ALIGN_UNIT (type);
8242 /* __sync builtins require strict data alignment. */
8243 if (exact_log2 (align) >= index)
8245 /* Atomic load. */
8246 if (loaded_val == stored_val
8247 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8248 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8249 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8250 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8251 return;
8253 /* Atomic store. */
8254 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8255 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8256 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8257 && store_bb == single_succ (load_bb)
8258 && first_stmt (store_bb) == store
8259 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8260 stored_val, index))
8261 return;
8263 /* When possible, use specialized atomic update functions. */
8264 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8265 && store_bb == single_succ (load_bb)
8266 && expand_omp_atomic_fetch_op (load_bb, addr,
8267 loaded_val, stored_val, index))
8268 return;
8270 /* If we don't have specialized __sync builtins, try and implement
8271 as a compare and swap loop. */
8272 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8273 loaded_val, stored_val, index))
8274 return;
8278 /* The ultimate fallback is wrapping the operation in a mutex. */
8279 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8283 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
8285 static void
8286 expand_omp_target (struct omp_region *region)
8288 basic_block entry_bb, exit_bb, new_bb;
8289 struct function *child_cfun = NULL;
8290 tree child_fn = NULL_TREE, block, t;
8291 gimple_stmt_iterator gsi;
8292 gomp_target *entry_stmt;
8293 gimple stmt;
8294 edge e;
8296 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8297 new_bb = region->entry;
8298 int kind = gimple_omp_target_kind (entry_stmt);
8299 if (kind == GF_OMP_TARGET_KIND_REGION)
8301 child_fn = gimple_omp_target_child_fn (entry_stmt);
8302 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8305 entry_bb = region->entry;
8306 exit_bb = region->exit;
8308 if (kind == GF_OMP_TARGET_KIND_REGION)
8310 unsigned srcidx, dstidx, num;
8311 struct cgraph_node *node;
8313 /* If the target region needs data sent from the parent
8314 function, then the very first statement (except possible
8315 tree profile counter updates) of the parallel body
8316 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8317 &.OMP_DATA_O is passed as an argument to the child function,
8318 we need to replace it with the argument as seen by the child
8319 function.
8321 In most cases, this will end up being the identity assignment
8322 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8323 a function call that has been inlined, the original PARM_DECL
8324 .OMP_DATA_I may have been converted into a different local
8325 variable. In which case, we need to keep the assignment. */
8326 if (gimple_omp_target_data_arg (entry_stmt))
8328 basic_block entry_succ_bb = single_succ (entry_bb);
8329 gimple_stmt_iterator gsi;
8330 tree arg;
8331 gimple tgtcopy_stmt = NULL;
8332 tree sender
8333 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
8335 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8337 gcc_assert (!gsi_end_p (gsi));
8338 stmt = gsi_stmt (gsi);
8339 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8340 continue;
8342 if (gimple_num_ops (stmt) == 2)
8344 tree arg = gimple_assign_rhs1 (stmt);
8346 /* We're ignoring the subcode because we're
8347 effectively doing a STRIP_NOPS. */
8349 if (TREE_CODE (arg) == ADDR_EXPR
8350 && TREE_OPERAND (arg, 0) == sender)
8352 tgtcopy_stmt = stmt;
8353 break;
8358 gcc_assert (tgtcopy_stmt != NULL);
8359 arg = DECL_ARGUMENTS (child_fn);
8361 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8362 gsi_remove (&gsi, true);
8365 /* Declare local variables needed in CHILD_CFUN. */
8366 block = DECL_INITIAL (child_fn);
8367 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8368 /* The gimplifier could record temporaries in target block
8369 rather than in containing function's local_decls chain,
8370 which would mean cgraph missed finalizing them. Do it now. */
8371 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8372 if (TREE_CODE (t) == VAR_DECL
8373 && TREE_STATIC (t)
8374 && !DECL_EXTERNAL (t))
8375 varpool_node::finalize_decl (t);
8376 DECL_SAVED_TREE (child_fn) = NULL;
8377 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8378 gimple_set_body (child_fn, NULL);
8379 TREE_USED (block) = 1;
8381 /* Reset DECL_CONTEXT on function arguments. */
8382 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8383 DECL_CONTEXT (t) = child_fn;
8385 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8386 so that it can be moved to the child function. */
8387 gsi = gsi_last_bb (entry_bb);
8388 stmt = gsi_stmt (gsi);
8389 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
8390 && gimple_omp_target_kind (stmt)
8391 == GF_OMP_TARGET_KIND_REGION);
8392 gsi_remove (&gsi, true);
8393 e = split_block (entry_bb, stmt);
8394 entry_bb = e->dest;
8395 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8397 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8398 if (exit_bb)
8400 gsi = gsi_last_bb (exit_bb);
8401 gcc_assert (!gsi_end_p (gsi)
8402 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8403 stmt = gimple_build_return (NULL);
8404 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8405 gsi_remove (&gsi, true);
8408 /* Move the target region into CHILD_CFUN. */
8410 block = gimple_block (entry_stmt);
8412 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8413 if (exit_bb)
8414 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8415 /* When the OMP expansion process cannot guarantee an up-to-date
8416 loop tree arrange for the child function to fixup loops. */
8417 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8418 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8420 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8421 num = vec_safe_length (child_cfun->local_decls);
8422 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8424 t = (*child_cfun->local_decls)[srcidx];
8425 if (DECL_CONTEXT (t) == cfun->decl)
8426 continue;
8427 if (srcidx != dstidx)
8428 (*child_cfun->local_decls)[dstidx] = t;
8429 dstidx++;
8431 if (dstidx != num)
8432 vec_safe_truncate (child_cfun->local_decls, dstidx);
8434 /* Inform the callgraph about the new function. */
8435 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8436 cgraph_node::add_new_function (child_fn, true);
8438 /* Add the new function to the offload table. */
8439 vec_safe_push (offload_funcs, child_fn);
8441 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8442 fixed in a following pass. */
8443 push_cfun (child_cfun);
8444 cgraph_edge::rebuild_edges ();
8446 /* Prevent IPA from removing child_fn as unreachable, since there are no
8447 refs from the parent function to child_fn in offload LTO mode. */
8448 node = cgraph_node::get (child_fn);
8449 node->mark_force_output ();
8451 /* Some EH regions might become dead, see PR34608. If
8452 pass_cleanup_cfg isn't the first pass to happen with the
8453 new child, these dead EH edges might cause problems.
8454 Clean them up now. */
8455 if (flag_exceptions)
8457 basic_block bb;
8458 bool changed = false;
8460 FOR_EACH_BB_FN (bb, cfun)
8461 changed |= gimple_purge_dead_eh_edges (bb);
8462 if (changed)
8463 cleanup_tree_cfg ();
8465 pop_cfun ();
8468 /* Emit a library call to launch the target region, or do data
8469 transfers. */
8470 tree t1, t2, t3, t4, device, cond, c, clauses;
8471 enum built_in_function start_ix;
8472 location_t clause_loc;
8474 clauses = gimple_omp_target_clauses (entry_stmt);
8476 if (kind == GF_OMP_TARGET_KIND_REGION)
8477 start_ix = BUILT_IN_GOMP_TARGET;
8478 else if (kind == GF_OMP_TARGET_KIND_DATA)
8479 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8480 else
8481 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8483 /* By default, the value of DEVICE is -1 (let runtime library choose)
8484 and there is no conditional. */
8485 cond = NULL_TREE;
8486 device = build_int_cst (integer_type_node, -1);
8488 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8489 if (c)
8490 cond = OMP_CLAUSE_IF_EXPR (c);
8492 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8493 if (c)
8495 device = OMP_CLAUSE_DEVICE_ID (c);
8496 clause_loc = OMP_CLAUSE_LOCATION (c);
8498 else
8499 clause_loc = gimple_location (entry_stmt);
8501 /* Ensure 'device' is of the correct type. */
8502 device = fold_convert_loc (clause_loc, integer_type_node, device);
8504 /* If we found the clause 'if (cond)', build
8505 (cond ? device : -2). */
8506 if (cond)
8508 cond = gimple_boolify (cond);
8510 basic_block cond_bb, then_bb, else_bb;
8511 edge e;
8512 tree tmp_var;
8514 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8515 if (kind != GF_OMP_TARGET_KIND_REGION)
8517 gsi = gsi_last_bb (new_bb);
8518 gsi_prev (&gsi);
8519 e = split_block (new_bb, gsi_stmt (gsi));
8521 else
8522 e = split_block (new_bb, NULL);
8523 cond_bb = e->src;
8524 new_bb = e->dest;
8525 remove_edge (e);
8527 then_bb = create_empty_bb (cond_bb);
8528 else_bb = create_empty_bb (then_bb);
8529 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8530 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8532 stmt = gimple_build_cond_empty (cond);
8533 gsi = gsi_last_bb (cond_bb);
8534 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8536 gsi = gsi_start_bb (then_bb);
8537 stmt = gimple_build_assign (tmp_var, device);
8538 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8540 gsi = gsi_start_bb (else_bb);
8541 stmt = gimple_build_assign (tmp_var,
8542 build_int_cst (integer_type_node, -2));
8543 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8545 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8546 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8547 add_bb_to_loop (then_bb, cond_bb->loop_father);
8548 add_bb_to_loop (else_bb, cond_bb->loop_father);
8549 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8550 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8552 device = tmp_var;
8555 gsi = gsi_last_bb (new_bb);
8556 t = gimple_omp_target_data_arg (entry_stmt);
8557 if (t == NULL)
8559 t1 = size_zero_node;
8560 t2 = build_zero_cst (ptr_type_node);
8561 t3 = t2;
8562 t4 = t2;
8564 else
8566 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8567 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8568 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8569 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8570 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8573 gimple g;
8574 /* FIXME: This will be address of
8575 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8576 symbol, as soon as the linker plugin is able to create it for us. */
8577 tree openmp_target = build_zero_cst (ptr_type_node);
8578 if (kind == GF_OMP_TARGET_KIND_REGION)
8580 tree fnaddr = build_fold_addr_expr (child_fn);
8581 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8582 device, fnaddr, openmp_target, t1, t2, t3, t4);
8584 else
8585 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8586 device, openmp_target, t1, t2, t3, t4);
8587 gimple_set_location (g, gimple_location (entry_stmt));
8588 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8589 if (kind != GF_OMP_TARGET_KIND_REGION)
8591 g = gsi_stmt (gsi);
8592 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8593 gsi_remove (&gsi, true);
8595 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8597 gsi = gsi_last_bb (region->exit);
8598 g = gsi_stmt (gsi);
8599 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8600 gsi_remove (&gsi, true);
8605 /* Expand the parallel region tree rooted at REGION. Expansion
8606 proceeds in depth-first order. Innermost regions are expanded
8607 first. This way, parallel regions that require a new function to
8608 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8609 internal dependencies in their body. */
8611 static void
8612 expand_omp (struct omp_region *region)
8614 while (region)
8616 location_t saved_location;
8617 gimple inner_stmt = NULL;
8619 /* First, determine whether this is a combined parallel+workshare
8620 region. */
8621 if (region->type == GIMPLE_OMP_PARALLEL)
8622 determine_parallel_type (region);
8624 if (region->type == GIMPLE_OMP_FOR
8625 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8626 inner_stmt = last_stmt (region->inner->entry);
8628 if (region->inner)
8629 expand_omp (region->inner);
8631 saved_location = input_location;
8632 if (gimple_has_location (last_stmt (region->entry)))
8633 input_location = gimple_location (last_stmt (region->entry));
8635 switch (region->type)
8637 case GIMPLE_OMP_PARALLEL:
8638 case GIMPLE_OMP_TASK:
8639 expand_omp_taskreg (region);
8640 break;
8642 case GIMPLE_OMP_FOR:
8643 expand_omp_for (region, inner_stmt);
8644 break;
8646 case GIMPLE_OMP_SECTIONS:
8647 expand_omp_sections (region);
8648 break;
8650 case GIMPLE_OMP_SECTION:
8651 /* Individual omp sections are handled together with their
8652 parent GIMPLE_OMP_SECTIONS region. */
8653 break;
8655 case GIMPLE_OMP_SINGLE:
8656 expand_omp_single (region);
8657 break;
8659 case GIMPLE_OMP_MASTER:
8660 case GIMPLE_OMP_TASKGROUP:
8661 case GIMPLE_OMP_ORDERED:
8662 case GIMPLE_OMP_CRITICAL:
8663 case GIMPLE_OMP_TEAMS:
8664 expand_omp_synch (region);
8665 break;
8667 case GIMPLE_OMP_ATOMIC_LOAD:
8668 expand_omp_atomic (region);
8669 break;
8671 case GIMPLE_OMP_TARGET:
8672 expand_omp_target (region);
8673 break;
8675 default:
8676 gcc_unreachable ();
8679 input_location = saved_location;
8680 region = region->next;
8685 /* Helper for build_omp_regions. Scan the dominator tree starting at
8686 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8687 true, the function ends once a single tree is built (otherwise, whole
8688 forest of OMP constructs may be built). */
8690 static void
8691 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8692 bool single_tree)
8694 gimple_stmt_iterator gsi;
8695 gimple stmt;
8696 basic_block son;
8698 gsi = gsi_last_bb (bb);
8699 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8701 struct omp_region *region;
8702 enum gimple_code code;
8704 stmt = gsi_stmt (gsi);
8705 code = gimple_code (stmt);
8706 if (code == GIMPLE_OMP_RETURN)
8708 /* STMT is the return point out of region PARENT. Mark it
8709 as the exit point and make PARENT the immediately
8710 enclosing region. */
8711 gcc_assert (parent);
8712 region = parent;
8713 region->exit = bb;
8714 parent = parent->outer;
8716 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8718 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8719 GIMPLE_OMP_RETURN, but matches with
8720 GIMPLE_OMP_ATOMIC_LOAD. */
8721 gcc_assert (parent);
8722 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8723 region = parent;
8724 region->exit = bb;
8725 parent = parent->outer;
8728 else if (code == GIMPLE_OMP_CONTINUE)
8730 gcc_assert (parent);
8731 parent->cont = bb;
8733 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8735 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8736 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8739 else if (code == GIMPLE_OMP_TARGET
8740 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8741 new_omp_region (bb, code, parent);
8742 else
8744 /* Otherwise, this directive becomes the parent for a new
8745 region. */
8746 region = new_omp_region (bb, code, parent);
8747 parent = region;
8751 if (single_tree && !parent)
8752 return;
8754 for (son = first_dom_son (CDI_DOMINATORS, bb);
8755 son;
8756 son = next_dom_son (CDI_DOMINATORS, son))
8757 build_omp_regions_1 (son, parent, single_tree);
8760 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8761 root_omp_region. */
8763 static void
8764 build_omp_regions_root (basic_block root)
8766 gcc_assert (root_omp_region == NULL);
8767 build_omp_regions_1 (root, NULL, true);
8768 gcc_assert (root_omp_region != NULL);
8771 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8773 void
8774 omp_expand_local (basic_block head)
8776 build_omp_regions_root (head);
8777 if (dump_file && (dump_flags & TDF_DETAILS))
8779 fprintf (dump_file, "\nOMP region tree\n\n");
8780 dump_omp_region (dump_file, root_omp_region, 0);
8781 fprintf (dump_file, "\n");
8784 remove_exit_barriers (root_omp_region);
8785 expand_omp (root_omp_region);
8787 free_omp_regions ();
8790 /* Scan the CFG and build a tree of OMP regions. Return the root of
8791 the OMP region tree. */
8793 static void
8794 build_omp_regions (void)
8796 gcc_assert (root_omp_region == NULL);
8797 calculate_dominance_info (CDI_DOMINATORS);
8798 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8801 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8803 static unsigned int
8804 execute_expand_omp (void)
8806 build_omp_regions ();
8808 if (!root_omp_region)
8809 return 0;
8811 if (dump_file)
8813 fprintf (dump_file, "\nOMP region tree\n\n");
8814 dump_omp_region (dump_file, root_omp_region, 0);
8815 fprintf (dump_file, "\n");
8818 remove_exit_barriers (root_omp_region);
8820 expand_omp (root_omp_region);
8822 cleanup_tree_cfg ();
8824 free_omp_regions ();
8826 return 0;
8829 /* OMP expansion -- the default pass, run before creation of SSA form. */
8831 namespace {
8833 const pass_data pass_data_expand_omp =
8835 GIMPLE_PASS, /* type */
8836 "ompexp", /* name */
8837 OPTGROUP_NONE, /* optinfo_flags */
8838 TV_NONE, /* tv_id */
8839 PROP_gimple_any, /* properties_required */
8840 PROP_gimple_eomp, /* properties_provided */
8841 0, /* properties_destroyed */
8842 0, /* todo_flags_start */
8843 0, /* todo_flags_finish */
8846 class pass_expand_omp : public gimple_opt_pass
8848 public:
8849 pass_expand_omp (gcc::context *ctxt)
8850 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8853 /* opt_pass methods: */
8854 virtual unsigned int execute (function *)
8856 bool gate = ((flag_openmp != 0 || flag_openmp_simd != 0
8857 || flag_cilkplus != 0) && !seen_error ());
8859 /* This pass always runs, to provide PROP_gimple_eomp.
8860 But there is nothing to do unless -fopenmp is given. */
8861 if (!gate)
8862 return 0;
8864 return execute_expand_omp ();
8867 }; // class pass_expand_omp
8869 } // anon namespace
8871 gimple_opt_pass *
8872 make_pass_expand_omp (gcc::context *ctxt)
8874 return new pass_expand_omp (ctxt);
8877 namespace {
8879 const pass_data pass_data_expand_omp_ssa =
8881 GIMPLE_PASS, /* type */
8882 "ompexpssa", /* name */
8883 OPTGROUP_NONE, /* optinfo_flags */
8884 TV_NONE, /* tv_id */
8885 PROP_cfg | PROP_ssa, /* properties_required */
8886 PROP_gimple_eomp, /* properties_provided */
8887 0, /* properties_destroyed */
8888 0, /* todo_flags_start */
8889 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
8892 class pass_expand_omp_ssa : public gimple_opt_pass
8894 public:
8895 pass_expand_omp_ssa (gcc::context *ctxt)
8896 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
8899 /* opt_pass methods: */
8900 virtual bool gate (function *fun)
8902 return !(fun->curr_properties & PROP_gimple_eomp);
8904 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8906 }; // class pass_expand_omp_ssa
8908 } // anon namespace
8910 gimple_opt_pass *
8911 make_pass_expand_omp_ssa (gcc::context *ctxt)
8913 return new pass_expand_omp_ssa (ctxt);
8916 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8918 /* If ctx is a worksharing context inside of a cancellable parallel
8919 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8920 and conditional branch to parallel's cancel_label to handle
8921 cancellation in the implicit barrier. */
8923 static void
8924 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8926 gimple omp_return = gimple_seq_last_stmt (*body);
8927 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8928 if (gimple_omp_return_nowait_p (omp_return))
8929 return;
8930 if (ctx->outer
8931 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8932 && ctx->outer->cancellable)
8934 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8935 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8936 tree lhs = create_tmp_var (c_bool_type, NULL);
8937 gimple_omp_return_set_lhs (omp_return, lhs);
8938 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8939 gimple g = gimple_build_cond (NE_EXPR, lhs,
8940 fold_convert (c_bool_type,
8941 boolean_false_node),
8942 ctx->outer->cancel_label, fallthru_label);
8943 gimple_seq_add_stmt (body, g);
8944 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8948 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8949 CTX is the enclosing OMP context for the current statement. */
8951 static void
8952 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8954 tree block, control;
8955 gimple_stmt_iterator tgsi;
8956 gomp_sections *stmt;
8957 gimple t;
8958 gbind *new_stmt, *bind;
8959 gimple_seq ilist, dlist, olist, new_body;
8961 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
8963 push_gimplify_context ();
8965 dlist = NULL;
8966 ilist = NULL;
8967 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8968 &ilist, &dlist, ctx, NULL);
8970 new_body = gimple_omp_body (stmt);
8971 gimple_omp_set_body (stmt, NULL);
8972 tgsi = gsi_start (new_body);
8973 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8975 omp_context *sctx;
8976 gimple sec_start;
8978 sec_start = gsi_stmt (tgsi);
8979 sctx = maybe_lookup_ctx (sec_start);
8980 gcc_assert (sctx);
8982 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8983 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8984 GSI_CONTINUE_LINKING);
8985 gimple_omp_set_body (sec_start, NULL);
8987 if (gsi_one_before_end_p (tgsi))
8989 gimple_seq l = NULL;
8990 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8991 &l, ctx);
8992 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8993 gimple_omp_section_set_last (sec_start);
8996 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8997 GSI_CONTINUE_LINKING);
9000 block = make_node (BLOCK);
9001 bind = gimple_build_bind (NULL, new_body, block);
9003 olist = NULL;
9004 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
9006 block = make_node (BLOCK);
9007 new_stmt = gimple_build_bind (NULL, NULL, block);
9008 gsi_replace (gsi_p, new_stmt, true);
9010 pop_gimplify_context (new_stmt);
9011 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9012 BLOCK_VARS (block) = gimple_bind_vars (bind);
9013 if (BLOCK_VARS (block))
9014 TREE_USED (block) = 1;
9016 new_body = NULL;
9017 gimple_seq_add_seq (&new_body, ilist);
9018 gimple_seq_add_stmt (&new_body, stmt);
9019 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
9020 gimple_seq_add_stmt (&new_body, bind);
9022 control = create_tmp_var (unsigned_type_node, ".section");
9023 t = gimple_build_omp_continue (control, control);
9024 gimple_omp_sections_set_control (stmt, control);
9025 gimple_seq_add_stmt (&new_body, t);
9027 gimple_seq_add_seq (&new_body, olist);
9028 if (ctx->cancellable)
9029 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9030 gimple_seq_add_seq (&new_body, dlist);
9032 new_body = maybe_catch_exception (new_body);
9034 t = gimple_build_omp_return
9035 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
9036 OMP_CLAUSE_NOWAIT));
9037 gimple_seq_add_stmt (&new_body, t);
9038 maybe_add_implicit_barrier_cancel (ctx, &new_body);
9040 gimple_bind_set_body (new_stmt, new_body);
9044 /* A subroutine of lower_omp_single. Expand the simple form of
9045 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
9047 if (GOMP_single_start ())
9048 BODY;
9049 [ GOMP_barrier (); ] -> unless 'nowait' is present.
9051 FIXME. It may be better to delay expanding the logic of this until
9052 pass_expand_omp. The expanded logic may make the job more difficult
9053 to a synchronization analysis pass. */
9055 static void
9056 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
9058 location_t loc = gimple_location (single_stmt);
9059 tree tlabel = create_artificial_label (loc);
9060 tree flabel = create_artificial_label (loc);
9061 gimple call, cond;
9062 tree lhs, decl;
9064 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
9065 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
9066 call = gimple_build_call (decl, 0);
9067 gimple_call_set_lhs (call, lhs);
9068 gimple_seq_add_stmt (pre_p, call);
9070 cond = gimple_build_cond (EQ_EXPR, lhs,
9071 fold_convert_loc (loc, TREE_TYPE (lhs),
9072 boolean_true_node),
9073 tlabel, flabel);
9074 gimple_seq_add_stmt (pre_p, cond);
9075 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
9076 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9077 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
9081 /* A subroutine of lower_omp_single. Expand the simple form of
9082 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
9084 #pragma omp single copyprivate (a, b, c)
9086 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
9089 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
9091 BODY;
9092 copyout.a = a;
9093 copyout.b = b;
9094 copyout.c = c;
9095 GOMP_single_copy_end (&copyout);
9097 else
9099 a = copyout_p->a;
9100 b = copyout_p->b;
9101 c = copyout_p->c;
9103 GOMP_barrier ();
9106 FIXME. It may be better to delay expanding the logic of this until
9107 pass_expand_omp. The expanded logic may make the job more difficult
9108 to a synchronization analysis pass. */
9110 static void
9111 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
9112 omp_context *ctx)
9114 tree ptr_type, t, l0, l1, l2, bfn_decl;
9115 gimple_seq copyin_seq;
9116 location_t loc = gimple_location (single_stmt);
9118 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
9120 ptr_type = build_pointer_type (ctx->record_type);
9121 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
9123 l0 = create_artificial_label (loc);
9124 l1 = create_artificial_label (loc);
9125 l2 = create_artificial_label (loc);
9127 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
9128 t = build_call_expr_loc (loc, bfn_decl, 0);
9129 t = fold_convert_loc (loc, ptr_type, t);
9130 gimplify_assign (ctx->receiver_decl, t, pre_p);
9132 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
9133 build_int_cst (ptr_type, 0));
9134 t = build3 (COND_EXPR, void_type_node, t,
9135 build_and_jump (&l0), build_and_jump (&l1));
9136 gimplify_and_add (t, pre_p);
9138 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
9140 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9142 copyin_seq = NULL;
9143 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
9144 &copyin_seq, ctx);
9146 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9147 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
9148 t = build_call_expr_loc (loc, bfn_decl, 1, t);
9149 gimplify_and_add (t, pre_p);
9151 t = build_and_jump (&l2);
9152 gimplify_and_add (t, pre_p);
9154 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
9156 gimple_seq_add_seq (pre_p, copyin_seq);
9158 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
9162 /* Expand code for an OpenMP single directive. */
9164 static void
9165 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9167 tree block;
9168 gimple t;
9169 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
9170 gbind *bind;
9171 gimple_seq bind_body, bind_body_tail = NULL, dlist;
9173 push_gimplify_context ();
9175 block = make_node (BLOCK);
9176 bind = gimple_build_bind (NULL, NULL, block);
9177 gsi_replace (gsi_p, bind, true);
9178 bind_body = NULL;
9179 dlist = NULL;
9180 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
9181 &bind_body, &dlist, ctx, NULL);
9182 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
9184 gimple_seq_add_stmt (&bind_body, single_stmt);
9186 if (ctx->record_type)
9187 lower_omp_single_copy (single_stmt, &bind_body, ctx);
9188 else
9189 lower_omp_single_simple (single_stmt, &bind_body);
9191 gimple_omp_set_body (single_stmt, NULL);
9193 gimple_seq_add_seq (&bind_body, dlist);
9195 bind_body = maybe_catch_exception (bind_body);
9197 t = gimple_build_omp_return
9198 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
9199 OMP_CLAUSE_NOWAIT));
9200 gimple_seq_add_stmt (&bind_body_tail, t);
9201 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
9202 if (ctx->record_type)
9204 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9205 tree clobber = build_constructor (ctx->record_type, NULL);
9206 TREE_THIS_VOLATILE (clobber) = 1;
9207 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9208 clobber), GSI_SAME_STMT);
9210 gimple_seq_add_seq (&bind_body, bind_body_tail);
9211 gimple_bind_set_body (bind, bind_body);
9213 pop_gimplify_context (bind);
9215 gimple_bind_append_vars (bind, ctx->block_vars);
9216 BLOCK_VARS (block) = ctx->block_vars;
9217 if (BLOCK_VARS (block))
9218 TREE_USED (block) = 1;
9222 /* Expand code for an OpenMP master directive. */
9224 static void
9225 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9227 tree block, lab = NULL, x, bfn_decl;
9228 gimple stmt = gsi_stmt (*gsi_p);
9229 gbind *bind;
9230 location_t loc = gimple_location (stmt);
9231 gimple_seq tseq;
9233 push_gimplify_context ();
9235 block = make_node (BLOCK);
9236 bind = gimple_build_bind (NULL, NULL, block);
9237 gsi_replace (gsi_p, bind, true);
9238 gimple_bind_add_stmt (bind, stmt);
9240 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9241 x = build_call_expr_loc (loc, bfn_decl, 0);
9242 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
9243 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9244 tseq = NULL;
9245 gimplify_and_add (x, &tseq);
9246 gimple_bind_add_seq (bind, tseq);
9248 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9249 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9250 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9251 gimple_omp_set_body (stmt, NULL);
9253 gimple_bind_add_stmt (bind, gimple_build_label (lab));
9255 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9257 pop_gimplify_context (bind);
9259 gimple_bind_append_vars (bind, ctx->block_vars);
9260 BLOCK_VARS (block) = ctx->block_vars;
9264 /* Expand code for an OpenMP taskgroup directive. */
9266 static void
9267 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9269 gimple stmt = gsi_stmt (*gsi_p);
9270 gcall *x;
9271 gbind *bind;
9272 tree block = make_node (BLOCK);
9274 bind = gimple_build_bind (NULL, NULL, block);
9275 gsi_replace (gsi_p, bind, true);
9276 gimple_bind_add_stmt (bind, stmt);
9278 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9280 gimple_bind_add_stmt (bind, x);
9282 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9283 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9284 gimple_omp_set_body (stmt, NULL);
9286 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9288 gimple_bind_append_vars (bind, ctx->block_vars);
9289 BLOCK_VARS (block) = ctx->block_vars;
9293 /* Expand code for an OpenMP ordered directive. */
9295 static void
9296 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9298 tree block;
9299 gimple stmt = gsi_stmt (*gsi_p);
9300 gcall *x;
9301 gbind *bind;
9303 push_gimplify_context ();
9305 block = make_node (BLOCK);
9306 bind = gimple_build_bind (NULL, NULL, block);
9307 gsi_replace (gsi_p, bind, true);
9308 gimple_bind_add_stmt (bind, stmt);
9310 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
9312 gimple_bind_add_stmt (bind, x);
9314 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9315 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9316 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9317 gimple_omp_set_body (stmt, NULL);
9319 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
9320 gimple_bind_add_stmt (bind, x);
9322 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9324 pop_gimplify_context (bind);
9326 gimple_bind_append_vars (bind, ctx->block_vars);
9327 BLOCK_VARS (block) = gimple_bind_vars (bind);
9331 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9332 substitution of a couple of function calls. But in the NAMED case,
9333 requires that languages coordinate a symbol name. It is therefore
9334 best put here in common code. */
9336 static GTY((param1_is (tree), param2_is (tree)))
9337 splay_tree critical_name_mutexes;
9339 static void
9340 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9342 tree block;
9343 tree name, lock, unlock;
9344 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
9345 gbind *bind;
9346 location_t loc = gimple_location (stmt);
9347 gimple_seq tbody;
9349 name = gimple_omp_critical_name (stmt);
9350 if (name)
9352 tree decl;
9353 splay_tree_node n;
9355 if (!critical_name_mutexes)
9356 critical_name_mutexes
9357 = splay_tree_new_ggc (splay_tree_compare_pointers,
9358 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
9359 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
9361 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
9362 if (n == NULL)
9364 char *new_str;
9366 decl = create_tmp_var_raw (ptr_type_node, NULL);
9368 new_str = ACONCAT ((".gomp_critical_user_",
9369 IDENTIFIER_POINTER (name), NULL));
9370 DECL_NAME (decl) = get_identifier (new_str);
9371 TREE_PUBLIC (decl) = 1;
9372 TREE_STATIC (decl) = 1;
9373 DECL_COMMON (decl) = 1;
9374 DECL_ARTIFICIAL (decl) = 1;
9375 DECL_IGNORED_P (decl) = 1;
9377 /* If '#pragma omp critical' is inside target region, the symbol must
9378 be marked for offloading. */
9379 omp_context *octx;
9380 for (octx = ctx->outer; octx; octx = octx->outer)
9381 if (is_targetreg_ctx (octx))
9383 varpool_node::get_create (decl)->offloadable = 1;
9384 break;
9387 varpool_node::finalize_decl (decl);
9389 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
9390 (splay_tree_value) decl);
9392 else
9393 decl = (tree) n->value;
9395 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
9396 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
9398 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
9399 unlock = build_call_expr_loc (loc, unlock, 1,
9400 build_fold_addr_expr_loc (loc, decl));
9402 else
9404 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
9405 lock = build_call_expr_loc (loc, lock, 0);
9407 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
9408 unlock = build_call_expr_loc (loc, unlock, 0);
9411 push_gimplify_context ();
9413 block = make_node (BLOCK);
9414 bind = gimple_build_bind (NULL, NULL, block);
9415 gsi_replace (gsi_p, bind, true);
9416 gimple_bind_add_stmt (bind, stmt);
9418 tbody = gimple_bind_body (bind);
9419 gimplify_and_add (lock, &tbody);
9420 gimple_bind_set_body (bind, tbody);
9422 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9423 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9424 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9425 gimple_omp_set_body (stmt, NULL);
9427 tbody = gimple_bind_body (bind);
9428 gimplify_and_add (unlock, &tbody);
9429 gimple_bind_set_body (bind, tbody);
9431 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9433 pop_gimplify_context (bind);
9434 gimple_bind_append_vars (bind, ctx->block_vars);
9435 BLOCK_VARS (block) = gimple_bind_vars (bind);
9439 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9440 for a lastprivate clause. Given a loop control predicate of (V
9441 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9442 is appended to *DLIST, iterator initialization is appended to
9443 *BODY_P. */
9445 static void
9446 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
9447 gimple_seq *dlist, struct omp_context *ctx)
9449 tree clauses, cond, vinit;
9450 enum tree_code cond_code;
9451 gimple_seq stmts;
9453 cond_code = fd->loop.cond_code;
9454 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
9456 /* When possible, use a strict equality expression. This can let VRP
9457 type optimizations deduce the value and remove a copy. */
9458 if (tree_fits_shwi_p (fd->loop.step))
9460 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
9461 if (step == 1 || step == -1)
9462 cond_code = EQ_EXPR;
9465 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
9467 clauses = gimple_omp_for_clauses (fd->for_stmt);
9468 stmts = NULL;
9469 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
9470 if (!gimple_seq_empty_p (stmts))
9472 gimple_seq_add_seq (&stmts, *dlist);
9473 *dlist = stmts;
9475 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9476 vinit = fd->loop.n1;
9477 if (cond_code == EQ_EXPR
9478 && tree_fits_shwi_p (fd->loop.n2)
9479 && ! integer_zerop (fd->loop.n2))
9480 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
9481 else
9482 vinit = unshare_expr (vinit);
9484 /* Initialize the iterator variable, so that threads that don't execute
9485 any iterations don't execute the lastprivate clauses by accident. */
9486 gimplify_assign (fd->loop.v, vinit, body_p);
9491 /* Lower code for an OpenMP loop directive. */
9493 static void
9494 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9496 tree *rhs_p, block;
9497 struct omp_for_data fd, *fdp = NULL;
9498 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
9499 gbind *new_stmt;
9500 gimple_seq omp_for_body, body, dlist;
9501 size_t i;
9503 push_gimplify_context ();
9505 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
9507 block = make_node (BLOCK);
9508 new_stmt = gimple_build_bind (NULL, NULL, block);
9509 /* Replace at gsi right away, so that 'stmt' is no member
9510 of a sequence anymore as we're going to add to to a different
9511 one below. */
9512 gsi_replace (gsi_p, new_stmt, true);
9514 /* Move declaration of temporaries in the loop body before we make
9515 it go away. */
9516 omp_for_body = gimple_omp_body (stmt);
9517 if (!gimple_seq_empty_p (omp_for_body)
9518 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9520 gbind *inner_bind =
9521 as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
9522 tree vars = gimple_bind_vars (inner_bind);
9523 gimple_bind_append_vars (new_stmt, vars);
9524 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9525 keep them on the inner_bind and it's block. */
9526 gimple_bind_set_vars (inner_bind, NULL_TREE);
9527 if (gimple_bind_block (inner_bind))
9528 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9531 if (gimple_omp_for_combined_into_p (stmt))
9533 extract_omp_for_data (stmt, &fd, NULL);
9534 fdp = &fd;
9536 /* We need two temporaries with fd.loop.v type (istart/iend)
9537 and then (fd.collapse - 1) temporaries with the same
9538 type for count2 ... countN-1 vars if not constant. */
9539 size_t count = 2;
9540 tree type = fd.iter_type;
9541 if (fd.collapse > 1
9542 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9543 count += fd.collapse - 1;
9544 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9545 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9546 tree clauses = *pc;
9547 if (parallel_for)
9548 outerc
9549 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9550 OMP_CLAUSE__LOOPTEMP_);
9551 for (i = 0; i < count; i++)
9553 tree temp;
9554 if (parallel_for)
9556 gcc_assert (outerc);
9557 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9558 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9559 OMP_CLAUSE__LOOPTEMP_);
9561 else
9563 temp = create_tmp_var (type, NULL);
9564 insert_decl_map (&ctx->outer->cb, temp, temp);
9566 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9567 OMP_CLAUSE_DECL (*pc) = temp;
9568 pc = &OMP_CLAUSE_CHAIN (*pc);
9570 *pc = clauses;
9573 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9574 dlist = NULL;
9575 body = NULL;
9576 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9577 fdp);
9578 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9580 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9582 /* Lower the header expressions. At this point, we can assume that
9583 the header is of the form:
9585 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9587 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9588 using the .omp_data_s mapping, if needed. */
9589 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9591 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9592 if (!is_gimple_min_invariant (*rhs_p))
9593 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9595 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9596 if (!is_gimple_min_invariant (*rhs_p))
9597 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9599 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9600 if (!is_gimple_min_invariant (*rhs_p))
9601 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9604 /* Once lowered, extract the bounds and clauses. */
9605 extract_omp_for_data (stmt, &fd, NULL);
9607 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9609 gimple_seq_add_stmt (&body, stmt);
9610 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9612 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9613 fd.loop.v));
9615 /* After the loop, add exit clauses. */
9616 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9618 if (ctx->cancellable)
9619 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9621 gimple_seq_add_seq (&body, dlist);
9623 body = maybe_catch_exception (body);
9625 /* Region exit marker goes at the end of the loop body. */
9626 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9627 maybe_add_implicit_barrier_cancel (ctx, &body);
9628 pop_gimplify_context (new_stmt);
9630 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9631 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9632 if (BLOCK_VARS (block))
9633 TREE_USED (block) = 1;
9635 gimple_bind_set_body (new_stmt, body);
9636 gimple_omp_set_body (stmt, NULL);
9637 gimple_omp_for_set_pre_body (stmt, NULL);
9640 /* Callback for walk_stmts. Check if the current statement only contains
9641 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9643 static tree
9644 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9645 bool *handled_ops_p,
9646 struct walk_stmt_info *wi)
9648 int *info = (int *) wi->info;
9649 gimple stmt = gsi_stmt (*gsi_p);
9651 *handled_ops_p = true;
9652 switch (gimple_code (stmt))
9654 WALK_SUBSTMTS;
9656 case GIMPLE_OMP_FOR:
9657 case GIMPLE_OMP_SECTIONS:
9658 *info = *info == 0 ? 1 : -1;
9659 break;
9660 default:
9661 *info = -1;
9662 break;
9664 return NULL;
9667 struct omp_taskcopy_context
9669 /* This field must be at the beginning, as we do "inheritance": Some
9670 callback functions for tree-inline.c (e.g., omp_copy_decl)
9671 receive a copy_body_data pointer that is up-casted to an
9672 omp_context pointer. */
9673 copy_body_data cb;
9674 omp_context *ctx;
9677 static tree
9678 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9680 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9682 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9683 return create_tmp_var (TREE_TYPE (var), NULL);
9685 return var;
9688 static tree
9689 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9691 tree name, new_fields = NULL, type, f;
9693 type = lang_hooks.types.make_type (RECORD_TYPE);
9694 name = DECL_NAME (TYPE_NAME (orig_type));
9695 name = build_decl (gimple_location (tcctx->ctx->stmt),
9696 TYPE_DECL, name, type);
9697 TYPE_NAME (type) = name;
9699 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9701 tree new_f = copy_node (f);
9702 DECL_CONTEXT (new_f) = type;
9703 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9704 TREE_CHAIN (new_f) = new_fields;
9705 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9706 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9707 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9708 &tcctx->cb, NULL);
9709 new_fields = new_f;
9710 tcctx->cb.decl_map->put (f, new_f);
9712 TYPE_FIELDS (type) = nreverse (new_fields);
9713 layout_type (type);
9714 return type;
9717 /* Create task copyfn. */
9719 static void
9720 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
9722 struct function *child_cfun;
9723 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9724 tree record_type, srecord_type, bind, list;
9725 bool record_needs_remap = false, srecord_needs_remap = false;
9726 splay_tree_node n;
9727 struct omp_taskcopy_context tcctx;
9728 location_t loc = gimple_location (task_stmt);
9730 child_fn = gimple_omp_task_copy_fn (task_stmt);
9731 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9732 gcc_assert (child_cfun->cfg == NULL);
9733 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9735 /* Reset DECL_CONTEXT on function arguments. */
9736 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9737 DECL_CONTEXT (t) = child_fn;
9739 /* Populate the function. */
9740 push_gimplify_context ();
9741 push_cfun (child_cfun);
9743 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9744 TREE_SIDE_EFFECTS (bind) = 1;
9745 list = NULL;
9746 DECL_SAVED_TREE (child_fn) = bind;
9747 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9749 /* Remap src and dst argument types if needed. */
9750 record_type = ctx->record_type;
9751 srecord_type = ctx->srecord_type;
9752 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9753 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9755 record_needs_remap = true;
9756 break;
9758 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9759 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9761 srecord_needs_remap = true;
9762 break;
9765 if (record_needs_remap || srecord_needs_remap)
9767 memset (&tcctx, '\0', sizeof (tcctx));
9768 tcctx.cb.src_fn = ctx->cb.src_fn;
9769 tcctx.cb.dst_fn = child_fn;
9770 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
9771 gcc_checking_assert (tcctx.cb.src_node);
9772 tcctx.cb.dst_node = tcctx.cb.src_node;
9773 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9774 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9775 tcctx.cb.eh_lp_nr = 0;
9776 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9777 tcctx.cb.decl_map = new hash_map<tree, tree>;
9778 tcctx.ctx = ctx;
9780 if (record_needs_remap)
9781 record_type = task_copyfn_remap_type (&tcctx, record_type);
9782 if (srecord_needs_remap)
9783 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9785 else
9786 tcctx.cb.decl_map = NULL;
9788 arg = DECL_ARGUMENTS (child_fn);
9789 TREE_TYPE (arg) = build_pointer_type (record_type);
9790 sarg = DECL_CHAIN (arg);
9791 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9793 /* First pass: initialize temporaries used in record_type and srecord_type
9794 sizes and field offsets. */
9795 if (tcctx.cb.decl_map)
9796 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9797 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9799 tree *p;
9801 decl = OMP_CLAUSE_DECL (c);
9802 p = tcctx.cb.decl_map->get (decl);
9803 if (p == NULL)
9804 continue;
9805 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9806 sf = (tree) n->value;
9807 sf = *tcctx.cb.decl_map->get (sf);
9808 src = build_simple_mem_ref_loc (loc, sarg);
9809 src = omp_build_component_ref (src, sf);
9810 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9811 append_to_statement_list (t, &list);
9814 /* Second pass: copy shared var pointers and copy construct non-VLA
9815 firstprivate vars. */
9816 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9817 switch (OMP_CLAUSE_CODE (c))
9819 case OMP_CLAUSE_SHARED:
9820 decl = OMP_CLAUSE_DECL (c);
9821 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9822 if (n == NULL)
9823 break;
9824 f = (tree) n->value;
9825 if (tcctx.cb.decl_map)
9826 f = *tcctx.cb.decl_map->get (f);
9827 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9828 sf = (tree) n->value;
9829 if (tcctx.cb.decl_map)
9830 sf = *tcctx.cb.decl_map->get (sf);
9831 src = build_simple_mem_ref_loc (loc, sarg);
9832 src = omp_build_component_ref (src, sf);
9833 dst = build_simple_mem_ref_loc (loc, arg);
9834 dst = omp_build_component_ref (dst, f);
9835 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9836 append_to_statement_list (t, &list);
9837 break;
9838 case OMP_CLAUSE_FIRSTPRIVATE:
9839 decl = OMP_CLAUSE_DECL (c);
9840 if (is_variable_sized (decl))
9841 break;
9842 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9843 if (n == NULL)
9844 break;
9845 f = (tree) n->value;
9846 if (tcctx.cb.decl_map)
9847 f = *tcctx.cb.decl_map->get (f);
9848 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9849 if (n != NULL)
9851 sf = (tree) n->value;
9852 if (tcctx.cb.decl_map)
9853 sf = *tcctx.cb.decl_map->get (sf);
9854 src = build_simple_mem_ref_loc (loc, sarg);
9855 src = omp_build_component_ref (src, sf);
9856 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9857 src = build_simple_mem_ref_loc (loc, src);
9859 else
9860 src = decl;
9861 dst = build_simple_mem_ref_loc (loc, arg);
9862 dst = omp_build_component_ref (dst, f);
9863 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9864 append_to_statement_list (t, &list);
9865 break;
9866 case OMP_CLAUSE_PRIVATE:
9867 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9868 break;
9869 decl = OMP_CLAUSE_DECL (c);
9870 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9871 f = (tree) n->value;
9872 if (tcctx.cb.decl_map)
9873 f = *tcctx.cb.decl_map->get (f);
9874 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9875 if (n != NULL)
9877 sf = (tree) n->value;
9878 if (tcctx.cb.decl_map)
9879 sf = *tcctx.cb.decl_map->get (sf);
9880 src = build_simple_mem_ref_loc (loc, sarg);
9881 src = omp_build_component_ref (src, sf);
9882 if (use_pointer_for_field (decl, NULL))
9883 src = build_simple_mem_ref_loc (loc, src);
9885 else
9886 src = decl;
9887 dst = build_simple_mem_ref_loc (loc, arg);
9888 dst = omp_build_component_ref (dst, f);
9889 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9890 append_to_statement_list (t, &list);
9891 break;
9892 default:
9893 break;
9896 /* Last pass: handle VLA firstprivates. */
9897 if (tcctx.cb.decl_map)
9898 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9899 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9901 tree ind, ptr, df;
9903 decl = OMP_CLAUSE_DECL (c);
9904 if (!is_variable_sized (decl))
9905 continue;
9906 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9907 if (n == NULL)
9908 continue;
9909 f = (tree) n->value;
9910 f = *tcctx.cb.decl_map->get (f);
9911 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9912 ind = DECL_VALUE_EXPR (decl);
9913 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9914 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9915 n = splay_tree_lookup (ctx->sfield_map,
9916 (splay_tree_key) TREE_OPERAND (ind, 0));
9917 sf = (tree) n->value;
9918 sf = *tcctx.cb.decl_map->get (sf);
9919 src = build_simple_mem_ref_loc (loc, sarg);
9920 src = omp_build_component_ref (src, sf);
9921 src = build_simple_mem_ref_loc (loc, src);
9922 dst = build_simple_mem_ref_loc (loc, arg);
9923 dst = omp_build_component_ref (dst, f);
9924 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9925 append_to_statement_list (t, &list);
9926 n = splay_tree_lookup (ctx->field_map,
9927 (splay_tree_key) TREE_OPERAND (ind, 0));
9928 df = (tree) n->value;
9929 df = *tcctx.cb.decl_map->get (df);
9930 ptr = build_simple_mem_ref_loc (loc, arg);
9931 ptr = omp_build_component_ref (ptr, df);
9932 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9933 build_fold_addr_expr_loc (loc, dst));
9934 append_to_statement_list (t, &list);
9937 t = build1 (RETURN_EXPR, void_type_node, NULL);
9938 append_to_statement_list (t, &list);
9940 if (tcctx.cb.decl_map)
9941 delete tcctx.cb.decl_map;
9942 pop_gimplify_context (NULL);
9943 BIND_EXPR_BODY (bind) = list;
9944 pop_cfun ();
9947 static void
9948 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9950 tree c, clauses;
9951 gimple g;
9952 size_t n_in = 0, n_out = 0, idx = 2, i;
9954 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9955 OMP_CLAUSE_DEPEND);
9956 gcc_assert (clauses);
9957 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9958 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9959 switch (OMP_CLAUSE_DEPEND_KIND (c))
9961 case OMP_CLAUSE_DEPEND_IN:
9962 n_in++;
9963 break;
9964 case OMP_CLAUSE_DEPEND_OUT:
9965 case OMP_CLAUSE_DEPEND_INOUT:
9966 n_out++;
9967 break;
9968 default:
9969 gcc_unreachable ();
9971 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9972 tree array = create_tmp_var (type, NULL);
9973 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9974 NULL_TREE);
9975 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9976 gimple_seq_add_stmt (iseq, g);
9977 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9978 NULL_TREE);
9979 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9980 gimple_seq_add_stmt (iseq, g);
9981 for (i = 0; i < 2; i++)
9983 if ((i ? n_in : n_out) == 0)
9984 continue;
9985 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9986 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9987 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9989 tree t = OMP_CLAUSE_DECL (c);
9990 t = fold_convert (ptr_type_node, t);
9991 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9992 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9993 NULL_TREE, NULL_TREE);
9994 g = gimple_build_assign (r, t);
9995 gimple_seq_add_stmt (iseq, g);
9998 tree *p = gimple_omp_task_clauses_ptr (stmt);
9999 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
10000 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
10001 OMP_CLAUSE_CHAIN (c) = *p;
10002 *p = c;
10003 tree clobber = build_constructor (type, NULL);
10004 TREE_THIS_VOLATILE (clobber) = 1;
10005 g = gimple_build_assign (array, clobber);
10006 gimple_seq_add_stmt (oseq, g);
10009 /* Lower the OpenMP parallel or task directive in the current statement
10010 in GSI_P. CTX holds context information for the directive. */
10012 static void
10013 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10015 tree clauses;
10016 tree child_fn, t;
10017 gimple stmt = gsi_stmt (*gsi_p);
10018 gbind *par_bind, *bind, *dep_bind = NULL;
10019 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
10020 location_t loc = gimple_location (stmt);
10022 clauses = gimple_omp_taskreg_clauses (stmt);
10023 par_bind =
10024 as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
10025 par_body = gimple_bind_body (par_bind);
10026 child_fn = ctx->cb.dst_fn;
10027 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
10028 && !gimple_omp_parallel_combined_p (stmt))
10030 struct walk_stmt_info wi;
10031 int ws_num = 0;
10033 memset (&wi, 0, sizeof (wi));
10034 wi.info = &ws_num;
10035 wi.val_only = true;
10036 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
10037 if (ws_num == 1)
10038 gimple_omp_parallel_set_combined_p (stmt, true);
10040 gimple_seq dep_ilist = NULL;
10041 gimple_seq dep_olist = NULL;
10042 if (gimple_code (stmt) == GIMPLE_OMP_TASK
10043 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
10045 push_gimplify_context ();
10046 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
10047 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
10050 if (ctx->srecord_type)
10051 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
10053 push_gimplify_context ();
10055 par_olist = NULL;
10056 par_ilist = NULL;
10057 par_rlist = NULL;
10058 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
10059 lower_omp (&par_body, ctx);
10060 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
10061 lower_reduction_clauses (clauses, &par_rlist, ctx);
10063 /* Declare all the variables created by mapping and the variables
10064 declared in the scope of the parallel body. */
10065 record_vars_into (ctx->block_vars, child_fn);
10066 record_vars_into (gimple_bind_vars (par_bind), child_fn);
10068 if (ctx->record_type)
10070 ctx->sender_decl
10071 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
10072 : ctx->record_type, ".omp_data_o");
10073 DECL_NAMELESS (ctx->sender_decl) = 1;
10074 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10075 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
10078 olist = NULL;
10079 ilist = NULL;
10080 lower_send_clauses (clauses, &ilist, &olist, ctx);
10081 lower_send_shared_vars (&ilist, &olist, ctx);
10083 if (ctx->record_type)
10085 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
10086 TREE_THIS_VOLATILE (clobber) = 1;
10087 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10088 clobber));
10091 /* Once all the expansions are done, sequence all the different
10092 fragments inside gimple_omp_body. */
10094 new_body = NULL;
10096 if (ctx->record_type)
10098 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10099 /* fixup_child_record_type might have changed receiver_decl's type. */
10100 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10101 gimple_seq_add_stmt (&new_body,
10102 gimple_build_assign (ctx->receiver_decl, t));
10105 gimple_seq_add_seq (&new_body, par_ilist);
10106 gimple_seq_add_seq (&new_body, par_body);
10107 gimple_seq_add_seq (&new_body, par_rlist);
10108 if (ctx->cancellable)
10109 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10110 gimple_seq_add_seq (&new_body, par_olist);
10111 new_body = maybe_catch_exception (new_body);
10112 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10113 gimple_omp_set_body (stmt, new_body);
10115 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
10116 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
10117 gimple_bind_add_seq (bind, ilist);
10118 gimple_bind_add_stmt (bind, stmt);
10119 gimple_bind_add_seq (bind, olist);
10121 pop_gimplify_context (NULL);
10123 if (dep_bind)
10125 gimple_bind_add_seq (dep_bind, dep_ilist);
10126 gimple_bind_add_stmt (dep_bind, bind);
10127 gimple_bind_add_seq (dep_bind, dep_olist);
10128 pop_gimplify_context (dep_bind);
10132 /* Lower the OpenMP target directive in the current statement
10133 in GSI_P. CTX holds context information for the directive. */
10135 static void
10136 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10138 tree clauses;
10139 tree child_fn, t, c;
10140 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
10141 gbind *tgt_bind = NULL, *bind;
10142 gimple_seq tgt_body = NULL, olist, ilist, new_body;
10143 location_t loc = gimple_location (stmt);
10144 int kind = gimple_omp_target_kind (stmt);
10145 unsigned int map_cnt = 0;
10147 clauses = gimple_omp_target_clauses (stmt);
10148 if (kind == GF_OMP_TARGET_KIND_REGION)
10150 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
10151 tgt_body = gimple_bind_body (tgt_bind);
10153 else if (kind == GF_OMP_TARGET_KIND_DATA)
10154 tgt_body = gimple_omp_body (stmt);
10155 child_fn = ctx->cb.dst_fn;
10157 push_gimplify_context ();
10159 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10160 switch (OMP_CLAUSE_CODE (c))
10162 tree var, x;
10164 default:
10165 break;
10166 case OMP_CLAUSE_MAP:
10167 case OMP_CLAUSE_TO:
10168 case OMP_CLAUSE_FROM:
10169 var = OMP_CLAUSE_DECL (c);
10170 if (!DECL_P (var))
10172 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10173 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10174 map_cnt++;
10175 continue;
10178 if (DECL_SIZE (var)
10179 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
10181 tree var2 = DECL_VALUE_EXPR (var);
10182 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
10183 var2 = TREE_OPERAND (var2, 0);
10184 gcc_assert (DECL_P (var2));
10185 var = var2;
10188 if (!maybe_lookup_field (var, ctx))
10189 continue;
10191 if (kind == GF_OMP_TARGET_KIND_REGION)
10193 x = build_receiver_ref (var, true, ctx);
10194 tree new_var = lookup_decl (var, ctx);
10195 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10196 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10197 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10198 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
10199 x = build_simple_mem_ref (x);
10200 SET_DECL_VALUE_EXPR (new_var, x);
10201 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
10203 map_cnt++;
10206 if (kind == GF_OMP_TARGET_KIND_REGION)
10208 target_nesting_level++;
10209 lower_omp (&tgt_body, ctx);
10210 target_nesting_level--;
10212 else if (kind == GF_OMP_TARGET_KIND_DATA)
10213 lower_omp (&tgt_body, ctx);
10215 if (kind == GF_OMP_TARGET_KIND_REGION)
10217 /* Declare all the variables created by mapping and the variables
10218 declared in the scope of the target body. */
10219 record_vars_into (ctx->block_vars, child_fn);
10220 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
10223 olist = NULL;
10224 ilist = NULL;
10225 if (ctx->record_type)
10227 ctx->sender_decl
10228 = create_tmp_var (ctx->record_type, ".omp_data_arr");
10229 DECL_NAMELESS (ctx->sender_decl) = 1;
10230 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10231 t = make_tree_vec (3);
10232 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
10233 TREE_VEC_ELT (t, 1)
10234 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
10235 ".omp_data_sizes");
10236 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
10237 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
10238 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
10239 TREE_VEC_ELT (t, 2)
10240 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
10241 map_cnt),
10242 ".omp_data_kinds");
10243 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
10244 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
10245 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
10246 gimple_omp_target_set_data_arg (stmt, t);
10248 vec<constructor_elt, va_gc> *vsize;
10249 vec<constructor_elt, va_gc> *vkind;
10250 vec_alloc (vsize, map_cnt);
10251 vec_alloc (vkind, map_cnt);
10252 unsigned int map_idx = 0;
10254 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10255 switch (OMP_CLAUSE_CODE (c))
10257 tree ovar, nc;
10259 default:
10260 break;
10261 case OMP_CLAUSE_MAP:
10262 case OMP_CLAUSE_TO:
10263 case OMP_CLAUSE_FROM:
10264 nc = c;
10265 ovar = OMP_CLAUSE_DECL (c);
10266 if (!DECL_P (ovar))
10268 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10269 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10271 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
10272 == get_base_address (ovar));
10273 nc = OMP_CLAUSE_CHAIN (c);
10274 ovar = OMP_CLAUSE_DECL (nc);
10276 else
10278 tree x = build_sender_ref (ovar, ctx);
10279 tree v
10280 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
10281 gimplify_assign (x, v, &ilist);
10282 nc = NULL_TREE;
10285 else
10287 if (DECL_SIZE (ovar)
10288 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
10290 tree ovar2 = DECL_VALUE_EXPR (ovar);
10291 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
10292 ovar2 = TREE_OPERAND (ovar2, 0);
10293 gcc_assert (DECL_P (ovar2));
10294 ovar = ovar2;
10296 if (!maybe_lookup_field (ovar, ctx))
10297 continue;
10300 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
10301 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
10302 talign = DECL_ALIGN_UNIT (ovar);
10303 if (nc)
10305 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
10306 tree x = build_sender_ref (ovar, ctx);
10307 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10308 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10309 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10310 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
10312 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10313 tree avar
10314 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
10315 mark_addressable (avar);
10316 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
10317 talign = DECL_ALIGN_UNIT (avar);
10318 avar = build_fold_addr_expr (avar);
10319 gimplify_assign (x, avar, &ilist);
10321 else if (is_gimple_reg (var))
10323 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10324 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
10325 mark_addressable (avar);
10326 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
10327 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
10328 gimplify_assign (avar, var, &ilist);
10329 avar = build_fold_addr_expr (avar);
10330 gimplify_assign (x, avar, &ilist);
10331 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
10332 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
10333 && !TYPE_READONLY (TREE_TYPE (var)))
10335 x = build_sender_ref (ovar, ctx);
10336 x = build_simple_mem_ref (x);
10337 gimplify_assign (var, x, &olist);
10340 else
10342 var = build_fold_addr_expr (var);
10343 gimplify_assign (x, var, &ilist);
10346 tree s = OMP_CLAUSE_SIZE (c);
10347 if (s == NULL_TREE)
10348 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
10349 s = fold_convert (size_type_node, s);
10350 tree purpose = size_int (map_idx++);
10351 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
10352 if (TREE_CODE (s) != INTEGER_CST)
10353 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
10355 unsigned char tkind = 0;
10356 switch (OMP_CLAUSE_CODE (c))
10358 case OMP_CLAUSE_MAP:
10359 tkind = OMP_CLAUSE_MAP_KIND (c);
10360 break;
10361 case OMP_CLAUSE_TO:
10362 tkind = OMP_CLAUSE_MAP_TO;
10363 break;
10364 case OMP_CLAUSE_FROM:
10365 tkind = OMP_CLAUSE_MAP_FROM;
10366 break;
10367 default:
10368 gcc_unreachable ();
10370 talign = ceil_log2 (talign);
10371 tkind |= talign << 3;
10372 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
10373 build_int_cst (unsigned_char_type_node,
10374 tkind));
10375 if (nc && nc != c)
10376 c = nc;
10379 gcc_assert (map_idx == map_cnt);
10381 DECL_INITIAL (TREE_VEC_ELT (t, 1))
10382 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
10383 DECL_INITIAL (TREE_VEC_ELT (t, 2))
10384 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
10385 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
10387 gimple_seq initlist = NULL;
10388 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
10389 TREE_VEC_ELT (t, 1)),
10390 &initlist, true, NULL_TREE);
10391 gimple_seq_add_seq (&ilist, initlist);
10393 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
10394 NULL);
10395 TREE_THIS_VOLATILE (clobber) = 1;
10396 gimple_seq_add_stmt (&olist,
10397 gimple_build_assign (TREE_VEC_ELT (t, 1),
10398 clobber));
10401 tree clobber = build_constructor (ctx->record_type, NULL);
10402 TREE_THIS_VOLATILE (clobber) = 1;
10403 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10404 clobber));
10407 /* Once all the expansions are done, sequence all the different
10408 fragments inside gimple_omp_body. */
10410 new_body = NULL;
10412 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
10414 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10415 /* fixup_child_record_type might have changed receiver_decl's type. */
10416 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10417 gimple_seq_add_stmt (&new_body,
10418 gimple_build_assign (ctx->receiver_decl, t));
10421 if (kind == GF_OMP_TARGET_KIND_REGION)
10423 gimple_seq_add_seq (&new_body, tgt_body);
10424 new_body = maybe_catch_exception (new_body);
10426 else if (kind == GF_OMP_TARGET_KIND_DATA)
10427 new_body = tgt_body;
10428 if (kind != GF_OMP_TARGET_KIND_UPDATE)
10430 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10431 gimple_omp_set_body (stmt, new_body);
10434 bind = gimple_build_bind (NULL, NULL,
10435 tgt_bind ? gimple_bind_block (tgt_bind)
10436 : NULL_TREE);
10437 gsi_replace (gsi_p, bind, true);
10438 gimple_bind_add_seq (bind, ilist);
10439 gimple_bind_add_stmt (bind, stmt);
10440 gimple_bind_add_seq (bind, olist);
10442 pop_gimplify_context (NULL);
10445 /* Expand code for an OpenMP teams directive. */
10447 static void
10448 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10450 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
10451 push_gimplify_context ();
10453 tree block = make_node (BLOCK);
10454 gbind *bind = gimple_build_bind (NULL, NULL, block);
10455 gsi_replace (gsi_p, bind, true);
10456 gimple_seq bind_body = NULL;
10457 gimple_seq dlist = NULL;
10458 gimple_seq olist = NULL;
10460 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10461 OMP_CLAUSE_NUM_TEAMS);
10462 if (num_teams == NULL_TREE)
10463 num_teams = build_int_cst (unsigned_type_node, 0);
10464 else
10466 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
10467 num_teams = fold_convert (unsigned_type_node, num_teams);
10468 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
10470 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10471 OMP_CLAUSE_THREAD_LIMIT);
10472 if (thread_limit == NULL_TREE)
10473 thread_limit = build_int_cst (unsigned_type_node, 0);
10474 else
10476 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10477 thread_limit = fold_convert (unsigned_type_node, thread_limit);
10478 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
10479 fb_rvalue);
10482 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
10483 &bind_body, &dlist, ctx, NULL);
10484 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
10485 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
10486 gimple_seq_add_stmt (&bind_body, teams_stmt);
10488 location_t loc = gimple_location (teams_stmt);
10489 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
10490 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10491 gimple_set_location (call, loc);
10492 gimple_seq_add_stmt (&bind_body, call);
10494 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10495 gimple_omp_set_body (teams_stmt, NULL);
10496 gimple_seq_add_seq (&bind_body, olist);
10497 gimple_seq_add_seq (&bind_body, dlist);
10498 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10499 gimple_bind_set_body (bind, bind_body);
10501 pop_gimplify_context (bind);
10503 gimple_bind_append_vars (bind, ctx->block_vars);
10504 BLOCK_VARS (block) = ctx->block_vars;
10505 if (BLOCK_VARS (block))
10506 TREE_USED (block) = 1;
10510 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10511 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10512 of OpenMP context, but with task_shared_vars set. */
10514 static tree
10515 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10516 void *data)
10518 tree t = *tp;
10520 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10521 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
10522 return t;
10524 if (task_shared_vars
10525 && DECL_P (t)
10526 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10527 return t;
10529 /* If a global variable has been privatized, TREE_CONSTANT on
10530 ADDR_EXPR might be wrong. */
10531 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10532 recompute_tree_invariant_for_addr_expr (t);
10534 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10535 return NULL_TREE;
10538 static void
10539 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10541 gimple stmt = gsi_stmt (*gsi_p);
10542 struct walk_stmt_info wi;
10543 gcall *call_stmt;
10545 if (gimple_has_location (stmt))
10546 input_location = gimple_location (stmt);
10548 if (task_shared_vars)
10549 memset (&wi, '\0', sizeof (wi));
10551 /* If we have issued syntax errors, avoid doing any heavy lifting.
10552 Just replace the OpenMP directives with a NOP to avoid
10553 confusing RTL expansion. */
10554 if (seen_error () && is_gimple_omp (stmt))
10556 gsi_replace (gsi_p, gimple_build_nop (), true);
10557 return;
10560 switch (gimple_code (stmt))
10562 case GIMPLE_COND:
10564 gcond *cond_stmt = as_a <gcond *> (stmt);
10565 if ((ctx || task_shared_vars)
10566 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
10567 lower_omp_regimplify_p,
10568 ctx ? NULL : &wi, NULL)
10569 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
10570 lower_omp_regimplify_p,
10571 ctx ? NULL : &wi, NULL)))
10572 gimple_regimplify_operands (cond_stmt, gsi_p);
10574 break;
10575 case GIMPLE_CATCH:
10576 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
10577 break;
10578 case GIMPLE_EH_FILTER:
10579 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10580 break;
10581 case GIMPLE_TRY:
10582 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10583 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10584 break;
10585 case GIMPLE_TRANSACTION:
10586 lower_omp (gimple_transaction_body_ptr (
10587 as_a <gtransaction *> (stmt)),
10588 ctx);
10589 break;
10590 case GIMPLE_BIND:
10591 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
10592 break;
10593 case GIMPLE_OMP_PARALLEL:
10594 case GIMPLE_OMP_TASK:
10595 ctx = maybe_lookup_ctx (stmt);
10596 gcc_assert (ctx);
10597 if (ctx->cancellable)
10598 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10599 lower_omp_taskreg (gsi_p, ctx);
10600 break;
10601 case GIMPLE_OMP_FOR:
10602 ctx = maybe_lookup_ctx (stmt);
10603 gcc_assert (ctx);
10604 if (ctx->cancellable)
10605 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10606 lower_omp_for (gsi_p, ctx);
10607 break;
10608 case GIMPLE_OMP_SECTIONS:
10609 ctx = maybe_lookup_ctx (stmt);
10610 gcc_assert (ctx);
10611 if (ctx->cancellable)
10612 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10613 lower_omp_sections (gsi_p, ctx);
10614 break;
10615 case GIMPLE_OMP_SINGLE:
10616 ctx = maybe_lookup_ctx (stmt);
10617 gcc_assert (ctx);
10618 lower_omp_single (gsi_p, ctx);
10619 break;
10620 case GIMPLE_OMP_MASTER:
10621 ctx = maybe_lookup_ctx (stmt);
10622 gcc_assert (ctx);
10623 lower_omp_master (gsi_p, ctx);
10624 break;
10625 case GIMPLE_OMP_TASKGROUP:
10626 ctx = maybe_lookup_ctx (stmt);
10627 gcc_assert (ctx);
10628 lower_omp_taskgroup (gsi_p, ctx);
10629 break;
10630 case GIMPLE_OMP_ORDERED:
10631 ctx = maybe_lookup_ctx (stmt);
10632 gcc_assert (ctx);
10633 lower_omp_ordered (gsi_p, ctx);
10634 break;
10635 case GIMPLE_OMP_CRITICAL:
10636 ctx = maybe_lookup_ctx (stmt);
10637 gcc_assert (ctx);
10638 lower_omp_critical (gsi_p, ctx);
10639 break;
10640 case GIMPLE_OMP_ATOMIC_LOAD:
10641 if ((ctx || task_shared_vars)
10642 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
10643 as_a <gomp_atomic_load *> (stmt)),
10644 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10645 gimple_regimplify_operands (stmt, gsi_p);
10646 break;
10647 case GIMPLE_OMP_TARGET:
10648 ctx = maybe_lookup_ctx (stmt);
10649 gcc_assert (ctx);
10650 lower_omp_target (gsi_p, ctx);
10651 break;
10652 case GIMPLE_OMP_TEAMS:
10653 ctx = maybe_lookup_ctx (stmt);
10654 gcc_assert (ctx);
10655 lower_omp_teams (gsi_p, ctx);
10656 break;
10657 case GIMPLE_CALL:
10658 tree fndecl;
10659 call_stmt = as_a <gcall *> (stmt);
10660 fndecl = gimple_call_fndecl (call_stmt);
10661 if (fndecl
10662 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10663 switch (DECL_FUNCTION_CODE (fndecl))
10665 case BUILT_IN_GOMP_BARRIER:
10666 if (ctx == NULL)
10667 break;
10668 /* FALLTHRU */
10669 case BUILT_IN_GOMP_CANCEL:
10670 case BUILT_IN_GOMP_CANCELLATION_POINT:
10671 omp_context *cctx;
10672 cctx = ctx;
10673 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10674 cctx = cctx->outer;
10675 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
10676 if (!cctx->cancellable)
10678 if (DECL_FUNCTION_CODE (fndecl)
10679 == BUILT_IN_GOMP_CANCELLATION_POINT)
10681 stmt = gimple_build_nop ();
10682 gsi_replace (gsi_p, stmt, false);
10684 break;
10686 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10688 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10689 gimple_call_set_fndecl (call_stmt, fndecl);
10690 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
10692 tree lhs;
10693 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
10694 gimple_call_set_lhs (call_stmt, lhs);
10695 tree fallthru_label;
10696 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10697 gimple g;
10698 g = gimple_build_label (fallthru_label);
10699 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10700 g = gimple_build_cond (NE_EXPR, lhs,
10701 fold_convert (TREE_TYPE (lhs),
10702 boolean_false_node),
10703 cctx->cancel_label, fallthru_label);
10704 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10705 break;
10706 default:
10707 break;
10709 /* FALLTHRU */
10710 default:
10711 if ((ctx || task_shared_vars)
10712 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10713 ctx ? NULL : &wi))
10715 /* Just remove clobbers, this should happen only if we have
10716 "privatized" local addressable variables in SIMD regions,
10717 the clobber isn't needed in that case and gimplifying address
10718 of the ARRAY_REF into a pointer and creating MEM_REF based
10719 clobber would create worse code than we get with the clobber
10720 dropped. */
10721 if (gimple_clobber_p (stmt))
10723 gsi_replace (gsi_p, gimple_build_nop (), true);
10724 break;
10726 gimple_regimplify_operands (stmt, gsi_p);
10728 break;
10732 static void
10733 lower_omp (gimple_seq *body, omp_context *ctx)
10735 location_t saved_location = input_location;
10736 gimple_stmt_iterator gsi;
10737 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10738 lower_omp_1 (&gsi, ctx);
10739 /* During gimplification, we have not always invoked fold_stmt
10740 (gimplify.c:maybe_fold_stmt); call it now. */
10741 if (target_nesting_level)
10742 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10743 fold_stmt (&gsi);
10744 input_location = saved_location;
10747 /* Main entry point. */
10749 static unsigned int
10750 execute_lower_omp (void)
10752 gimple_seq body;
10753 int i;
10754 omp_context *ctx;
10756 /* This pass always runs, to provide PROP_gimple_lomp.
10757 But there is nothing to do unless -fopenmp is given. */
10758 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10759 return 0;
10761 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10762 delete_omp_context);
10764 body = gimple_body (current_function_decl);
10765 scan_omp (&body, NULL);
10766 gcc_assert (taskreg_nesting_level == 0);
10767 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
10768 finish_taskreg_scan (ctx);
10769 taskreg_contexts.release ();
10771 if (all_contexts->root)
10773 if (task_shared_vars)
10774 push_gimplify_context ();
10775 lower_omp (&body, NULL);
10776 if (task_shared_vars)
10777 pop_gimplify_context (NULL);
10780 if (all_contexts)
10782 splay_tree_delete (all_contexts);
10783 all_contexts = NULL;
10785 BITMAP_FREE (task_shared_vars);
10786 return 0;
10789 namespace {
10791 const pass_data pass_data_lower_omp =
10793 GIMPLE_PASS, /* type */
10794 "omplower", /* name */
10795 OPTGROUP_NONE, /* optinfo_flags */
10796 TV_NONE, /* tv_id */
10797 PROP_gimple_any, /* properties_required */
10798 PROP_gimple_lomp, /* properties_provided */
10799 0, /* properties_destroyed */
10800 0, /* todo_flags_start */
10801 0, /* todo_flags_finish */
10804 class pass_lower_omp : public gimple_opt_pass
10806 public:
10807 pass_lower_omp (gcc::context *ctxt)
10808 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10811 /* opt_pass methods: */
10812 virtual unsigned int execute (function *) { return execute_lower_omp (); }
10814 }; // class pass_lower_omp
10816 } // anon namespace
10818 gimple_opt_pass *
10819 make_pass_lower_omp (gcc::context *ctxt)
10821 return new pass_lower_omp (ctxt);
10824 /* The following is a utility to diagnose OpenMP structured block violations.
10825 It is not part of the "omplower" pass, as that's invoked too late. It
10826 should be invoked by the respective front ends after gimplification. */
10828 static splay_tree all_labels;
10830 /* Check for mismatched contexts and generate an error if needed. Return
10831 true if an error is detected. */
10833 static bool
10834 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10835 gimple branch_ctx, gimple label_ctx)
10837 if (label_ctx == branch_ctx)
10838 return false;
10842 Previously we kept track of the label's entire context in diagnose_sb_[12]
10843 so we could traverse it and issue a correct "exit" or "enter" error
10844 message upon a structured block violation.
10846 We built the context by building a list with tree_cons'ing, but there is
10847 no easy counterpart in gimple tuples. It seems like far too much work
10848 for issuing exit/enter error messages. If someone really misses the
10849 distinct error message... patches welcome.
10852 #if 0
10853 /* Try to avoid confusing the user by producing and error message
10854 with correct "exit" or "enter" verbiage. We prefer "exit"
10855 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10856 if (branch_ctx == NULL)
10857 exit_p = false;
10858 else
10860 while (label_ctx)
10862 if (TREE_VALUE (label_ctx) == branch_ctx)
10864 exit_p = false;
10865 break;
10867 label_ctx = TREE_CHAIN (label_ctx);
10871 if (exit_p)
10872 error ("invalid exit from OpenMP structured block");
10873 else
10874 error ("invalid entry to OpenMP structured block");
10875 #endif
10877 bool cilkplus_block = false;
10878 if (flag_cilkplus)
10880 if ((branch_ctx
10881 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10882 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10883 || (label_ctx
10884 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10885 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10886 cilkplus_block = true;
10889 /* If it's obvious we have an invalid entry, be specific about the error. */
10890 if (branch_ctx == NULL)
10892 if (cilkplus_block)
10893 error ("invalid entry to Cilk Plus structured block");
10894 else
10895 error ("invalid entry to OpenMP structured block");
10897 else
10899 /* Otherwise, be vague and lazy, but efficient. */
10900 if (cilkplus_block)
10901 error ("invalid branch to/from a Cilk Plus structured block");
10902 else
10903 error ("invalid branch to/from an OpenMP structured block");
10906 gsi_replace (gsi_p, gimple_build_nop (), false);
10907 return true;
10910 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10911 where each label is found. */
10913 static tree
10914 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10915 struct walk_stmt_info *wi)
10917 gimple context = (gimple) wi->info;
10918 gimple inner_context;
10919 gimple stmt = gsi_stmt (*gsi_p);
10921 *handled_ops_p = true;
10923 switch (gimple_code (stmt))
10925 WALK_SUBSTMTS;
10927 case GIMPLE_OMP_PARALLEL:
10928 case GIMPLE_OMP_TASK:
10929 case GIMPLE_OMP_SECTIONS:
10930 case GIMPLE_OMP_SINGLE:
10931 case GIMPLE_OMP_SECTION:
10932 case GIMPLE_OMP_MASTER:
10933 case GIMPLE_OMP_ORDERED:
10934 case GIMPLE_OMP_CRITICAL:
10935 case GIMPLE_OMP_TARGET:
10936 case GIMPLE_OMP_TEAMS:
10937 case GIMPLE_OMP_TASKGROUP:
10938 /* The minimal context here is just the current OMP construct. */
10939 inner_context = stmt;
10940 wi->info = inner_context;
10941 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10942 wi->info = context;
10943 break;
10945 case GIMPLE_OMP_FOR:
10946 inner_context = stmt;
10947 wi->info = inner_context;
10948 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10949 walk them. */
10950 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10951 diagnose_sb_1, NULL, wi);
10952 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10953 wi->info = context;
10954 break;
10956 case GIMPLE_LABEL:
10957 splay_tree_insert (all_labels,
10958 (splay_tree_key) gimple_label_label (
10959 as_a <glabel *> (stmt)),
10960 (splay_tree_value) context);
10961 break;
10963 default:
10964 break;
10967 return NULL_TREE;
10970 /* Pass 2: Check each branch and see if its context differs from that of
10971 the destination label's context. */
10973 static tree
10974 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10975 struct walk_stmt_info *wi)
10977 gimple context = (gimple) wi->info;
10978 splay_tree_node n;
10979 gimple stmt = gsi_stmt (*gsi_p);
10981 *handled_ops_p = true;
10983 switch (gimple_code (stmt))
10985 WALK_SUBSTMTS;
10987 case GIMPLE_OMP_PARALLEL:
10988 case GIMPLE_OMP_TASK:
10989 case GIMPLE_OMP_SECTIONS:
10990 case GIMPLE_OMP_SINGLE:
10991 case GIMPLE_OMP_SECTION:
10992 case GIMPLE_OMP_MASTER:
10993 case GIMPLE_OMP_ORDERED:
10994 case GIMPLE_OMP_CRITICAL:
10995 case GIMPLE_OMP_TARGET:
10996 case GIMPLE_OMP_TEAMS:
10997 case GIMPLE_OMP_TASKGROUP:
10998 wi->info = stmt;
10999 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
11000 wi->info = context;
11001 break;
11003 case GIMPLE_OMP_FOR:
11004 wi->info = stmt;
11005 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
11006 walk them. */
11007 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
11008 diagnose_sb_2, NULL, wi);
11009 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
11010 wi->info = context;
11011 break;
11013 case GIMPLE_COND:
11015 gcond *cond_stmt = as_a <gcond *> (stmt);
11016 tree lab = gimple_cond_true_label (cond_stmt);
11017 if (lab)
11019 n = splay_tree_lookup (all_labels,
11020 (splay_tree_key) lab);
11021 diagnose_sb_0 (gsi_p, context,
11022 n ? (gimple) n->value : NULL);
11024 lab = gimple_cond_false_label (cond_stmt);
11025 if (lab)
11027 n = splay_tree_lookup (all_labels,
11028 (splay_tree_key) lab);
11029 diagnose_sb_0 (gsi_p, context,
11030 n ? (gimple) n->value : NULL);
11033 break;
11035 case GIMPLE_GOTO:
11037 tree lab = gimple_goto_dest (stmt);
11038 if (TREE_CODE (lab) != LABEL_DECL)
11039 break;
11041 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
11042 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
11044 break;
11046 case GIMPLE_SWITCH:
11048 gswitch *switch_stmt = as_a <gswitch *> (stmt);
11049 unsigned int i;
11050 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
11052 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
11053 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
11054 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
11055 break;
11058 break;
11060 case GIMPLE_RETURN:
11061 diagnose_sb_0 (gsi_p, context, NULL);
11062 break;
11064 default:
11065 break;
11068 return NULL_TREE;
11071 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
11072 codes. */
11073 bool
11074 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
11075 int *region_idx)
11077 gimple last = last_stmt (bb);
11078 enum gimple_code code = gimple_code (last);
11079 struct omp_region *cur_region = *region;
11080 bool fallthru = false;
11082 switch (code)
11084 case GIMPLE_OMP_PARALLEL:
11085 case GIMPLE_OMP_TASK:
11086 case GIMPLE_OMP_FOR:
11087 case GIMPLE_OMP_SINGLE:
11088 case GIMPLE_OMP_TEAMS:
11089 case GIMPLE_OMP_MASTER:
11090 case GIMPLE_OMP_TASKGROUP:
11091 case GIMPLE_OMP_ORDERED:
11092 case GIMPLE_OMP_CRITICAL:
11093 case GIMPLE_OMP_SECTION:
11094 cur_region = new_omp_region (bb, code, cur_region);
11095 fallthru = true;
11096 break;
11098 case GIMPLE_OMP_TARGET:
11099 cur_region = new_omp_region (bb, code, cur_region);
11100 fallthru = true;
11101 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
11102 cur_region = cur_region->outer;
11103 break;
11105 case GIMPLE_OMP_SECTIONS:
11106 cur_region = new_omp_region (bb, code, cur_region);
11107 fallthru = true;
11108 break;
11110 case GIMPLE_OMP_SECTIONS_SWITCH:
11111 fallthru = false;
11112 break;
11114 case GIMPLE_OMP_ATOMIC_LOAD:
11115 case GIMPLE_OMP_ATOMIC_STORE:
11116 fallthru = true;
11117 break;
11119 case GIMPLE_OMP_RETURN:
11120 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
11121 somewhere other than the next block. This will be
11122 created later. */
11123 cur_region->exit = bb;
11124 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
11125 cur_region = cur_region->outer;
11126 break;
11128 case GIMPLE_OMP_CONTINUE:
11129 cur_region->cont = bb;
11130 switch (cur_region->type)
11132 case GIMPLE_OMP_FOR:
11133 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11134 succs edges as abnormal to prevent splitting
11135 them. */
11136 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
11137 /* Make the loopback edge. */
11138 make_edge (bb, single_succ (cur_region->entry),
11139 EDGE_ABNORMAL);
11141 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11142 corresponds to the case that the body of the loop
11143 is not executed at all. */
11144 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
11145 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
11146 fallthru = false;
11147 break;
11149 case GIMPLE_OMP_SECTIONS:
11150 /* Wire up the edges into and out of the nested sections. */
11152 basic_block switch_bb = single_succ (cur_region->entry);
11154 struct omp_region *i;
11155 for (i = cur_region->inner; i ; i = i->next)
11157 gcc_assert (i->type == GIMPLE_OMP_SECTION);
11158 make_edge (switch_bb, i->entry, 0);
11159 make_edge (i->exit, bb, EDGE_FALLTHRU);
11162 /* Make the loopback edge to the block with
11163 GIMPLE_OMP_SECTIONS_SWITCH. */
11164 make_edge (bb, switch_bb, 0);
11166 /* Make the edge from the switch to exit. */
11167 make_edge (switch_bb, bb->next_bb, 0);
11168 fallthru = false;
11170 break;
11172 default:
11173 gcc_unreachable ();
11175 break;
11177 default:
11178 gcc_unreachable ();
11181 if (*region != cur_region)
11183 *region = cur_region;
11184 if (cur_region)
11185 *region_idx = cur_region->entry->index;
11186 else
11187 *region_idx = 0;
11190 return fallthru;
11193 static unsigned int
11194 diagnose_omp_structured_block_errors (void)
11196 struct walk_stmt_info wi;
11197 gimple_seq body = gimple_body (current_function_decl);
11199 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
11201 memset (&wi, 0, sizeof (wi));
11202 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
11204 memset (&wi, 0, sizeof (wi));
11205 wi.want_locations = true;
11206 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
11208 gimple_set_body (current_function_decl, body);
11210 splay_tree_delete (all_labels);
11211 all_labels = NULL;
11213 return 0;
11216 namespace {
11218 const pass_data pass_data_diagnose_omp_blocks =
11220 GIMPLE_PASS, /* type */
11221 "*diagnose_omp_blocks", /* name */
11222 OPTGROUP_NONE, /* optinfo_flags */
11223 TV_NONE, /* tv_id */
11224 PROP_gimple_any, /* properties_required */
11225 0, /* properties_provided */
11226 0, /* properties_destroyed */
11227 0, /* todo_flags_start */
11228 0, /* todo_flags_finish */
11231 class pass_diagnose_omp_blocks : public gimple_opt_pass
11233 public:
11234 pass_diagnose_omp_blocks (gcc::context *ctxt)
11235 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
11238 /* opt_pass methods: */
11239 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
11240 virtual unsigned int execute (function *)
11242 return diagnose_omp_structured_block_errors ();
11245 }; // class pass_diagnose_omp_blocks
11247 } // anon namespace
11249 gimple_opt_pass *
11250 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
11252 return new pass_diagnose_omp_blocks (ctxt);
11255 /* SIMD clone supporting code. */
11257 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11258 of arguments to reserve space for. */
11260 static struct cgraph_simd_clone *
11261 simd_clone_struct_alloc (int nargs)
11263 struct cgraph_simd_clone *clone_info;
11264 size_t len = (sizeof (struct cgraph_simd_clone)
11265 + nargs * sizeof (struct cgraph_simd_clone_arg));
11266 clone_info = (struct cgraph_simd_clone *)
11267 ggc_internal_cleared_alloc (len);
11268 return clone_info;
11271 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11273 static inline void
11274 simd_clone_struct_copy (struct cgraph_simd_clone *to,
11275 struct cgraph_simd_clone *from)
11277 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
11278 + ((from->nargs - from->inbranch)
11279 * sizeof (struct cgraph_simd_clone_arg))));
11282 /* Return vector of parameter types of function FNDECL. This uses
11283 TYPE_ARG_TYPES if available, otherwise falls back to types of
11284 DECL_ARGUMENTS types. */
11286 vec<tree>
11287 simd_clone_vector_of_formal_parm_types (tree fndecl)
11289 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
11290 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
11291 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
11292 unsigned int i;
11293 tree arg;
11294 FOR_EACH_VEC_ELT (args, i, arg)
11295 args[i] = TREE_TYPE (args[i]);
11296 return args;
11299 /* Given a simd function in NODE, extract the simd specific
11300 information from the OMP clauses passed in CLAUSES, and return
11301 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11302 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11303 otherwise set to FALSE. */
11305 static struct cgraph_simd_clone *
11306 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
11307 bool *inbranch_specified)
11309 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
11310 tree t;
11311 int n;
11312 *inbranch_specified = false;
11314 n = args.length ();
11315 if (n > 0 && args.last () == void_type_node)
11316 n--;
11318 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11319 be cloned have a distinctive artificial label in addition to "omp
11320 declare simd". */
11321 bool cilk_clone
11322 = (flag_cilkplus
11323 && lookup_attribute ("cilk simd function",
11324 DECL_ATTRIBUTES (node->decl)));
11326 /* Allocate one more than needed just in case this is an in-branch
11327 clone which will require a mask argument. */
11328 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
11329 clone_info->nargs = n;
11330 clone_info->cilk_elemental = cilk_clone;
11332 if (!clauses)
11334 args.release ();
11335 return clone_info;
11337 clauses = TREE_VALUE (clauses);
11338 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
11339 return clone_info;
11341 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
11343 switch (OMP_CLAUSE_CODE (t))
11345 case OMP_CLAUSE_INBRANCH:
11346 clone_info->inbranch = 1;
11347 *inbranch_specified = true;
11348 break;
11349 case OMP_CLAUSE_NOTINBRANCH:
11350 clone_info->inbranch = 0;
11351 *inbranch_specified = true;
11352 break;
11353 case OMP_CLAUSE_SIMDLEN:
11354 clone_info->simdlen
11355 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
11356 break;
11357 case OMP_CLAUSE_LINEAR:
11359 tree decl = OMP_CLAUSE_DECL (t);
11360 tree step = OMP_CLAUSE_LINEAR_STEP (t);
11361 int argno = TREE_INT_CST_LOW (decl);
11362 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
11364 clone_info->args[argno].arg_type
11365 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
11366 clone_info->args[argno].linear_step = tree_to_shwi (step);
11367 gcc_assert (clone_info->args[argno].linear_step >= 0
11368 && clone_info->args[argno].linear_step < n);
11370 else
11372 if (POINTER_TYPE_P (args[argno]))
11373 step = fold_convert (ssizetype, step);
11374 if (!tree_fits_shwi_p (step))
11376 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11377 "ignoring large linear step");
11378 args.release ();
11379 return NULL;
11381 else if (integer_zerop (step))
11383 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11384 "ignoring zero linear step");
11385 args.release ();
11386 return NULL;
11388 else
11390 clone_info->args[argno].arg_type
11391 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
11392 clone_info->args[argno].linear_step = tree_to_shwi (step);
11395 break;
11397 case OMP_CLAUSE_UNIFORM:
11399 tree decl = OMP_CLAUSE_DECL (t);
11400 int argno = tree_to_uhwi (decl);
11401 clone_info->args[argno].arg_type
11402 = SIMD_CLONE_ARG_TYPE_UNIFORM;
11403 break;
11405 case OMP_CLAUSE_ALIGNED:
11407 tree decl = OMP_CLAUSE_DECL (t);
11408 int argno = tree_to_uhwi (decl);
11409 clone_info->args[argno].alignment
11410 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
11411 break;
11413 default:
11414 break;
11417 args.release ();
11418 return clone_info;
11421 /* Given a SIMD clone in NODE, calculate the characteristic data
11422 type and return the coresponding type. The characteristic data
11423 type is computed as described in the Intel Vector ABI. */
11425 static tree
11426 simd_clone_compute_base_data_type (struct cgraph_node *node,
11427 struct cgraph_simd_clone *clone_info)
11429 tree type = integer_type_node;
11430 tree fndecl = node->decl;
11432 /* a) For non-void function, the characteristic data type is the
11433 return type. */
11434 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
11435 type = TREE_TYPE (TREE_TYPE (fndecl));
11437 /* b) If the function has any non-uniform, non-linear parameters,
11438 then the characteristic data type is the type of the first
11439 such parameter. */
11440 else
11442 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
11443 for (unsigned int i = 0; i < clone_info->nargs; ++i)
11444 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
11446 type = map[i];
11447 break;
11449 map.release ();
11452 /* c) If the characteristic data type determined by a) or b) above
11453 is struct, union, or class type which is pass-by-value (except
11454 for the type that maps to the built-in complex data type), the
11455 characteristic data type is int. */
11456 if (RECORD_OR_UNION_TYPE_P (type)
11457 && !aggregate_value_p (type, NULL)
11458 && TREE_CODE (type) != COMPLEX_TYPE)
11459 return integer_type_node;
11461 /* d) If none of the above three classes is applicable, the
11462 characteristic data type is int. */
11464 return type;
11466 /* e) For Intel Xeon Phi native and offload compilation, if the
11467 resulting characteristic data type is 8-bit or 16-bit integer
11468 data type, the characteristic data type is int. */
11469 /* Well, we don't handle Xeon Phi yet. */
11472 static tree
11473 simd_clone_mangle (struct cgraph_node *node,
11474 struct cgraph_simd_clone *clone_info)
11476 char vecsize_mangle = clone_info->vecsize_mangle;
11477 char mask = clone_info->inbranch ? 'M' : 'N';
11478 unsigned int simdlen = clone_info->simdlen;
11479 unsigned int n;
11480 pretty_printer pp;
11482 gcc_assert (vecsize_mangle && simdlen);
11484 pp_string (&pp, "_ZGV");
11485 pp_character (&pp, vecsize_mangle);
11486 pp_character (&pp, mask);
11487 pp_decimal_int (&pp, simdlen);
11489 for (n = 0; n < clone_info->nargs; ++n)
11491 struct cgraph_simd_clone_arg arg = clone_info->args[n];
11493 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
11494 pp_character (&pp, 'u');
11495 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11497 gcc_assert (arg.linear_step != 0);
11498 pp_character (&pp, 'l');
11499 if (arg.linear_step > 1)
11500 pp_unsigned_wide_integer (&pp, arg.linear_step);
11501 else if (arg.linear_step < 0)
11503 pp_character (&pp, 'n');
11504 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
11505 arg.linear_step));
11508 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11510 pp_character (&pp, 's');
11511 pp_unsigned_wide_integer (&pp, arg.linear_step);
11513 else
11514 pp_character (&pp, 'v');
11515 if (arg.alignment)
11517 pp_character (&pp, 'a');
11518 pp_decimal_int (&pp, arg.alignment);
11522 pp_underscore (&pp);
11523 pp_string (&pp,
11524 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11525 const char *str = pp_formatted_text (&pp);
11527 /* If there already is a SIMD clone with the same mangled name, don't
11528 add another one. This can happen e.g. for
11529 #pragma omp declare simd
11530 #pragma omp declare simd simdlen(8)
11531 int foo (int, int);
11532 if the simdlen is assumed to be 8 for the first one, etc. */
11533 for (struct cgraph_node *clone = node->simd_clones; clone;
11534 clone = clone->simdclone->next_clone)
11535 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11536 str) == 0)
11537 return NULL_TREE;
11539 return get_identifier (str);
11542 /* Create a simd clone of OLD_NODE and return it. */
11544 static struct cgraph_node *
11545 simd_clone_create (struct cgraph_node *old_node)
11547 struct cgraph_node *new_node;
11548 if (old_node->definition)
11550 if (!old_node->has_gimple_body_p ())
11551 return NULL;
11552 old_node->get_body ();
11553 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
11554 false, NULL, NULL,
11555 "simdclone");
11557 else
11559 tree old_decl = old_node->decl;
11560 tree new_decl = copy_node (old_node->decl);
11561 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11562 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11563 SET_DECL_RTL (new_decl, NULL);
11564 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11565 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11566 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
11567 symtab->call_cgraph_insertion_hooks (new_node);
11569 if (new_node == NULL)
11570 return new_node;
11572 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11574 /* The function cgraph_function_versioning () will force the new
11575 symbol local. Undo this, and inherit external visability from
11576 the old node. */
11577 new_node->local.local = old_node->local.local;
11578 new_node->externally_visible = old_node->externally_visible;
11580 return new_node;
11583 /* Adjust the return type of the given function to its appropriate
11584 vector counterpart. Returns a simd array to be used throughout the
11585 function as a return value. */
11587 static tree
11588 simd_clone_adjust_return_type (struct cgraph_node *node)
11590 tree fndecl = node->decl;
11591 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11592 unsigned int veclen;
11593 tree t;
11595 /* Adjust the function return type. */
11596 if (orig_rettype == void_type_node)
11597 return NULL_TREE;
11598 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11599 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11600 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11601 veclen = node->simdclone->vecsize_int;
11602 else
11603 veclen = node->simdclone->vecsize_float;
11604 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11605 if (veclen > node->simdclone->simdlen)
11606 veclen = node->simdclone->simdlen;
11607 if (veclen == node->simdclone->simdlen)
11608 TREE_TYPE (TREE_TYPE (fndecl))
11609 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11610 node->simdclone->simdlen);
11611 else
11613 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11614 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11615 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11617 if (!node->definition)
11618 return NULL_TREE;
11620 t = DECL_RESULT (fndecl);
11621 /* Adjust the DECL_RESULT. */
11622 gcc_assert (TREE_TYPE (t) != void_type_node);
11623 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11624 relayout_decl (t);
11626 tree atype = build_array_type_nelts (orig_rettype,
11627 node->simdclone->simdlen);
11628 if (veclen != node->simdclone->simdlen)
11629 return build1 (VIEW_CONVERT_EXPR, atype, t);
11631 /* Set up a SIMD array to use as the return value. */
11632 tree retval = create_tmp_var_raw (atype, "retval");
11633 gimple_add_tmp_var (retval);
11634 return retval;
11637 /* Each vector argument has a corresponding array to be used locally
11638 as part of the eventual loop. Create such temporary array and
11639 return it.
11641 PREFIX is the prefix to be used for the temporary.
11643 TYPE is the inner element type.
11645 SIMDLEN is the number of elements. */
11647 static tree
11648 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11650 tree atype = build_array_type_nelts (type, simdlen);
11651 tree avar = create_tmp_var_raw (atype, prefix);
11652 gimple_add_tmp_var (avar);
11653 return avar;
11656 /* Modify the function argument types to their corresponding vector
11657 counterparts if appropriate. Also, create one array for each simd
11658 argument to be used locally when using the function arguments as
11659 part of the loop.
11661 NODE is the function whose arguments are to be adjusted.
11663 Returns an adjustment vector that will be filled describing how the
11664 argument types will be adjusted. */
11666 static ipa_parm_adjustment_vec
11667 simd_clone_adjust_argument_types (struct cgraph_node *node)
11669 vec<tree> args;
11670 ipa_parm_adjustment_vec adjustments;
11672 if (node->definition)
11673 args = ipa_get_vector_of_formal_parms (node->decl);
11674 else
11675 args = simd_clone_vector_of_formal_parm_types (node->decl);
11676 adjustments.create (args.length ());
11677 unsigned i, j, veclen;
11678 struct ipa_parm_adjustment adj;
11679 for (i = 0; i < node->simdclone->nargs; ++i)
11681 memset (&adj, 0, sizeof (adj));
11682 tree parm = args[i];
11683 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11684 adj.base_index = i;
11685 adj.base = parm;
11687 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11688 node->simdclone->args[i].orig_type = parm_type;
11690 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11692 /* No adjustment necessary for scalar arguments. */
11693 adj.op = IPA_PARM_OP_COPY;
11695 else
11697 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11698 veclen = node->simdclone->vecsize_int;
11699 else
11700 veclen = node->simdclone->vecsize_float;
11701 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11702 if (veclen > node->simdclone->simdlen)
11703 veclen = node->simdclone->simdlen;
11704 adj.arg_prefix = "simd";
11705 adj.type = build_vector_type (parm_type, veclen);
11706 node->simdclone->args[i].vector_type = adj.type;
11707 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11709 adjustments.safe_push (adj);
11710 if (j == veclen)
11712 memset (&adj, 0, sizeof (adj));
11713 adj.op = IPA_PARM_OP_NEW;
11714 adj.arg_prefix = "simd";
11715 adj.base_index = i;
11716 adj.type = node->simdclone->args[i].vector_type;
11720 if (node->definition)
11721 node->simdclone->args[i].simd_array
11722 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11723 parm_type, node->simdclone->simdlen);
11725 adjustments.safe_push (adj);
11728 if (node->simdclone->inbranch)
11730 tree base_type
11731 = simd_clone_compute_base_data_type (node->simdclone->origin,
11732 node->simdclone);
11734 memset (&adj, 0, sizeof (adj));
11735 adj.op = IPA_PARM_OP_NEW;
11736 adj.arg_prefix = "mask";
11738 adj.base_index = i;
11739 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11740 veclen = node->simdclone->vecsize_int;
11741 else
11742 veclen = node->simdclone->vecsize_float;
11743 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11744 if (veclen > node->simdclone->simdlen)
11745 veclen = node->simdclone->simdlen;
11746 adj.type = build_vector_type (base_type, veclen);
11747 adjustments.safe_push (adj);
11749 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11750 adjustments.safe_push (adj);
11752 /* We have previously allocated one extra entry for the mask. Use
11753 it and fill it. */
11754 struct cgraph_simd_clone *sc = node->simdclone;
11755 sc->nargs++;
11756 if (node->definition)
11758 sc->args[i].orig_arg
11759 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11760 sc->args[i].simd_array
11761 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11763 sc->args[i].orig_type = base_type;
11764 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11767 if (node->definition)
11768 ipa_modify_formal_parameters (node->decl, adjustments);
11769 else
11771 tree new_arg_types = NULL_TREE, new_reversed;
11772 bool last_parm_void = false;
11773 if (args.length () > 0 && args.last () == void_type_node)
11774 last_parm_void = true;
11776 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11777 j = adjustments.length ();
11778 for (i = 0; i < j; i++)
11780 struct ipa_parm_adjustment *adj = &adjustments[i];
11781 tree ptype;
11782 if (adj->op == IPA_PARM_OP_COPY)
11783 ptype = args[adj->base_index];
11784 else
11785 ptype = adj->type;
11786 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11788 new_reversed = nreverse (new_arg_types);
11789 if (last_parm_void)
11791 if (new_reversed)
11792 TREE_CHAIN (new_arg_types) = void_list_node;
11793 else
11794 new_reversed = void_list_node;
11797 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11798 TYPE_ARG_TYPES (new_type) = new_reversed;
11799 TREE_TYPE (node->decl) = new_type;
11801 adjustments.release ();
11803 args.release ();
11804 return adjustments;
11807 /* Initialize and copy the function arguments in NODE to their
11808 corresponding local simd arrays. Returns a fresh gimple_seq with
11809 the instruction sequence generated. */
11811 static gimple_seq
11812 simd_clone_init_simd_arrays (struct cgraph_node *node,
11813 ipa_parm_adjustment_vec adjustments)
11815 gimple_seq seq = NULL;
11816 unsigned i = 0, j = 0, k;
11818 for (tree arg = DECL_ARGUMENTS (node->decl);
11819 arg;
11820 arg = DECL_CHAIN (arg), i++, j++)
11822 if (adjustments[j].op == IPA_PARM_OP_COPY)
11823 continue;
11825 node->simdclone->args[i].vector_arg = arg;
11827 tree array = node->simdclone->args[i].simd_array;
11828 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11830 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11831 tree ptr = build_fold_addr_expr (array);
11832 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11833 build_int_cst (ptype, 0));
11834 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11835 gimplify_and_add (t, &seq);
11837 else
11839 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11840 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11841 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11843 tree ptr = build_fold_addr_expr (array);
11844 int elemsize;
11845 if (k)
11847 arg = DECL_CHAIN (arg);
11848 j++;
11850 elemsize
11851 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11852 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11853 build_int_cst (ptype, k * elemsize));
11854 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11855 gimplify_and_add (t, &seq);
11859 return seq;
11862 /* Callback info for ipa_simd_modify_stmt_ops below. */
11864 struct modify_stmt_info {
11865 ipa_parm_adjustment_vec adjustments;
11866 gimple stmt;
11867 /* True if the parent statement was modified by
11868 ipa_simd_modify_stmt_ops. */
11869 bool modified;
11872 /* Callback for walk_gimple_op.
11874 Adjust operands from a given statement as specified in the
11875 adjustments vector in the callback data. */
11877 static tree
11878 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11880 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11881 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11882 tree *orig_tp = tp;
11883 if (TREE_CODE (*tp) == ADDR_EXPR)
11884 tp = &TREE_OPERAND (*tp, 0);
11885 struct ipa_parm_adjustment *cand = NULL;
11886 if (TREE_CODE (*tp) == PARM_DECL)
11887 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11888 else
11890 if (TYPE_P (*tp))
11891 *walk_subtrees = 0;
11894 tree repl = NULL_TREE;
11895 if (cand)
11896 repl = unshare_expr (cand->new_decl);
11897 else
11899 if (tp != orig_tp)
11901 *walk_subtrees = 0;
11902 bool modified = info->modified;
11903 info->modified = false;
11904 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11905 if (!info->modified)
11907 info->modified = modified;
11908 return NULL_TREE;
11910 info->modified = modified;
11911 repl = *tp;
11913 else
11914 return NULL_TREE;
11917 if (tp != orig_tp)
11919 repl = build_fold_addr_expr (repl);
11920 gimple stmt;
11921 if (is_gimple_debug (info->stmt))
11923 tree vexpr = make_node (DEBUG_EXPR_DECL);
11924 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
11925 DECL_ARTIFICIAL (vexpr) = 1;
11926 TREE_TYPE (vexpr) = TREE_TYPE (repl);
11927 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
11928 repl = vexpr;
11930 else
11932 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl),
11933 NULL), repl);
11934 repl = gimple_assign_lhs (stmt);
11936 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11937 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11938 *orig_tp = repl;
11940 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11942 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11943 *tp = vce;
11945 else
11946 *tp = repl;
11948 info->modified = true;
11949 return NULL_TREE;
11952 /* Traverse the function body and perform all modifications as
11953 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11954 modified such that the replacement/reduction value will now be an
11955 offset into the corresponding simd_array.
11957 This function will replace all function argument uses with their
11958 corresponding simd array elements, and ajust the return values
11959 accordingly. */
11961 static void
11962 ipa_simd_modify_function_body (struct cgraph_node *node,
11963 ipa_parm_adjustment_vec adjustments,
11964 tree retval_array, tree iter)
11966 basic_block bb;
11967 unsigned int i, j, l;
11969 /* Re-use the adjustments array, but this time use it to replace
11970 every function argument use to an offset into the corresponding
11971 simd_array. */
11972 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11974 if (!node->simdclone->args[i].vector_arg)
11975 continue;
11977 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11978 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11979 adjustments[j].new_decl
11980 = build4 (ARRAY_REF,
11981 basetype,
11982 node->simdclone->args[i].simd_array,
11983 iter,
11984 NULL_TREE, NULL_TREE);
11985 if (adjustments[j].op == IPA_PARM_OP_NONE
11986 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11987 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11990 l = adjustments.length ();
11991 for (i = 1; i < num_ssa_names; i++)
11993 tree name = ssa_name (i);
11994 if (name
11995 && SSA_NAME_VAR (name)
11996 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11998 for (j = 0; j < l; j++)
11999 if (SSA_NAME_VAR (name) == adjustments[j].base
12000 && adjustments[j].new_decl)
12002 tree base_var;
12003 if (adjustments[j].new_ssa_base == NULL_TREE)
12005 base_var
12006 = copy_var_decl (adjustments[j].base,
12007 DECL_NAME (adjustments[j].base),
12008 TREE_TYPE (adjustments[j].base));
12009 adjustments[j].new_ssa_base = base_var;
12011 else
12012 base_var = adjustments[j].new_ssa_base;
12013 if (SSA_NAME_IS_DEFAULT_DEF (name))
12015 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12016 gimple_stmt_iterator gsi = gsi_after_labels (bb);
12017 tree new_decl = unshare_expr (adjustments[j].new_decl);
12018 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
12019 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
12020 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
12021 gimple stmt = gimple_build_assign (name, new_decl);
12022 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
12024 else
12025 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
12030 struct modify_stmt_info info;
12031 info.adjustments = adjustments;
12033 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
12035 gimple_stmt_iterator gsi;
12037 gsi = gsi_start_bb (bb);
12038 while (!gsi_end_p (gsi))
12040 gimple stmt = gsi_stmt (gsi);
12041 info.stmt = stmt;
12042 struct walk_stmt_info wi;
12044 memset (&wi, 0, sizeof (wi));
12045 info.modified = false;
12046 wi.info = &info;
12047 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
12049 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
12051 tree retval = gimple_return_retval (return_stmt);
12052 if (!retval)
12054 gsi_remove (&gsi, true);
12055 continue;
12058 /* Replace `return foo' with `retval_array[iter] = foo'. */
12059 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
12060 retval_array, iter, NULL, NULL);
12061 stmt = gimple_build_assign (ref, retval);
12062 gsi_replace (&gsi, stmt, true);
12063 info.modified = true;
12066 if (info.modified)
12068 update_stmt (stmt);
12069 if (maybe_clean_eh_stmt (stmt))
12070 gimple_purge_dead_eh_edges (gimple_bb (stmt));
12072 gsi_next (&gsi);
12077 /* Adjust the argument types in NODE to their appropriate vector
12078 counterparts. */
12080 static void
12081 simd_clone_adjust (struct cgraph_node *node)
12083 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
12085 targetm.simd_clone.adjust (node);
12087 tree retval = simd_clone_adjust_return_type (node);
12088 ipa_parm_adjustment_vec adjustments
12089 = simd_clone_adjust_argument_types (node);
12091 push_gimplify_context ();
12093 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
12095 /* Adjust all uses of vector arguments accordingly. Adjust all
12096 return values accordingly. */
12097 tree iter = create_tmp_var (unsigned_type_node, "iter");
12098 tree iter1 = make_ssa_name (iter, NULL);
12099 tree iter2 = make_ssa_name (iter, NULL);
12100 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
12102 /* Initialize the iteration variable. */
12103 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12104 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
12105 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
12106 /* Insert the SIMD array and iv initialization at function
12107 entry. */
12108 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
12110 pop_gimplify_context (NULL);
12112 /* Create a new BB right before the original exit BB, to hold the
12113 iteration increment and the condition/branch. */
12114 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
12115 basic_block incr_bb = create_empty_bb (orig_exit);
12116 add_bb_to_loop (incr_bb, body_bb->loop_father);
12117 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
12118 flag. Set it now to be a FALLTHRU_EDGE. */
12119 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
12120 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
12121 for (unsigned i = 0;
12122 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
12124 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
12125 redirect_edge_succ (e, incr_bb);
12127 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
12128 e->probability = REG_BR_PROB_BASE;
12129 gsi = gsi_last_bb (incr_bb);
12130 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
12131 build_int_cst (unsigned_type_node,
12132 1));
12133 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12135 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12136 struct loop *loop = alloc_loop ();
12137 cfun->has_force_vectorize_loops = true;
12138 loop->safelen = node->simdclone->simdlen;
12139 loop->force_vectorize = true;
12140 loop->header = body_bb;
12142 /* Branch around the body if the mask applies. */
12143 if (node->simdclone->inbranch)
12145 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
12146 tree mask_array
12147 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
12148 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
12149 tree aref = build4 (ARRAY_REF,
12150 TREE_TYPE (TREE_TYPE (mask_array)),
12151 mask_array, iter1,
12152 NULL, NULL);
12153 g = gimple_build_assign (mask, aref);
12154 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12155 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
12156 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
12158 aref = build1 (VIEW_CONVERT_EXPR,
12159 build_nonstandard_integer_type (bitsize, 0), mask);
12160 mask = make_ssa_name (TREE_TYPE (aref), NULL);
12161 g = gimple_build_assign (mask, aref);
12162 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12165 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
12166 NULL, NULL);
12167 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12168 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
12169 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
12172 /* Generate the condition. */
12173 g = gimple_build_cond (LT_EXPR,
12174 iter2,
12175 build_int_cst (unsigned_type_node,
12176 node->simdclone->simdlen),
12177 NULL, NULL);
12178 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12179 e = split_block (incr_bb, gsi_stmt (gsi));
12180 basic_block latch_bb = e->dest;
12181 basic_block new_exit_bb;
12182 new_exit_bb = split_block (latch_bb, NULL)->dest;
12183 loop->latch = latch_bb;
12185 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
12187 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
12188 /* The successor of incr_bb is already pointing to latch_bb; just
12189 change the flags.
12190 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12191 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
12193 gphi *phi = create_phi_node (iter1, body_bb);
12194 edge preheader_edge = find_edge (entry_bb, body_bb);
12195 edge latch_edge = single_succ_edge (latch_bb);
12196 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
12197 UNKNOWN_LOCATION);
12198 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12200 /* Generate the new return. */
12201 gsi = gsi_last_bb (new_exit_bb);
12202 if (retval
12203 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
12204 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
12205 retval = TREE_OPERAND (retval, 0);
12206 else if (retval)
12208 retval = build1 (VIEW_CONVERT_EXPR,
12209 TREE_TYPE (TREE_TYPE (node->decl)),
12210 retval);
12211 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
12212 false, GSI_CONTINUE_LINKING);
12214 g = gimple_build_return (retval);
12215 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12217 /* Handle aligned clauses by replacing default defs of the aligned
12218 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12219 lhs. Handle linear by adding PHIs. */
12220 for (unsigned i = 0; i < node->simdclone->nargs; i++)
12221 if (node->simdclone->args[i].alignment
12222 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
12223 && (node->simdclone->args[i].alignment
12224 & (node->simdclone->args[i].alignment - 1)) == 0
12225 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
12226 == POINTER_TYPE)
12228 unsigned int alignment = node->simdclone->args[i].alignment;
12229 tree orig_arg = node->simdclone->args[i].orig_arg;
12230 tree def = ssa_default_def (cfun, orig_arg);
12231 if (def && !has_zero_uses (def))
12233 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
12234 gimple_seq seq = NULL;
12235 bool need_cvt = false;
12236 gcall *call
12237 = gimple_build_call (fn, 2, def, size_int (alignment));
12238 g = call;
12239 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
12240 ptr_type_node))
12241 need_cvt = true;
12242 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
12243 gimple_call_set_lhs (g, t);
12244 gimple_seq_add_stmt_without_update (&seq, g);
12245 if (need_cvt)
12247 t = make_ssa_name (orig_arg, NULL);
12248 g = gimple_build_assign_with_ops (NOP_EXPR, t,
12249 gimple_call_lhs (g),
12250 NULL_TREE);
12251 gimple_seq_add_stmt_without_update (&seq, g);
12253 gsi_insert_seq_on_edge_immediate
12254 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
12256 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12257 int freq = compute_call_stmt_bb_frequency (current_function_decl,
12258 entry_bb);
12259 node->create_edge (cgraph_node::get_create (fn),
12260 call, entry_bb->count, freq);
12262 imm_use_iterator iter;
12263 use_operand_p use_p;
12264 gimple use_stmt;
12265 tree repl = gimple_get_lhs (g);
12266 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12267 if (is_gimple_debug (use_stmt) || use_stmt == call)
12268 continue;
12269 else
12270 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12271 SET_USE (use_p, repl);
12274 else if (node->simdclone->args[i].arg_type
12275 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12277 tree orig_arg = node->simdclone->args[i].orig_arg;
12278 tree def = ssa_default_def (cfun, orig_arg);
12279 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12280 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
12281 if (def && !has_zero_uses (def))
12283 iter1 = make_ssa_name (orig_arg, NULL);
12284 iter2 = make_ssa_name (orig_arg, NULL);
12285 phi = create_phi_node (iter1, body_bb);
12286 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
12287 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12288 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12289 ? PLUS_EXPR : POINTER_PLUS_EXPR;
12290 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12291 ? TREE_TYPE (orig_arg) : sizetype;
12292 tree addcst
12293 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
12294 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
12295 gsi = gsi_last_bb (incr_bb);
12296 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12298 imm_use_iterator iter;
12299 use_operand_p use_p;
12300 gimple use_stmt;
12301 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12302 if (use_stmt == phi)
12303 continue;
12304 else
12305 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12306 SET_USE (use_p, iter1);
12310 calculate_dominance_info (CDI_DOMINATORS);
12311 add_loop (loop, loop->header->loop_father);
12312 update_ssa (TODO_update_ssa);
12314 pop_cfun ();
12317 /* If the function in NODE is tagged as an elemental SIMD function,
12318 create the appropriate SIMD clones. */
12320 static void
12321 expand_simd_clones (struct cgraph_node *node)
12323 tree attr = lookup_attribute ("omp declare simd",
12324 DECL_ATTRIBUTES (node->decl));
12325 if (attr == NULL_TREE
12326 || node->global.inlined_to
12327 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
12328 return;
12330 /* Ignore
12331 #pragma omp declare simd
12332 extern int foo ();
12333 in C, there we don't know the argument types at all. */
12334 if (!node->definition
12335 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
12336 return;
12340 /* Start with parsing the "omp declare simd" attribute(s). */
12341 bool inbranch_clause_specified;
12342 struct cgraph_simd_clone *clone_info
12343 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
12344 &inbranch_clause_specified);
12345 if (clone_info == NULL)
12346 continue;
12348 int orig_simdlen = clone_info->simdlen;
12349 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
12350 /* The target can return 0 (no simd clones should be created),
12351 1 (just one ISA of simd clones should be created) or higher
12352 count of ISA variants. In that case, clone_info is initialized
12353 for the first ISA variant. */
12354 int count
12355 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
12356 base_type, 0);
12357 if (count == 0)
12358 continue;
12360 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12361 also create one inbranch and one !inbranch clone of it. */
12362 for (int i = 0; i < count * 2; i++)
12364 struct cgraph_simd_clone *clone = clone_info;
12365 if (inbranch_clause_specified && (i & 1) != 0)
12366 continue;
12368 if (i != 0)
12370 clone = simd_clone_struct_alloc (clone_info->nargs
12371 + ((i & 1) != 0));
12372 simd_clone_struct_copy (clone, clone_info);
12373 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12374 and simd_clone_adjust_argument_types did to the first
12375 clone's info. */
12376 clone->nargs -= clone_info->inbranch;
12377 clone->simdlen = orig_simdlen;
12378 /* And call the target hook again to get the right ISA. */
12379 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
12380 base_type,
12381 i / 2);
12382 if ((i & 1) != 0)
12383 clone->inbranch = 1;
12386 /* simd_clone_mangle might fail if such a clone has been created
12387 already. */
12388 tree id = simd_clone_mangle (node, clone);
12389 if (id == NULL_TREE)
12390 continue;
12392 /* Only when we are sure we want to create the clone actually
12393 clone the function (or definitions) or create another
12394 extern FUNCTION_DECL (for prototypes without definitions). */
12395 struct cgraph_node *n = simd_clone_create (node);
12396 if (n == NULL)
12397 continue;
12399 n->simdclone = clone;
12400 clone->origin = node;
12401 clone->next_clone = NULL;
12402 if (node->simd_clones == NULL)
12404 clone->prev_clone = n;
12405 node->simd_clones = n;
12407 else
12409 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
12410 clone->prev_clone->simdclone->next_clone = n;
12411 node->simd_clones->simdclone->prev_clone = n;
12413 symtab->change_decl_assembler_name (n->decl, id);
12414 /* And finally adjust the return type, parameters and for
12415 definitions also function body. */
12416 if (node->definition)
12417 simd_clone_adjust (n);
12418 else
12420 simd_clone_adjust_return_type (n);
12421 simd_clone_adjust_argument_types (n);
12425 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
12428 /* Entry point for IPA simd clone creation pass. */
12430 static unsigned int
12431 ipa_omp_simd_clone (void)
12433 struct cgraph_node *node;
12434 FOR_EACH_FUNCTION (node)
12435 expand_simd_clones (node);
12436 return 0;
12439 namespace {
12441 const pass_data pass_data_omp_simd_clone =
12443 SIMPLE_IPA_PASS, /* type */
12444 "simdclone", /* name */
12445 OPTGROUP_NONE, /* optinfo_flags */
12446 TV_NONE, /* tv_id */
12447 ( PROP_ssa | PROP_cfg ), /* properties_required */
12448 0, /* properties_provided */
12449 0, /* properties_destroyed */
12450 0, /* todo_flags_start */
12451 0, /* todo_flags_finish */
12454 class pass_omp_simd_clone : public simple_ipa_opt_pass
12456 public:
12457 pass_omp_simd_clone(gcc::context *ctxt)
12458 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
12461 /* opt_pass methods: */
12462 virtual bool gate (function *);
12463 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
12466 bool
12467 pass_omp_simd_clone::gate (function *)
12469 return ((flag_openmp || flag_openmp_simd
12470 || flag_cilkplus
12471 || (in_lto_p && !flag_wpa))
12472 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
12475 } // anon namespace
12477 simple_ipa_opt_pass *
12478 make_pass_omp_simd_clone (gcc::context *ctxt)
12480 return new pass_omp_simd_clone (ctxt);
12483 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
12484 adds their addresses and sizes to constructor-vector V_CTOR. */
12485 static void
12486 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
12487 vec<constructor_elt, va_gc> *v_ctor)
12489 unsigned len = vec_safe_length (v_decls);
12490 for (unsigned i = 0; i < len; i++)
12492 tree it = (*v_decls)[i];
12493 bool is_function = TREE_CODE (it) != VAR_DECL;
12495 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
12496 if (!is_function)
12497 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
12498 fold_convert (const_ptr_type_node,
12499 DECL_SIZE_UNIT (it)));
12503 /* Create new symbols containing (address, size) pairs for global variables,
12504 marked with "omp declare target" attribute, as well as addresses for the
12505 functions, which are outlined target regions. */
12506 void
12507 omp_finish_file (void)
12509 unsigned num_funcs = vec_safe_length (offload_funcs);
12510 unsigned num_vars = vec_safe_length (offload_vars);
12512 if (num_funcs == 0 && num_vars == 0)
12513 return;
12515 if (targetm_common.have_named_sections)
12517 vec<constructor_elt, va_gc> *v_f, *v_v;
12518 vec_alloc (v_f, num_funcs);
12519 vec_alloc (v_v, num_vars * 2);
12521 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
12522 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
12524 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
12525 num_vars * 2);
12526 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
12527 num_funcs);
12528 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
12529 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
12530 tree ctor_v = build_constructor (vars_decl_type, v_v);
12531 tree ctor_f = build_constructor (funcs_decl_type, v_f);
12532 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
12533 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
12534 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
12535 get_identifier (".offload_func_table"),
12536 funcs_decl_type);
12537 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
12538 get_identifier (".offload_var_table"),
12539 vars_decl_type);
12540 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
12541 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
12542 otherwise a joint table in a binary will contain padding between
12543 tables from multiple object files. */
12544 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
12545 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
12546 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
12547 DECL_INITIAL (funcs_decl) = ctor_f;
12548 DECL_INITIAL (vars_decl) = ctor_v;
12549 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
12550 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
12552 varpool_node::finalize_decl (vars_decl);
12553 varpool_node::finalize_decl (funcs_decl);
12555 else
12557 for (unsigned i = 0; i < num_funcs; i++)
12559 tree it = (*offload_funcs)[i];
12560 targetm.record_offload_symbol (it);
12562 for (unsigned i = 0; i < num_vars; i++)
12564 tree it = (*offload_vars)[i];
12565 targetm.record_offload_symbol (it);
12570 #include "gt-omp-low.h"