Continue implementation of OpenACC loop construct.
[official-gcc.git] / gcc / omp-low.c
blob13373ca410425e6a6511e67eecaecc1809f6d04c
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005-2014 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "stringpool.h"
30 #include "stor-layout.h"
31 #include "rtl.h"
32 #include "pointer-set.h"
33 #include "basic-block.h"
34 #include "tree-ssa-alias.h"
35 #include "internal-fn.h"
36 #include "gimple-fold.h"
37 #include "gimple-expr.h"
38 #include "is-a.h"
39 #include "gimple.h"
40 #include "gimplify.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "gimple-walk.h"
44 #include "tree-iterator.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47 #include "diagnostic-core.h"
48 #include "gimple-ssa.h"
49 #include "cgraph.h"
50 #include "tree-cfg.h"
51 #include "tree-phinodes.h"
52 #include "ssa-iterators.h"
53 #include "tree-ssanames.h"
54 #include "tree-into-ssa.h"
55 #include "expr.h"
56 #include "tree-dfa.h"
57 #include "tree-ssa.h"
58 #include "flags.h"
59 #include "function.h"
60 #include "expr.h"
61 #include "tree-pass.h"
62 #include "except.h"
63 #include "splay-tree.h"
64 #include "optabs.h"
65 #include "cfgloop.h"
66 #include "target.h"
67 #include "omp-low.h"
68 #include "gimple-low.h"
69 #include "tree-cfgcleanup.h"
70 #include "pretty-print.h"
71 #include "ipa-prop.h"
72 #include "tree-nested.h"
73 #include "tree-eh.h"
76 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
77 phases. The first phase scans the function looking for OMP statements
78 and then for variables that must be replaced to satisfy data sharing
79 clauses. The second phase expands code for the constructs, as well as
80 re-gimplifying things when variables have been replaced with complex
81 expressions.
83 Final code generation is done by pass_expand_omp. The flowgraph is
84 scanned for parallel regions which are then moved to a new
85 function, to be invoked by the thread library. */
87 /* Parallel region information. Every parallel and workshare
88 directive is enclosed between two markers, the OMP_* directive
89 and a corresponding OMP_RETURN statement. */
91 struct omp_region
93 /* The enclosing region. */
94 struct omp_region *outer;
96 /* First child region. */
97 struct omp_region *inner;
99 /* Next peer region. */
100 struct omp_region *next;
102 /* Block containing the omp directive as its last stmt. */
103 basic_block entry;
105 /* Block containing the OMP_RETURN as its last stmt. */
106 basic_block exit;
108 /* Block containing the OMP_CONTINUE as its last stmt. */
109 basic_block cont;
111 /* If this is a combined parallel+workshare region, this is a list
112 of additional arguments needed by the combined parallel+workshare
113 library call. */
114 vec<tree, va_gc> *ws_args;
116 /* The code for the omp directive of this region. */
117 enum gimple_code type;
119 /* Schedule kind, only used for OMP_FOR type regions. */
120 enum omp_clause_schedule_kind sched_kind;
122 /* True if this is a combined parallel+workshare region. */
123 bool is_combined_parallel;
126 /* Context structure. Used to store information about each parallel
127 directive in the code. */
129 typedef struct omp_context
131 /* This field must be at the beginning, as we do "inheritance": Some
132 callback functions for tree-inline.c (e.g., omp_copy_decl)
133 receive a copy_body_data pointer that is up-casted to an
134 omp_context pointer. */
135 copy_body_data cb;
137 /* The tree of contexts corresponding to the encountered constructs. */
138 struct omp_context *outer;
139 gimple stmt;
141 /* Map variables to fields in a structure that allows communication
142 between sending and receiving threads. */
143 splay_tree field_map;
144 tree record_type;
145 tree sender_decl;
146 tree receiver_decl;
148 /* These are used just by task contexts, if task firstprivate fn is
149 needed. srecord_type is used to communicate from the thread
150 that encountered the task construct to task firstprivate fn,
151 record_type is allocated by GOMP_task, initialized by task firstprivate
152 fn and passed to the task body fn. */
153 splay_tree sfield_map;
154 tree srecord_type;
156 /* A chain of variables to add to the top-level block surrounding the
157 construct. In the case of a parallel, this is in the child function. */
158 tree block_vars;
160 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
161 barriers should jump to during omplower pass. */
162 tree cancel_label;
164 /* What to do with variables with implicitly determined sharing
165 attributes. */
166 enum omp_clause_default_kind default_kind;
168 /* Nesting depth of this context. Used to beautify error messages re
169 invalid gotos. The outermost ctx is depth 1, with depth 0 being
170 reserved for the main body of the function. */
171 int depth;
173 /* True if this parallel directive is nested within another. */
174 bool is_nested;
176 /* True if this construct can be cancelled. */
177 bool cancellable;
178 } omp_context;
180 /* A structure holding the elements of:
181 for (V = N1; V cond N2; V += STEP) [...] */
183 struct omp_for_data_loop
185 tree v, n1, n2, step;
186 enum tree_code cond_code;
189 /* A structure describing the main elements of a parallel loop. */
191 struct omp_for_data
193 struct omp_for_data_loop loop;
194 tree chunk_size;
195 gimple for_stmt;
196 tree pre, iter_type;
197 int collapse;
198 bool have_nowait, have_ordered;
199 enum omp_clause_schedule_kind sched_kind;
200 struct omp_for_data_loop *loops;
204 static splay_tree all_contexts;
205 static int taskreg_nesting_level;
206 static int target_nesting_level;
207 static struct omp_region *root_omp_region;
208 static bitmap task_shared_vars;
210 static void scan_omp (gimple_seq *, omp_context *);
211 static tree scan_omp_1_op (tree *, int *, void *);
213 #define WALK_SUBSTMTS \
214 case GIMPLE_BIND: \
215 case GIMPLE_TRY: \
216 case GIMPLE_CATCH: \
217 case GIMPLE_EH_FILTER: \
218 case GIMPLE_TRANSACTION: \
219 /* The sub-statements for these should be walked. */ \
220 *handled_ops_p = false; \
221 break;
223 /* Convenience function for calling scan_omp_1_op on tree operands. */
225 static inline tree
226 scan_omp_op (tree *tp, omp_context *ctx)
228 struct walk_stmt_info wi;
230 memset (&wi, 0, sizeof (wi));
231 wi.info = ctx;
232 wi.want_locations = true;
234 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
237 static void lower_omp (gimple_seq *, omp_context *);
238 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
239 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
241 /* Find an OpenMP clause of type KIND within CLAUSES. */
243 tree
244 find_omp_clause (tree clauses, enum omp_clause_code kind)
246 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
247 if (OMP_CLAUSE_CODE (clauses) == kind)
248 return clauses;
250 return NULL_TREE;
253 /* Return true if CTX is for an omp parallel. */
255 static inline bool
256 is_parallel_ctx (omp_context *ctx)
258 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
262 /* Return true if CTX is for an omp task. */
264 static inline bool
265 is_task_ctx (omp_context *ctx)
267 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
271 /* Return true if CTX is for an omp parallel or omp task. */
273 static inline bool
274 is_taskreg_ctx (omp_context *ctx)
276 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
277 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
281 /* Return true if REGION is a combined parallel+workshare region. */
283 static inline bool
284 is_combined_parallel (struct omp_region *region)
286 return region->is_combined_parallel;
290 /* Extract the header elements of parallel loop FOR_STMT and store
291 them into *FD. */
293 static void
294 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
295 struct omp_for_data_loop *loops)
297 tree t, var, *collapse_iter, *collapse_count;
298 tree count = NULL_TREE, iter_type = long_integer_type_node;
299 struct omp_for_data_loop *loop;
300 int i;
301 struct omp_for_data_loop dummy_loop;
302 location_t loc = gimple_location (for_stmt);
303 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
304 bool distribute = gimple_omp_for_kind (for_stmt)
305 == GF_OMP_FOR_KIND_DISTRIBUTE;
307 fd->for_stmt = for_stmt;
308 fd->pre = NULL;
309 fd->collapse = gimple_omp_for_collapse (for_stmt);
310 if (fd->collapse > 1)
311 fd->loops = loops;
312 else
313 fd->loops = &fd->loop;
315 fd->have_nowait = (gimple_omp_for_kind (for_stmt) != GF_OMP_FOR_KIND_FOR);
316 fd->have_ordered = false;
317 fd->sched_kind = /* TODO: OACC_LOOP */ OMP_CLAUSE_SCHEDULE_STATIC;
318 fd->chunk_size = NULL_TREE;
319 collapse_iter = NULL;
320 collapse_count = NULL;
322 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
323 switch (OMP_CLAUSE_CODE (t))
325 case OMP_CLAUSE_NOWAIT:
326 fd->have_nowait = true;
327 break;
328 case OMP_CLAUSE_ORDERED:
329 fd->have_ordered = true;
330 break;
331 case OMP_CLAUSE_SCHEDULE:
332 gcc_assert (!distribute);
333 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
334 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
335 break;
336 case OMP_CLAUSE_DIST_SCHEDULE:
337 gcc_assert (distribute);
338 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
339 break;
340 case OMP_CLAUSE_COLLAPSE:
341 if (fd->collapse > 1)
343 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
344 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
346 default:
347 break;
350 /* FIXME: for now map schedule(auto) to schedule(static).
351 There should be analysis to determine whether all iterations
352 are approximately the same amount of work (then schedule(static)
353 is best) or if it varies (then schedule(dynamic,N) is better). */
354 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
356 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
357 gcc_assert (fd->chunk_size == NULL);
359 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
360 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
361 gcc_assert (fd->chunk_size == NULL);
362 else if (fd->chunk_size == NULL)
364 /* We only need to compute a default chunk size for ordered
365 static loops and dynamic loops. */
366 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
367 || fd->have_ordered)
368 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
369 ? integer_zero_node : integer_one_node;
372 for (i = 0; i < fd->collapse; i++)
374 if (fd->collapse == 1)
375 loop = &fd->loop;
376 else if (loops != NULL)
377 loop = loops + i;
378 else
379 loop = &dummy_loop;
381 loop->v = gimple_omp_for_index (for_stmt, i);
382 gcc_assert (SSA_VAR_P (loop->v));
383 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
384 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
385 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
386 loop->n1 = gimple_omp_for_initial (for_stmt, i);
388 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
389 loop->n2 = gimple_omp_for_final (for_stmt, i);
390 switch (loop->cond_code)
392 case LT_EXPR:
393 case GT_EXPR:
394 break;
395 case NE_EXPR:
396 gcc_assert (gimple_omp_for_kind (for_stmt)
397 == GF_OMP_FOR_KIND_CILKSIMD);
398 break;
399 case LE_EXPR:
400 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
401 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
402 else
403 loop->n2 = fold_build2_loc (loc,
404 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
405 build_int_cst (TREE_TYPE (loop->n2), 1));
406 loop->cond_code = LT_EXPR;
407 break;
408 case GE_EXPR:
409 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
410 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
411 else
412 loop->n2 = fold_build2_loc (loc,
413 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
414 build_int_cst (TREE_TYPE (loop->n2), 1));
415 loop->cond_code = GT_EXPR;
416 break;
417 default:
418 gcc_unreachable ();
421 t = gimple_omp_for_incr (for_stmt, i);
422 gcc_assert (TREE_OPERAND (t, 0) == var);
423 switch (TREE_CODE (t))
425 case PLUS_EXPR:
426 loop->step = TREE_OPERAND (t, 1);
427 break;
428 case POINTER_PLUS_EXPR:
429 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
430 break;
431 case MINUS_EXPR:
432 loop->step = TREE_OPERAND (t, 1);
433 loop->step = fold_build1_loc (loc,
434 NEGATE_EXPR, TREE_TYPE (loop->step),
435 loop->step);
436 break;
437 default:
438 gcc_unreachable ();
441 if (simd
442 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
443 && !fd->have_ordered))
445 if (fd->collapse == 1)
446 iter_type = TREE_TYPE (loop->v);
447 else if (i == 0
448 || TYPE_PRECISION (iter_type)
449 < TYPE_PRECISION (TREE_TYPE (loop->v)))
450 iter_type
451 = build_nonstandard_integer_type
452 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
454 else if (iter_type != long_long_unsigned_type_node)
456 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
457 iter_type = long_long_unsigned_type_node;
458 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
459 && TYPE_PRECISION (TREE_TYPE (loop->v))
460 >= TYPE_PRECISION (iter_type))
462 tree n;
464 if (loop->cond_code == LT_EXPR)
465 n = fold_build2_loc (loc,
466 PLUS_EXPR, TREE_TYPE (loop->v),
467 loop->n2, loop->step);
468 else
469 n = loop->n1;
470 if (TREE_CODE (n) != INTEGER_CST
471 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
472 iter_type = long_long_unsigned_type_node;
474 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
475 > TYPE_PRECISION (iter_type))
477 tree n1, n2;
479 if (loop->cond_code == LT_EXPR)
481 n1 = loop->n1;
482 n2 = fold_build2_loc (loc,
483 PLUS_EXPR, TREE_TYPE (loop->v),
484 loop->n2, loop->step);
486 else
488 n1 = fold_build2_loc (loc,
489 MINUS_EXPR, TREE_TYPE (loop->v),
490 loop->n2, loop->step);
491 n2 = loop->n1;
493 if (TREE_CODE (n1) != INTEGER_CST
494 || TREE_CODE (n2) != INTEGER_CST
495 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
496 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
497 iter_type = long_long_unsigned_type_node;
501 if (collapse_count && *collapse_count == NULL)
503 t = fold_binary (loop->cond_code, boolean_type_node,
504 fold_convert (TREE_TYPE (loop->v), loop->n1),
505 fold_convert (TREE_TYPE (loop->v), loop->n2));
506 if (t && integer_zerop (t))
507 count = build_zero_cst (long_long_unsigned_type_node);
508 else if ((i == 0 || count != NULL_TREE)
509 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
510 && TREE_CONSTANT (loop->n1)
511 && TREE_CONSTANT (loop->n2)
512 && TREE_CODE (loop->step) == INTEGER_CST)
514 tree itype = TREE_TYPE (loop->v);
516 if (POINTER_TYPE_P (itype))
517 itype = signed_type_for (itype);
518 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
519 t = fold_build2_loc (loc,
520 PLUS_EXPR, itype,
521 fold_convert_loc (loc, itype, loop->step), t);
522 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
523 fold_convert_loc (loc, itype, loop->n2));
524 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
525 fold_convert_loc (loc, itype, loop->n1));
526 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
527 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
528 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
529 fold_build1_loc (loc, NEGATE_EXPR, itype,
530 fold_convert_loc (loc, itype,
531 loop->step)));
532 else
533 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
534 fold_convert_loc (loc, itype, loop->step));
535 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
536 if (count != NULL_TREE)
537 count = fold_build2_loc (loc,
538 MULT_EXPR, long_long_unsigned_type_node,
539 count, t);
540 else
541 count = t;
542 if (TREE_CODE (count) != INTEGER_CST)
543 count = NULL_TREE;
545 else if (count && !integer_zerop (count))
546 count = NULL_TREE;
550 if (count
551 && !simd
552 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
553 || fd->have_ordered))
555 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
556 iter_type = long_long_unsigned_type_node;
557 else
558 iter_type = long_integer_type_node;
560 else if (collapse_iter && *collapse_iter != NULL)
561 iter_type = TREE_TYPE (*collapse_iter);
562 fd->iter_type = iter_type;
563 if (collapse_iter && *collapse_iter == NULL)
564 *collapse_iter = create_tmp_var (iter_type, ".iter");
565 if (collapse_count && *collapse_count == NULL)
567 if (count)
568 *collapse_count = fold_convert_loc (loc, iter_type, count);
569 else
570 *collapse_count = create_tmp_var (iter_type, ".count");
573 if (fd->collapse > 1)
575 fd->loop.v = *collapse_iter;
576 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
577 fd->loop.n2 = *collapse_count;
578 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
579 fd->loop.cond_code = LT_EXPR;
584 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
585 is the immediate dominator of PAR_ENTRY_BB, return true if there
586 are no data dependencies that would prevent expanding the parallel
587 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
589 When expanding a combined parallel+workshare region, the call to
590 the child function may need additional arguments in the case of
591 GIMPLE_OMP_FOR regions. In some cases, these arguments are
592 computed out of variables passed in from the parent to the child
593 via 'struct .omp_data_s'. For instance:
595 #pragma omp parallel for schedule (guided, i * 4)
596 for (j ...)
598 Is lowered into:
600 # BLOCK 2 (PAR_ENTRY_BB)
601 .omp_data_o.i = i;
602 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
604 # BLOCK 3 (WS_ENTRY_BB)
605 .omp_data_i = &.omp_data_o;
606 D.1667 = .omp_data_i->i;
607 D.1598 = D.1667 * 4;
608 #pragma omp for schedule (guided, D.1598)
610 When we outline the parallel region, the call to the child function
611 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
612 that value is computed *after* the call site. So, in principle we
613 cannot do the transformation.
615 To see whether the code in WS_ENTRY_BB blocks the combined
616 parallel+workshare call, we collect all the variables used in the
617 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
618 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
619 call.
621 FIXME. If we had the SSA form built at this point, we could merely
622 hoist the code in block 3 into block 2 and be done with it. But at
623 this point we don't have dataflow information and though we could
624 hack something up here, it is really not worth the aggravation. */
626 static bool
627 workshare_safe_to_combine_p (basic_block ws_entry_bb)
629 struct omp_for_data fd;
630 gimple ws_stmt = last_stmt (ws_entry_bb);
632 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
633 return true;
635 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
637 extract_omp_for_data (ws_stmt, &fd, NULL);
639 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
640 return false;
641 if (fd.iter_type != long_integer_type_node)
642 return false;
644 /* FIXME. We give up too easily here. If any of these arguments
645 are not constants, they will likely involve variables that have
646 been mapped into fields of .omp_data_s for sharing with the child
647 function. With appropriate data flow, it would be possible to
648 see through this. */
649 if (!is_gimple_min_invariant (fd.loop.n1)
650 || !is_gimple_min_invariant (fd.loop.n2)
651 || !is_gimple_min_invariant (fd.loop.step)
652 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
653 return false;
655 return true;
659 /* Collect additional arguments needed to emit a combined
660 parallel+workshare call. WS_STMT is the workshare directive being
661 expanded. */
663 static vec<tree, va_gc> *
664 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
666 tree t;
667 location_t loc = gimple_location (ws_stmt);
668 vec<tree, va_gc> *ws_args;
670 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
672 struct omp_for_data fd;
673 tree n1, n2;
675 extract_omp_for_data (ws_stmt, &fd, NULL);
676 n1 = fd.loop.n1;
677 n2 = fd.loop.n2;
679 if (gimple_omp_for_combined_into_p (ws_stmt))
681 tree innerc
682 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
683 OMP_CLAUSE__LOOPTEMP_);
684 gcc_assert (innerc);
685 n1 = OMP_CLAUSE_DECL (innerc);
686 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
687 OMP_CLAUSE__LOOPTEMP_);
688 gcc_assert (innerc);
689 n2 = OMP_CLAUSE_DECL (innerc);
692 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
694 t = fold_convert_loc (loc, long_integer_type_node, n1);
695 ws_args->quick_push (t);
697 t = fold_convert_loc (loc, long_integer_type_node, n2);
698 ws_args->quick_push (t);
700 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
701 ws_args->quick_push (t);
703 if (fd.chunk_size)
705 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
706 ws_args->quick_push (t);
709 return ws_args;
711 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
713 /* Number of sections is equal to the number of edges from the
714 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
715 the exit of the sections region. */
716 basic_block bb = single_succ (gimple_bb (ws_stmt));
717 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
718 vec_alloc (ws_args, 1);
719 ws_args->quick_push (t);
720 return ws_args;
723 gcc_unreachable ();
727 /* Discover whether REGION is a combined parallel+workshare region. */
729 static void
730 determine_parallel_type (struct omp_region *region)
732 basic_block par_entry_bb, par_exit_bb;
733 basic_block ws_entry_bb, ws_exit_bb;
735 if (region == NULL || region->inner == NULL
736 || region->exit == NULL || region->inner->exit == NULL
737 || region->inner->cont == NULL)
738 return;
740 /* We only support parallel+for and parallel+sections. */
741 if (region->type != GIMPLE_OMP_PARALLEL
742 || (region->inner->type != GIMPLE_OMP_FOR
743 && region->inner->type != GIMPLE_OMP_SECTIONS))
744 return;
746 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
747 WS_EXIT_BB -> PAR_EXIT_BB. */
748 par_entry_bb = region->entry;
749 par_exit_bb = region->exit;
750 ws_entry_bb = region->inner->entry;
751 ws_exit_bb = region->inner->exit;
753 if (single_succ (par_entry_bb) == ws_entry_bb
754 && single_succ (ws_exit_bb) == par_exit_bb
755 && workshare_safe_to_combine_p (ws_entry_bb)
756 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
757 || (last_and_only_stmt (ws_entry_bb)
758 && last_and_only_stmt (par_exit_bb))))
760 gimple par_stmt = last_stmt (par_entry_bb);
761 gimple ws_stmt = last_stmt (ws_entry_bb);
763 if (region->inner->type == GIMPLE_OMP_FOR)
765 /* If this is a combined parallel loop, we need to determine
766 whether or not to use the combined library calls. There
767 are two cases where we do not apply the transformation:
768 static loops and any kind of ordered loop. In the first
769 case, we already open code the loop so there is no need
770 to do anything else. In the latter case, the combined
771 parallel loop call would still need extra synchronization
772 to implement ordered semantics, so there would not be any
773 gain in using the combined call. */
774 tree clauses = gimple_omp_for_clauses (ws_stmt);
775 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
776 if (c == NULL
777 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
778 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
780 region->is_combined_parallel = false;
781 region->inner->is_combined_parallel = false;
782 return;
786 region->is_combined_parallel = true;
787 region->inner->is_combined_parallel = true;
788 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
793 /* Return true if EXPR is variable sized. */
795 static inline bool
796 is_variable_sized (const_tree expr)
798 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
801 /* Return true if DECL is a reference type. */
803 static inline bool
804 is_reference (tree decl)
806 return lang_hooks.decls.omp_privatize_by_reference (decl);
809 /* Lookup variables in the decl or field splay trees. The "maybe" form
810 allows for the variable form to not have been entered, otherwise we
811 assert that the variable must have been entered. */
813 static inline tree
814 lookup_decl (tree var, omp_context *ctx)
816 tree *n;
817 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
818 return *n;
821 static inline tree
822 maybe_lookup_decl (const_tree var, omp_context *ctx)
824 tree *n;
825 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
826 return n ? *n : NULL_TREE;
829 static inline tree
830 lookup_field (tree var, omp_context *ctx)
832 splay_tree_node n;
833 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
834 return (tree) n->value;
837 static inline tree
838 lookup_sfield (tree var, omp_context *ctx)
840 splay_tree_node n;
841 n = splay_tree_lookup (ctx->sfield_map
842 ? ctx->sfield_map : ctx->field_map,
843 (splay_tree_key) var);
844 return (tree) n->value;
847 static inline tree
848 maybe_lookup_field (tree var, omp_context *ctx)
850 splay_tree_node n;
851 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
852 return n ? (tree) n->value : NULL_TREE;
855 /* Return true if DECL should be copied by pointer. SHARED_CTX is
856 the parallel context if DECL is to be shared. */
858 static bool
859 use_pointer_for_field (tree decl, omp_context *shared_ctx)
861 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
862 return true;
864 /* We can only use copy-in/copy-out semantics for shared variables
865 when we know the value is not accessible from an outer scope. */
866 if (shared_ctx)
868 gcc_assert (!is_gimple_omp_oacc_specifically (shared_ctx->stmt));
870 /* ??? Trivially accessible from anywhere. But why would we even
871 be passing an address in this case? Should we simply assert
872 this to be false, or should we have a cleanup pass that removes
873 these from the list of mappings? */
874 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
875 return true;
877 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
878 without analyzing the expression whether or not its location
879 is accessible to anyone else. In the case of nested parallel
880 regions it certainly may be. */
881 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
882 return true;
884 /* Do not use copy-in/copy-out for variables that have their
885 address taken. */
886 if (TREE_ADDRESSABLE (decl))
887 return true;
889 /* lower_send_shared_vars only uses copy-in, but not copy-out
890 for these. */
891 if (TREE_READONLY (decl)
892 || ((TREE_CODE (decl) == RESULT_DECL
893 || TREE_CODE (decl) == PARM_DECL)
894 && DECL_BY_REFERENCE (decl)))
895 return false;
897 /* Disallow copy-in/out in nested parallel if
898 decl is shared in outer parallel, otherwise
899 each thread could store the shared variable
900 in its own copy-in location, making the
901 variable no longer really shared. */
902 if (shared_ctx->is_nested)
904 omp_context *up;
906 for (up = shared_ctx->outer; up; up = up->outer)
907 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
908 break;
910 if (up)
912 tree c;
914 for (c = gimple_omp_taskreg_clauses (up->stmt);
915 c; c = OMP_CLAUSE_CHAIN (c))
916 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
917 && OMP_CLAUSE_DECL (c) == decl)
918 break;
920 if (c)
921 goto maybe_mark_addressable_and_ret;
925 /* For tasks avoid using copy-in/out. As tasks can be
926 deferred or executed in different thread, when GOMP_task
927 returns, the task hasn't necessarily terminated. */
928 if (is_task_ctx (shared_ctx))
930 tree outer;
931 maybe_mark_addressable_and_ret:
932 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
933 if (is_gimple_reg (outer))
935 /* Taking address of OUTER in lower_send_shared_vars
936 might need regimplification of everything that uses the
937 variable. */
938 if (!task_shared_vars)
939 task_shared_vars = BITMAP_ALLOC (NULL);
940 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
941 TREE_ADDRESSABLE (outer) = 1;
943 return true;
947 return false;
950 /* Construct a new automatic decl similar to VAR. */
952 static tree
953 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
955 tree copy = copy_var_decl (var, name, type);
957 DECL_CONTEXT (copy) = current_function_decl;
958 DECL_CHAIN (copy) = ctx->block_vars;
959 ctx->block_vars = copy;
961 return copy;
964 static tree
965 omp_copy_decl_1 (tree var, omp_context *ctx)
967 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
970 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
971 as appropriate. */
972 static tree
973 omp_build_component_ref (tree obj, tree field)
975 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
976 if (TREE_THIS_VOLATILE (field))
977 TREE_THIS_VOLATILE (ret) |= 1;
978 if (TREE_READONLY (field))
979 TREE_READONLY (ret) |= 1;
980 return ret;
983 /* Build tree nodes to access the field for VAR on the receiver side. */
985 static tree
986 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
988 tree x, field = lookup_field (var, ctx);
990 /* If the receiver record type was remapped in the child function,
991 remap the field into the new record type. */
992 x = maybe_lookup_field (field, ctx);
993 if (x != NULL)
994 field = x;
996 x = build_simple_mem_ref (ctx->receiver_decl);
997 x = omp_build_component_ref (x, field);
998 if (by_ref)
999 x = build_simple_mem_ref (x);
1001 return x;
1004 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1005 of a parallel, this is a component reference; for workshare constructs
1006 this is some variable. */
1008 static tree
1009 build_outer_var_ref (tree var, omp_context *ctx)
1011 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1013 tree x;
1015 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1016 x = var;
1017 else if (is_variable_sized (var))
1019 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1020 x = build_outer_var_ref (x, ctx);
1021 x = build_simple_mem_ref (x);
1023 else if (is_taskreg_ctx (ctx))
1025 bool by_ref = use_pointer_for_field (var, NULL);
1026 x = build_receiver_ref (var, by_ref, ctx);
1028 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1029 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1031 /* #pragma omp simd isn't a worksharing construct, and can reference even
1032 private vars in its linear etc. clauses. */
1033 x = NULL_TREE;
1034 if (ctx->outer && is_taskreg_ctx (ctx))
1035 x = lookup_decl (var, ctx->outer);
1036 else if (ctx->outer)
1037 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1038 if (x == NULL_TREE)
1039 x = var;
1041 else if (ctx->outer)
1042 x = lookup_decl (var, ctx->outer);
1043 else if (is_reference (var))
1044 /* This can happen with orphaned constructs. If var is reference, it is
1045 possible it is shared and as such valid. */
1046 x = var;
1047 else
1048 gcc_unreachable ();
1050 if (is_reference (var))
1051 x = build_simple_mem_ref (x);
1053 return x;
1056 /* Build tree nodes to access the field for VAR on the sender side. */
1058 static tree
1059 build_sender_ref (tree var, omp_context *ctx)
1061 tree field = lookup_sfield (var, ctx);
1062 return omp_build_component_ref (ctx->sender_decl, field);
1065 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1067 static void
1068 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1070 tree field, type, sfield = NULL_TREE;
1072 gcc_assert ((mask & 1) == 0
1073 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1074 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1075 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1076 gcc_assert ((mask & 3) == 3
1077 || !is_gimple_omp_oacc_specifically (ctx->stmt));
1079 type = TREE_TYPE (var);
1080 if (mask & 4)
1082 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1083 type = build_pointer_type (build_pointer_type (type));
1085 else if (by_ref)
1086 type = build_pointer_type (type);
1087 else if ((mask & 3) == 1 && is_reference (var))
1088 type = TREE_TYPE (type);
1090 field = build_decl (DECL_SOURCE_LOCATION (var),
1091 FIELD_DECL, DECL_NAME (var), type);
1093 /* Remember what variable this field was created for. This does have a
1094 side effect of making dwarf2out ignore this member, so for helpful
1095 debugging we clear it later in delete_omp_context. */
1096 DECL_ABSTRACT_ORIGIN (field) = var;
1097 if (type == TREE_TYPE (var))
1099 DECL_ALIGN (field) = DECL_ALIGN (var);
1100 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1101 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1103 else
1104 DECL_ALIGN (field) = TYPE_ALIGN (type);
1106 if ((mask & 3) == 3)
1108 insert_field_into_struct (ctx->record_type, field);
1109 if (ctx->srecord_type)
1111 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1112 FIELD_DECL, DECL_NAME (var), type);
1113 DECL_ABSTRACT_ORIGIN (sfield) = var;
1114 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1115 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1116 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1117 insert_field_into_struct (ctx->srecord_type, sfield);
1120 else
1122 if (ctx->srecord_type == NULL_TREE)
1124 tree t;
1126 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1127 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1128 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1130 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1131 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1132 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1133 insert_field_into_struct (ctx->srecord_type, sfield);
1134 splay_tree_insert (ctx->sfield_map,
1135 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1136 (splay_tree_value) sfield);
1139 sfield = field;
1140 insert_field_into_struct ((mask & 1) ? ctx->record_type
1141 : ctx->srecord_type, field);
1144 if (mask & 1)
1145 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1146 (splay_tree_value) field);
1147 if ((mask & 2) && ctx->sfield_map)
1148 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1149 (splay_tree_value) sfield);
1152 static tree
1153 install_var_local (tree var, omp_context *ctx)
1155 tree new_var = omp_copy_decl_1 (var, ctx);
1156 insert_decl_map (&ctx->cb, var, new_var);
1157 return new_var;
1160 /* Adjust the replacement for DECL in CTX for the new context. This means
1161 copying the DECL_VALUE_EXPR, and fixing up the type. */
1163 static void
1164 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1166 tree new_decl, size;
1168 new_decl = lookup_decl (decl, ctx);
1170 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1172 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1173 && DECL_HAS_VALUE_EXPR_P (decl))
1175 tree ve = DECL_VALUE_EXPR (decl);
1176 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1177 SET_DECL_VALUE_EXPR (new_decl, ve);
1178 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1181 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1183 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1184 if (size == error_mark_node)
1185 size = TYPE_SIZE (TREE_TYPE (new_decl));
1186 DECL_SIZE (new_decl) = size;
1188 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1189 if (size == error_mark_node)
1190 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1191 DECL_SIZE_UNIT (new_decl) = size;
1195 /* The callback for remap_decl. Search all containing contexts for a
1196 mapping of the variable; this avoids having to duplicate the splay
1197 tree ahead of time. We know a mapping doesn't already exist in the
1198 given context. Create new mappings to implement default semantics. */
1200 static tree
1201 omp_copy_decl (tree var, copy_body_data *cb)
1203 omp_context *ctx = (omp_context *) cb;
1204 tree new_var;
1206 if (TREE_CODE (var) == LABEL_DECL)
1208 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1209 DECL_CONTEXT (new_var) = current_function_decl;
1210 insert_decl_map (&ctx->cb, var, new_var);
1211 return new_var;
1214 while (!is_taskreg_ctx (ctx))
1216 ctx = ctx->outer;
1217 if (ctx == NULL)
1218 return var;
1219 new_var = maybe_lookup_decl (var, ctx);
1220 if (new_var)
1221 return new_var;
1224 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1225 return var;
1227 return error_mark_node;
1231 /* Debugging dumps for parallel regions. */
1232 void dump_omp_region (FILE *, struct omp_region *, int);
1233 void debug_omp_region (struct omp_region *);
1234 void debug_all_omp_regions (void);
1236 /* Dump the parallel region tree rooted at REGION. */
1238 void
1239 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1241 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1242 gimple_code_name[region->type]);
1244 if (region->inner)
1245 dump_omp_region (file, region->inner, indent + 4);
1247 if (region->cont)
1249 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1250 region->cont->index);
1253 if (region->exit)
1254 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1255 region->exit->index);
1256 else
1257 fprintf (file, "%*s[no exit marker]\n", indent, "");
1259 if (region->next)
1260 dump_omp_region (file, region->next, indent);
1263 DEBUG_FUNCTION void
1264 debug_omp_region (struct omp_region *region)
1266 dump_omp_region (stderr, region, 0);
1269 DEBUG_FUNCTION void
1270 debug_all_omp_regions (void)
1272 dump_omp_region (stderr, root_omp_region, 0);
1276 /* Create a new parallel region starting at STMT inside region PARENT. */
1278 static struct omp_region *
1279 new_omp_region (basic_block bb, enum gimple_code type,
1280 struct omp_region *parent)
1282 struct omp_region *region = XCNEW (struct omp_region);
1284 region->outer = parent;
1285 region->entry = bb;
1286 region->type = type;
1288 if (parent)
1290 /* This is a nested region. Add it to the list of inner
1291 regions in PARENT. */
1292 region->next = parent->inner;
1293 parent->inner = region;
1295 else
1297 /* This is a toplevel region. Add it to the list of toplevel
1298 regions in ROOT_OMP_REGION. */
1299 region->next = root_omp_region;
1300 root_omp_region = region;
1303 return region;
1306 /* Release the memory associated with the region tree rooted at REGION. */
1308 static void
1309 free_omp_region_1 (struct omp_region *region)
1311 struct omp_region *i, *n;
1313 for (i = region->inner; i ; i = n)
1315 n = i->next;
1316 free_omp_region_1 (i);
1319 free (region);
1322 /* Release the memory for the entire omp region tree. */
1324 void
1325 free_omp_regions (void)
1327 struct omp_region *r, *n;
1328 for (r = root_omp_region; r ; r = n)
1330 n = r->next;
1331 free_omp_region_1 (r);
1333 root_omp_region = NULL;
1337 /* Create a new context, with OUTER_CTX being the surrounding context. */
1339 static omp_context *
1340 new_omp_context (gimple stmt, omp_context *outer_ctx)
1342 omp_context *ctx = XCNEW (omp_context);
1344 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1345 (splay_tree_value) ctx);
1346 ctx->stmt = stmt;
1348 if (outer_ctx)
1350 ctx->outer = outer_ctx;
1351 ctx->cb = outer_ctx->cb;
1352 ctx->cb.block = NULL;
1353 ctx->depth = outer_ctx->depth + 1;
1355 else
1357 ctx->cb.src_fn = current_function_decl;
1358 ctx->cb.dst_fn = current_function_decl;
1359 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1360 gcc_checking_assert (ctx->cb.src_node);
1361 ctx->cb.dst_node = ctx->cb.src_node;
1362 ctx->cb.src_cfun = cfun;
1363 ctx->cb.copy_decl = omp_copy_decl;
1364 ctx->cb.eh_lp_nr = 0;
1365 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1366 ctx->depth = 1;
1369 ctx->cb.decl_map = pointer_map_create ();
1371 return ctx;
1374 static gimple_seq maybe_catch_exception (gimple_seq);
1376 /* Finalize task copyfn. */
1378 static void
1379 finalize_task_copyfn (gimple task_stmt)
1381 struct function *child_cfun;
1382 tree child_fn;
1383 gimple_seq seq = NULL, new_seq;
1384 gimple bind;
1386 child_fn = gimple_omp_task_copy_fn (task_stmt);
1387 if (child_fn == NULL_TREE)
1388 return;
1390 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1391 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1393 push_cfun (child_cfun);
1394 bind = gimplify_body (child_fn, false);
1395 gimple_seq_add_stmt (&seq, bind);
1396 new_seq = maybe_catch_exception (seq);
1397 if (new_seq != seq)
1399 bind = gimple_build_bind (NULL, new_seq, NULL);
1400 seq = NULL;
1401 gimple_seq_add_stmt (&seq, bind);
1403 gimple_set_body (child_fn, seq);
1404 pop_cfun ();
1406 /* Inform the callgraph about the new function. */
1407 cgraph_add_new_function (child_fn, false);
1410 /* Destroy a omp_context data structures. Called through the splay tree
1411 value delete callback. */
1413 static void
1414 delete_omp_context (splay_tree_value value)
1416 omp_context *ctx = (omp_context *) value;
1418 pointer_map_destroy (ctx->cb.decl_map);
1420 if (ctx->field_map)
1421 splay_tree_delete (ctx->field_map);
1422 if (ctx->sfield_map)
1423 splay_tree_delete (ctx->sfield_map);
1425 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1426 it produces corrupt debug information. */
1427 if (ctx->record_type)
1429 tree t;
1430 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1431 DECL_ABSTRACT_ORIGIN (t) = NULL;
1433 if (ctx->srecord_type)
1435 tree t;
1436 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1437 DECL_ABSTRACT_ORIGIN (t) = NULL;
1440 if (is_task_ctx (ctx))
1441 finalize_task_copyfn (ctx->stmt);
1443 XDELETE (ctx);
1446 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1447 context. */
1449 static void
1450 fixup_child_record_type (omp_context *ctx)
1452 tree f, type = ctx->record_type;
1454 /* ??? It isn't sufficient to just call remap_type here, because
1455 variably_modified_type_p doesn't work the way we expect for
1456 record types. Testing each field for whether it needs remapping
1457 and creating a new record by hand works, however. */
1458 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1459 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1460 break;
1461 if (f)
1463 tree name, new_fields = NULL;
1465 type = lang_hooks.types.make_type (RECORD_TYPE);
1466 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1467 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1468 TYPE_DECL, name, type);
1469 TYPE_NAME (type) = name;
1471 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1473 tree new_f = copy_node (f);
1474 DECL_CONTEXT (new_f) = type;
1475 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1476 DECL_CHAIN (new_f) = new_fields;
1477 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1478 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1479 &ctx->cb, NULL);
1480 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1481 &ctx->cb, NULL);
1482 new_fields = new_f;
1484 /* Arrange to be able to look up the receiver field
1485 given the sender field. */
1486 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1487 (splay_tree_value) new_f);
1489 TYPE_FIELDS (type) = nreverse (new_fields);
1490 layout_type (type);
1493 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1496 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1497 specified by CLAUSES. */
1499 static void
1500 scan_sharing_clauses (tree clauses, omp_context *ctx)
1502 tree c, decl;
1503 bool scan_array_reductions = false;
1505 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1507 bool by_ref;
1509 switch (OMP_CLAUSE_CODE (c))
1511 case OMP_CLAUSE_PRIVATE:
1512 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1513 decl = OMP_CLAUSE_DECL (c);
1514 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1515 goto do_private;
1516 else if (!is_variable_sized (decl))
1517 install_var_local (decl, ctx);
1518 break;
1520 case OMP_CLAUSE_SHARED:
1521 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1522 /* Ignore shared directives in teams construct. */
1523 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1524 break;
1525 gcc_assert (is_taskreg_ctx (ctx));
1526 decl = OMP_CLAUSE_DECL (c);
1527 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1528 || !is_variable_sized (decl));
1529 /* Global variables don't need to be copied,
1530 the receiver side will use them directly. */
1531 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1532 break;
1533 by_ref = use_pointer_for_field (decl, ctx);
1534 if (! TREE_READONLY (decl)
1535 || TREE_ADDRESSABLE (decl)
1536 || by_ref
1537 || is_reference (decl))
1539 install_var_field (decl, by_ref, 3, ctx);
1540 install_var_local (decl, ctx);
1541 break;
1543 /* We don't need to copy const scalar vars back. */
1544 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1545 goto do_private;
1547 case OMP_CLAUSE_LASTPRIVATE:
1548 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1549 /* Let the corresponding firstprivate clause create
1550 the variable. */
1551 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1552 break;
1553 /* FALLTHRU */
1555 case OMP_CLAUSE_FIRSTPRIVATE:
1556 case OMP_CLAUSE_REDUCTION:
1557 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1559 sorry ("clause not supported yet");
1560 break;
1562 case OMP_CLAUSE_LINEAR:
1563 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1564 decl = OMP_CLAUSE_DECL (c);
1565 do_private:
1566 if (is_variable_sized (decl))
1568 if (is_task_ctx (ctx))
1569 install_var_field (decl, false, 1, ctx);
1570 break;
1572 else if (is_taskreg_ctx (ctx))
1574 bool global
1575 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1576 by_ref = use_pointer_for_field (decl, NULL);
1578 if (is_task_ctx (ctx)
1579 && (global || by_ref || is_reference (decl)))
1581 install_var_field (decl, false, 1, ctx);
1582 if (!global)
1583 install_var_field (decl, by_ref, 2, ctx);
1585 else if (!global)
1586 install_var_field (decl, by_ref, 3, ctx);
1588 install_var_local (decl, ctx);
1589 break;
1591 case OMP_CLAUSE__LOOPTEMP_:
1592 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1593 gcc_assert (is_parallel_ctx (ctx));
1594 decl = OMP_CLAUSE_DECL (c);
1595 install_var_field (decl, false, 3, ctx);
1596 install_var_local (decl, ctx);
1597 break;
1599 case OMP_CLAUSE_COPYPRIVATE:
1600 case OMP_CLAUSE_COPYIN:
1601 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1602 decl = OMP_CLAUSE_DECL (c);
1603 by_ref = use_pointer_for_field (decl, NULL);
1604 install_var_field (decl, by_ref, 3, ctx);
1605 break;
1607 case OMP_CLAUSE_DEFAULT:
1608 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1609 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1610 break;
1612 case OMP_CLAUSE_IF:
1613 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1615 sorry ("clause not supported yet");
1616 break;
1618 case OMP_CLAUSE_FINAL:
1619 case OMP_CLAUSE_NUM_THREADS:
1620 case OMP_CLAUSE_NUM_TEAMS:
1621 case OMP_CLAUSE_THREAD_LIMIT:
1622 case OMP_CLAUSE_DEVICE:
1623 case OMP_CLAUSE_SCHEDULE:
1624 case OMP_CLAUSE_DIST_SCHEDULE:
1625 case OMP_CLAUSE_DEPEND:
1626 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1627 case OMP_CLAUSE_NUM_GANGS:
1628 case OMP_CLAUSE_NUM_WORKERS:
1629 case OMP_CLAUSE_VECTOR_LENGTH:
1630 if (ctx->outer)
1632 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1633 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1635 break;
1637 case OMP_CLAUSE_TO:
1638 case OMP_CLAUSE_FROM:
1639 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1640 case OMP_CLAUSE_MAP:
1641 switch (OMP_CLAUSE_CODE (c))
1643 case OMP_CLAUSE_TO:
1644 case OMP_CLAUSE_FROM:
1645 /* The to and from clauses are only ever seen with OpenMP target
1646 update constructs. */
1647 gcc_assert (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1648 && (gimple_omp_target_kind (ctx->stmt)
1649 == GF_OMP_TARGET_KIND_UPDATE));
1650 break;
1651 case OMP_CLAUSE_MAP:
1652 /* The map clause is never seen with OpenMP target update
1653 constructs. */
1654 gcc_assert (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
1655 || (gimple_omp_target_kind (ctx->stmt)
1656 != GF_OMP_TARGET_KIND_UPDATE));
1657 break;
1658 default:
1659 gcc_unreachable ();
1661 if (ctx->outer)
1662 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1663 decl = OMP_CLAUSE_DECL (c);
1664 /* Global variables with "omp declare target" attribute
1665 don't need to be copied, the receiver side will use them
1666 directly. */
1667 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1668 && DECL_P (decl)
1669 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1670 && lookup_attribute ("omp declare target",
1671 DECL_ATTRIBUTES (decl)))
1673 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1674 break;
1676 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1677 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1679 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1680 target regions that are not offloaded; there is nothing to map for
1681 those. */
1682 if (!is_gimple_omp_offloaded (ctx->stmt)
1683 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1684 break;
1686 if (DECL_P (decl))
1688 if (DECL_SIZE (decl)
1689 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1691 tree decl2 = DECL_VALUE_EXPR (decl);
1692 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1693 decl2 = TREE_OPERAND (decl2, 0);
1694 gcc_assert (DECL_P (decl2));
1695 install_var_field (decl2, true, 3, ctx);
1696 install_var_local (decl2, ctx);
1697 install_var_local (decl, ctx);
1699 else
1701 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1702 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1703 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1704 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1705 install_var_field (decl, true, 7, ctx);
1706 else
1707 install_var_field (decl, true, 3, ctx);
1708 if (is_gimple_omp_offloaded (ctx->stmt))
1709 install_var_local (decl, ctx);
1712 else
1714 tree base = get_base_address (decl);
1715 tree nc = OMP_CLAUSE_CHAIN (c);
1716 if (DECL_P (base)
1717 && nc != NULL_TREE
1718 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1719 && OMP_CLAUSE_DECL (nc) == base
1720 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1721 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1723 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1724 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1726 else
1728 gcc_assert (!splay_tree_lookup (ctx->field_map,
1729 (splay_tree_key) decl));
1730 tree field
1731 = build_decl (OMP_CLAUSE_LOCATION (c),
1732 FIELD_DECL, NULL_TREE, ptr_type_node);
1733 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1734 insert_field_into_struct (ctx->record_type, field);
1735 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1736 (splay_tree_value) field);
1739 break;
1741 case OMP_CLAUSE_NOWAIT:
1742 case OMP_CLAUSE_ORDERED:
1743 case OMP_CLAUSE_COLLAPSE:
1744 case OMP_CLAUSE_UNTIED:
1745 case OMP_CLAUSE_MERGEABLE:
1746 case OMP_CLAUSE_PROC_BIND:
1747 case OMP_CLAUSE_SAFELEN:
1748 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1749 break;
1751 case OMP_CLAUSE_ALIGNED:
1752 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1753 decl = OMP_CLAUSE_DECL (c);
1754 if (is_global_var (decl)
1755 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1756 install_var_local (decl, ctx);
1757 break;
1759 case OMP_CLAUSE_HOST:
1760 case OMP_CLAUSE_OACC_DEVICE:
1761 case OMP_CLAUSE_DEVICE_RESIDENT:
1762 case OMP_CLAUSE_USE_DEVICE:
1763 case OMP_CLAUSE_GANG:
1764 case OMP_CLAUSE_ASYNC:
1765 case OMP_CLAUSE_WAIT:
1766 case OMP_NO_CLAUSE_CACHE:
1767 case OMP_CLAUSE_INDEPENDENT:
1768 case OMP_CLAUSE_WORKER:
1769 case OMP_CLAUSE_VECTOR:
1770 sorry ("Clause not supported yet");
1771 break;
1773 default:
1774 gcc_unreachable ();
1778 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1780 switch (OMP_CLAUSE_CODE (c))
1782 case OMP_CLAUSE_LASTPRIVATE:
1783 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1784 /* Let the corresponding firstprivate clause create
1785 the variable. */
1786 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1787 scan_array_reductions = true;
1788 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1789 break;
1790 /* FALLTHRU */
1792 case OMP_CLAUSE_PRIVATE:
1793 case OMP_CLAUSE_FIRSTPRIVATE:
1794 case OMP_CLAUSE_REDUCTION:
1795 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1797 sorry ("clause not supported yet");
1798 break;
1800 case OMP_CLAUSE_LINEAR:
1801 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1802 decl = OMP_CLAUSE_DECL (c);
1803 if (is_variable_sized (decl))
1804 install_var_local (decl, ctx);
1805 fixup_remapped_decl (decl, ctx,
1806 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1807 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1808 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1809 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1810 scan_array_reductions = true;
1811 break;
1813 case OMP_CLAUSE_SHARED:
1814 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1815 /* Ignore shared directives in teams construct. */
1816 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1817 break;
1818 decl = OMP_CLAUSE_DECL (c);
1819 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1820 fixup_remapped_decl (decl, ctx, false);
1821 break;
1823 case OMP_CLAUSE_MAP:
1824 /* The map clause is never seen with OpenMP target update
1825 constructs. */
1826 gcc_assert (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
1827 || (gimple_omp_target_kind (ctx->stmt)
1828 != GF_OMP_TARGET_KIND_UPDATE));
1829 if (!is_gimple_omp_offloaded (ctx->stmt))
1830 break;
1831 decl = OMP_CLAUSE_DECL (c);
1832 if (DECL_P (decl)
1833 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1834 && lookup_attribute ("omp declare target",
1835 DECL_ATTRIBUTES (decl)))
1837 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1838 break;
1840 if (DECL_P (decl))
1842 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1843 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1844 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1846 tree new_decl = lookup_decl (decl, ctx);
1847 TREE_TYPE (new_decl)
1848 = remap_type (TREE_TYPE (decl), &ctx->cb);
1850 else if (DECL_SIZE (decl)
1851 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1853 tree decl2 = DECL_VALUE_EXPR (decl);
1854 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1855 decl2 = TREE_OPERAND (decl2, 0);
1856 gcc_assert (DECL_P (decl2));
1857 fixup_remapped_decl (decl2, ctx, false);
1858 fixup_remapped_decl (decl, ctx, true);
1860 else
1861 fixup_remapped_decl (decl, ctx, false);
1863 break;
1865 case OMP_CLAUSE_IF:
1866 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1868 sorry ("clause not supported yet");
1869 break;
1871 case OMP_CLAUSE_COPYPRIVATE:
1872 case OMP_CLAUSE_COPYIN:
1873 case OMP_CLAUSE_DEFAULT:
1874 case OMP_CLAUSE_NUM_THREADS:
1875 case OMP_CLAUSE_NUM_TEAMS:
1876 case OMP_CLAUSE_THREAD_LIMIT:
1877 case OMP_CLAUSE_DEVICE:
1878 case OMP_CLAUSE_SCHEDULE:
1879 case OMP_CLAUSE_DIST_SCHEDULE:
1880 case OMP_CLAUSE_NOWAIT:
1881 case OMP_CLAUSE_ORDERED:
1882 case OMP_CLAUSE_COLLAPSE:
1883 case OMP_CLAUSE_UNTIED:
1884 case OMP_CLAUSE_FINAL:
1885 case OMP_CLAUSE_MERGEABLE:
1886 case OMP_CLAUSE_PROC_BIND:
1887 case OMP_CLAUSE_SAFELEN:
1888 case OMP_CLAUSE_ALIGNED:
1889 case OMP_CLAUSE_DEPEND:
1890 case OMP_CLAUSE__LOOPTEMP_:
1891 case OMP_CLAUSE_TO:
1892 case OMP_CLAUSE_FROM:
1893 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1894 case OMP_CLAUSE_NUM_GANGS:
1895 case OMP_CLAUSE_NUM_WORKERS:
1896 case OMP_CLAUSE_VECTOR_LENGTH:
1897 break;
1899 case OMP_CLAUSE_HOST:
1900 case OMP_CLAUSE_OACC_DEVICE:
1901 case OMP_CLAUSE_DEVICE_RESIDENT:
1902 case OMP_CLAUSE_USE_DEVICE:
1903 case OMP_CLAUSE_GANG:
1904 case OMP_CLAUSE_ASYNC:
1905 case OMP_CLAUSE_WAIT:
1906 case OMP_NO_CLAUSE_CACHE:
1907 case OMP_CLAUSE_INDEPENDENT:
1908 case OMP_CLAUSE_WORKER:
1909 case OMP_CLAUSE_VECTOR:
1910 sorry ("Clause not supported yet");
1911 break;
1913 default:
1914 gcc_unreachable ();
1918 if (scan_array_reductions)
1920 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1921 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1922 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1923 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1925 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1926 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1928 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1929 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1930 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1934 /* Create a new name for omp child function. Returns an identifier. */
1936 static tree
1937 create_omp_child_function_name (bool task_copy)
1939 return (clone_function_name (current_function_decl,
1940 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1943 /* Build a decl for the omp child function. It'll not contain a body
1944 yet, just the bare decl. */
1946 static void
1947 create_omp_child_function (omp_context *ctx, bool task_copy)
1949 tree decl, type, name, t;
1951 name = create_omp_child_function_name (task_copy);
1952 if (task_copy)
1953 type = build_function_type_list (void_type_node, ptr_type_node,
1954 ptr_type_node, NULL_TREE);
1955 else
1956 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1958 decl = build_decl (gimple_location (ctx->stmt),
1959 FUNCTION_DECL, name, type);
1961 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt)
1962 || !task_copy);
1963 if (!task_copy)
1964 ctx->cb.dst_fn = decl;
1965 else
1966 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1968 TREE_STATIC (decl) = 1;
1969 TREE_USED (decl) = 1;
1970 DECL_ARTIFICIAL (decl) = 1;
1971 DECL_NAMELESS (decl) = 1;
1972 DECL_IGNORED_P (decl) = 0;
1973 TREE_PUBLIC (decl) = 0;
1974 DECL_UNINLINABLE (decl) = 1;
1975 DECL_EXTERNAL (decl) = 0;
1976 DECL_CONTEXT (decl) = NULL_TREE;
1977 DECL_INITIAL (decl) = make_node (BLOCK);
1978 bool target_p = false;
1979 if (lookup_attribute ("omp declare target",
1980 DECL_ATTRIBUTES (current_function_decl)))
1981 target_p = true;
1982 else
1984 omp_context *octx;
1985 for (octx = ctx; octx; octx = octx->outer)
1986 if (is_gimple_omp_offloaded (octx->stmt))
1988 target_p = true;
1989 break;
1992 if (target_p)
1993 DECL_ATTRIBUTES (decl)
1994 = tree_cons (get_identifier ("omp declare target"),
1995 NULL_TREE, DECL_ATTRIBUTES (decl));
1997 t = build_decl (DECL_SOURCE_LOCATION (decl),
1998 RESULT_DECL, NULL_TREE, void_type_node);
1999 DECL_ARTIFICIAL (t) = 1;
2000 DECL_IGNORED_P (t) = 1;
2001 DECL_CONTEXT (t) = decl;
2002 DECL_RESULT (decl) = t;
2004 t = build_decl (DECL_SOURCE_LOCATION (decl),
2005 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
2006 DECL_ARTIFICIAL (t) = 1;
2007 DECL_NAMELESS (t) = 1;
2008 DECL_ARG_TYPE (t) = ptr_type_node;
2009 DECL_CONTEXT (t) = current_function_decl;
2010 TREE_USED (t) = 1;
2011 DECL_ARGUMENTS (decl) = t;
2012 if (!task_copy)
2013 ctx->receiver_decl = t;
2014 else
2016 t = build_decl (DECL_SOURCE_LOCATION (decl),
2017 PARM_DECL, get_identifier (".omp_data_o"),
2018 ptr_type_node);
2019 DECL_ARTIFICIAL (t) = 1;
2020 DECL_NAMELESS (t) = 1;
2021 DECL_ARG_TYPE (t) = ptr_type_node;
2022 DECL_CONTEXT (t) = current_function_decl;
2023 TREE_USED (t) = 1;
2024 TREE_ADDRESSABLE (t) = 1;
2025 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2026 DECL_ARGUMENTS (decl) = t;
2029 /* Allocate memory for the function structure. The call to
2030 allocate_struct_function clobbers CFUN, so we need to restore
2031 it afterward. */
2032 push_struct_function (decl);
2033 cfun->function_end_locus = gimple_location (ctx->stmt);
2034 pop_cfun ();
2037 /* Callback for walk_gimple_seq. Check if combined parallel
2038 contains gimple_omp_for_combined_into_p OMP_FOR. */
2040 static tree
2041 find_combined_for (gimple_stmt_iterator *gsi_p,
2042 bool *handled_ops_p,
2043 struct walk_stmt_info *wi)
2045 gimple stmt = gsi_stmt (*gsi_p);
2047 *handled_ops_p = true;
2048 switch (gimple_code (stmt))
2050 WALK_SUBSTMTS;
2052 case GIMPLE_OMP_FOR:
2053 if (gimple_omp_for_combined_into_p (stmt)
2054 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2056 wi->info = stmt;
2057 return integer_zero_node;
2059 break;
2060 default:
2061 break;
2063 return NULL;
2066 /* Scan an OpenACC offload directive. */
2068 static void
2069 scan_oacc_offload (gimple stmt, omp_context *outer_ctx)
2071 omp_context *ctx;
2072 tree name;
2073 void (*gimple_omp_set_child_fn) (gimple, tree);
2074 tree (*gimple_omp_clauses) (const_gimple);
2075 switch (gimple_code (stmt))
2077 case GIMPLE_OACC_KERNELS:
2078 gimple_omp_set_child_fn = gimple_oacc_kernels_set_child_fn;
2079 gimple_omp_clauses = gimple_oacc_kernels_clauses;
2080 break;
2081 case GIMPLE_OACC_PARALLEL:
2082 gimple_omp_set_child_fn = gimple_oacc_parallel_set_child_fn;
2083 gimple_omp_clauses = gimple_oacc_parallel_clauses;
2084 break;
2085 default:
2086 gcc_unreachable ();
2089 gcc_assert (taskreg_nesting_level == 0);
2090 gcc_assert (target_nesting_level == 0);
2092 ctx = new_omp_context (stmt, outer_ctx);
2093 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2094 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2095 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2096 name = create_tmp_var_name (".omp_data_t");
2097 name = build_decl (gimple_location (stmt),
2098 TYPE_DECL, name, ctx->record_type);
2099 DECL_ARTIFICIAL (name) = 1;
2100 DECL_NAMELESS (name) = 1;
2101 TYPE_NAME (ctx->record_type) = name;
2102 create_omp_child_function (ctx, false);
2104 gimple_omp_set_child_fn (stmt, ctx->cb.dst_fn);
2106 scan_sharing_clauses (gimple_omp_clauses (stmt), ctx);
2107 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2109 if (TYPE_FIELDS (ctx->record_type) == NULL)
2110 ctx->record_type = ctx->receiver_decl = NULL;
2111 else
2113 TYPE_FIELDS (ctx->record_type)
2114 = nreverse (TYPE_FIELDS (ctx->record_type));
2115 #ifdef ENABLE_CHECKING
2116 tree field;
2117 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2118 for (field = TYPE_FIELDS (ctx->record_type);
2119 field;
2120 field = DECL_CHAIN (field))
2121 gcc_assert (DECL_ALIGN (field) == align);
2122 #endif
2123 layout_type (ctx->record_type);
2124 fixup_child_record_type (ctx);
2128 /* Scan an OpenMP parallel directive. */
2130 static void
2131 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2133 omp_context *ctx;
2134 tree name;
2135 gimple stmt = gsi_stmt (*gsi);
2137 /* Ignore parallel directives with empty bodies, unless there
2138 are copyin clauses. */
2139 if (optimize > 0
2140 && empty_body_p (gimple_omp_body (stmt))
2141 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2142 OMP_CLAUSE_COPYIN) == NULL)
2144 gsi_replace (gsi, gimple_build_nop (), false);
2145 return;
2148 if (gimple_omp_parallel_combined_p (stmt))
2150 gimple for_stmt;
2151 struct walk_stmt_info wi;
2153 memset (&wi, 0, sizeof (wi));
2154 wi.val_only = true;
2155 walk_gimple_seq (gimple_omp_body (stmt),
2156 find_combined_for, NULL, &wi);
2157 for_stmt = (gimple) wi.info;
2158 if (for_stmt)
2160 struct omp_for_data fd;
2161 extract_omp_for_data (for_stmt, &fd, NULL);
2162 /* We need two temporaries with fd.loop.v type (istart/iend)
2163 and then (fd.collapse - 1) temporaries with the same
2164 type for count2 ... countN-1 vars if not constant. */
2165 size_t count = 2, i;
2166 tree type = fd.iter_type;
2167 if (fd.collapse > 1
2168 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2169 count += fd.collapse - 1;
2170 for (i = 0; i < count; i++)
2172 tree temp = create_tmp_var (type, NULL);
2173 tree c = build_omp_clause (UNKNOWN_LOCATION,
2174 OMP_CLAUSE__LOOPTEMP_);
2175 OMP_CLAUSE_DECL (c) = temp;
2176 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2177 gimple_omp_parallel_set_clauses (stmt, c);
2182 ctx = new_omp_context (stmt, outer_ctx);
2183 if (taskreg_nesting_level > 1)
2184 ctx->is_nested = true;
2185 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2186 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2187 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2188 name = create_tmp_var_name (".omp_data_s");
2189 name = build_decl (gimple_location (stmt),
2190 TYPE_DECL, name, ctx->record_type);
2191 DECL_ARTIFICIAL (name) = 1;
2192 DECL_NAMELESS (name) = 1;
2193 TYPE_NAME (ctx->record_type) = name;
2194 create_omp_child_function (ctx, false);
2195 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2197 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2198 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2200 if (TYPE_FIELDS (ctx->record_type) == NULL)
2201 ctx->record_type = ctx->receiver_decl = NULL;
2202 else
2204 layout_type (ctx->record_type);
2205 fixup_child_record_type (ctx);
2209 /* Scan an OpenMP task directive. */
2211 static void
2212 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2214 omp_context *ctx;
2215 tree name, t;
2216 gimple stmt = gsi_stmt (*gsi);
2217 location_t loc = gimple_location (stmt);
2219 /* Ignore task directives with empty bodies. */
2220 if (optimize > 0
2221 && empty_body_p (gimple_omp_body (stmt)))
2223 gsi_replace (gsi, gimple_build_nop (), false);
2224 return;
2227 ctx = new_omp_context (stmt, outer_ctx);
2228 if (taskreg_nesting_level > 1)
2229 ctx->is_nested = true;
2230 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2231 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2232 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2233 name = create_tmp_var_name (".omp_data_s");
2234 name = build_decl (gimple_location (stmt),
2235 TYPE_DECL, name, ctx->record_type);
2236 DECL_ARTIFICIAL (name) = 1;
2237 DECL_NAMELESS (name) = 1;
2238 TYPE_NAME (ctx->record_type) = name;
2239 create_omp_child_function (ctx, false);
2240 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2242 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2244 if (ctx->srecord_type)
2246 name = create_tmp_var_name (".omp_data_a");
2247 name = build_decl (gimple_location (stmt),
2248 TYPE_DECL, name, ctx->srecord_type);
2249 DECL_ARTIFICIAL (name) = 1;
2250 DECL_NAMELESS (name) = 1;
2251 TYPE_NAME (ctx->srecord_type) = name;
2252 create_omp_child_function (ctx, true);
2255 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2257 if (TYPE_FIELDS (ctx->record_type) == NULL)
2259 ctx->record_type = ctx->receiver_decl = NULL;
2260 t = build_int_cst (long_integer_type_node, 0);
2261 gimple_omp_task_set_arg_size (stmt, t);
2262 t = build_int_cst (long_integer_type_node, 1);
2263 gimple_omp_task_set_arg_align (stmt, t);
2265 else
2267 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2268 /* Move VLA fields to the end. */
2269 p = &TYPE_FIELDS (ctx->record_type);
2270 while (*p)
2271 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2272 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2274 *q = *p;
2275 *p = TREE_CHAIN (*p);
2276 TREE_CHAIN (*q) = NULL_TREE;
2277 q = &TREE_CHAIN (*q);
2279 else
2280 p = &DECL_CHAIN (*p);
2281 *p = vla_fields;
2282 layout_type (ctx->record_type);
2283 fixup_child_record_type (ctx);
2284 if (ctx->srecord_type)
2285 layout_type (ctx->srecord_type);
2286 t = fold_convert_loc (loc, long_integer_type_node,
2287 TYPE_SIZE_UNIT (ctx->record_type));
2288 gimple_omp_task_set_arg_size (stmt, t);
2289 t = build_int_cst (long_integer_type_node,
2290 TYPE_ALIGN_UNIT (ctx->record_type));
2291 gimple_omp_task_set_arg_align (stmt, t);
2296 /* Scan a GIMPLE_OMP_FOR. */
2298 static void
2299 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2301 omp_context *ctx;
2302 size_t i;
2304 ctx = new_omp_context (stmt, outer_ctx);
2306 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2308 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2309 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2311 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2312 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2313 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2314 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2316 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2319 /* Scan an OpenMP sections directive. */
2321 static void
2322 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2324 omp_context *ctx;
2326 ctx = new_omp_context (stmt, outer_ctx);
2327 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2328 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2331 /* Scan an OpenMP single directive. */
2333 static void
2334 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2336 omp_context *ctx;
2337 tree name;
2339 ctx = new_omp_context (stmt, outer_ctx);
2340 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2341 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2342 name = create_tmp_var_name (".omp_copy_s");
2343 name = build_decl (gimple_location (stmt),
2344 TYPE_DECL, name, ctx->record_type);
2345 TYPE_NAME (ctx->record_type) = name;
2347 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2348 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2350 if (TYPE_FIELDS (ctx->record_type) == NULL)
2351 ctx->record_type = NULL;
2352 else
2353 layout_type (ctx->record_type);
2356 /* Scan a GIMPLE_OMP_TARGET. */
2358 static void
2359 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2361 omp_context *ctx;
2362 tree name;
2363 int kind = gimple_omp_target_kind (stmt);
2365 if (kind == GF_OMP_TARGET_KIND_OACC_DATA)
2367 gcc_assert (taskreg_nesting_level == 0);
2368 gcc_assert (target_nesting_level == 0);
2371 ctx = new_omp_context (stmt, outer_ctx);
2372 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2373 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2374 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2375 name = create_tmp_var_name (".omp_data_t");
2376 name = build_decl (gimple_location (stmt),
2377 TYPE_DECL, name, ctx->record_type);
2378 DECL_ARTIFICIAL (name) = 1;
2379 DECL_NAMELESS (name) = 1;
2380 TYPE_NAME (ctx->record_type) = name;
2381 if (kind == GF_OMP_TARGET_KIND_REGION)
2383 create_omp_child_function (ctx, false);
2384 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2387 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2388 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2390 if (TYPE_FIELDS (ctx->record_type) == NULL)
2391 ctx->record_type = ctx->receiver_decl = NULL;
2392 else
2394 TYPE_FIELDS (ctx->record_type)
2395 = nreverse (TYPE_FIELDS (ctx->record_type));
2396 #ifdef ENABLE_CHECKING
2397 tree field;
2398 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2399 for (field = TYPE_FIELDS (ctx->record_type);
2400 field;
2401 field = DECL_CHAIN (field))
2402 gcc_assert (DECL_ALIGN (field) == align);
2403 #endif
2404 layout_type (ctx->record_type);
2405 if (kind == GF_OMP_TARGET_KIND_REGION)
2406 fixup_child_record_type (ctx);
2410 /* Scan an OpenMP teams directive. */
2412 static void
2413 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2415 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2416 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2417 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2420 /* Check OpenMP nesting restrictions. */
2421 static bool
2422 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2424 /* TODO: While the OpenACC specification does allow for certain kinds of
2425 nesting, we don't support many of these yet. */
2426 if (is_gimple_omp (stmt)
2427 && is_gimple_omp_oacc_specifically (stmt))
2429 /* Regular handling of OpenACC loop constructs. */
2430 if (gimple_code (stmt) == GIMPLE_OMP_FOR
2431 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
2432 goto cont;
2433 /* No nesting of OpenACC STMT inside any OpenACC or OpenMP CTX different
2434 from an OpenACC data construct. */
2435 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2436 if (is_gimple_omp (ctx_->stmt)
2437 && !(gimple_code (ctx_->stmt) == GIMPLE_OMP_TARGET
2438 && (gimple_omp_target_kind (ctx_->stmt)
2439 == GF_OMP_TARGET_KIND_OACC_DATA)))
2441 error_at (gimple_location (stmt),
2442 "may not be nested");
2443 return false;
2446 else
2448 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP
2449 builtin) inside any OpenACC CTX. */
2450 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2451 if (is_gimple_omp (ctx_->stmt)
2452 && is_gimple_omp_oacc_specifically (ctx_->stmt))
2454 error_at (gimple_location (stmt),
2455 "may not be nested");
2456 return false;
2459 cont:
2461 if (ctx != NULL)
2463 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2464 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2466 error_at (gimple_location (stmt),
2467 "OpenMP constructs may not be nested inside simd region");
2468 return false;
2470 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2472 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2473 || (gimple_omp_for_kind (stmt)
2474 != GF_OMP_FOR_KIND_DISTRIBUTE))
2475 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2477 error_at (gimple_location (stmt),
2478 "only distribute or parallel constructs are allowed to "
2479 "be closely nested inside teams construct");
2480 return false;
2484 switch (gimple_code (stmt))
2486 case GIMPLE_OMP_FOR:
2487 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2488 return true;
2489 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2491 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2493 error_at (gimple_location (stmt),
2494 "distribute construct must be closely nested inside "
2495 "teams construct");
2496 return false;
2498 return true;
2500 /* FALLTHRU */
2501 case GIMPLE_CALL:
2502 if (is_gimple_call (stmt)
2503 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2504 == BUILT_IN_GOMP_CANCEL
2505 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2506 == BUILT_IN_GOMP_CANCELLATION_POINT))
2508 const char *bad = NULL;
2509 const char *kind = NULL;
2510 if (ctx == NULL)
2512 error_at (gimple_location (stmt), "orphaned %qs construct",
2513 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2514 == BUILT_IN_GOMP_CANCEL
2515 ? "#pragma omp cancel"
2516 : "#pragma omp cancellation point");
2517 return false;
2519 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2520 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2521 : 0)
2523 case 1:
2524 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2525 bad = "#pragma omp parallel";
2526 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2527 == BUILT_IN_GOMP_CANCEL
2528 && !integer_zerop (gimple_call_arg (stmt, 1)))
2529 ctx->cancellable = true;
2530 kind = "parallel";
2531 break;
2532 case 2:
2533 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2534 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2535 bad = "#pragma omp for";
2536 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2537 == BUILT_IN_GOMP_CANCEL
2538 && !integer_zerop (gimple_call_arg (stmt, 1)))
2540 ctx->cancellable = true;
2541 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2542 OMP_CLAUSE_NOWAIT))
2543 warning_at (gimple_location (stmt), 0,
2544 "%<#pragma omp cancel for%> inside "
2545 "%<nowait%> for construct");
2546 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2547 OMP_CLAUSE_ORDERED))
2548 warning_at (gimple_location (stmt), 0,
2549 "%<#pragma omp cancel for%> inside "
2550 "%<ordered%> for construct");
2552 kind = "for";
2553 break;
2554 case 4:
2555 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2556 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2557 bad = "#pragma omp sections";
2558 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2559 == BUILT_IN_GOMP_CANCEL
2560 && !integer_zerop (gimple_call_arg (stmt, 1)))
2562 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2564 ctx->cancellable = true;
2565 if (find_omp_clause (gimple_omp_sections_clauses
2566 (ctx->stmt),
2567 OMP_CLAUSE_NOWAIT))
2568 warning_at (gimple_location (stmt), 0,
2569 "%<#pragma omp cancel sections%> inside "
2570 "%<nowait%> sections construct");
2572 else
2574 gcc_assert (ctx->outer
2575 && gimple_code (ctx->outer->stmt)
2576 == GIMPLE_OMP_SECTIONS);
2577 ctx->outer->cancellable = true;
2578 if (find_omp_clause (gimple_omp_sections_clauses
2579 (ctx->outer->stmt),
2580 OMP_CLAUSE_NOWAIT))
2581 warning_at (gimple_location (stmt), 0,
2582 "%<#pragma omp cancel sections%> inside "
2583 "%<nowait%> sections construct");
2586 kind = "sections";
2587 break;
2588 case 8:
2589 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2590 bad = "#pragma omp task";
2591 else
2592 ctx->cancellable = true;
2593 kind = "taskgroup";
2594 break;
2595 default:
2596 error_at (gimple_location (stmt), "invalid arguments");
2597 return false;
2599 if (bad)
2601 error_at (gimple_location (stmt),
2602 "%<%s %s%> construct not closely nested inside of %qs",
2603 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2604 == BUILT_IN_GOMP_CANCEL
2605 ? "#pragma omp cancel"
2606 : "#pragma omp cancellation point", kind, bad);
2607 return false;
2610 /* FALLTHRU */
2611 case GIMPLE_OMP_SECTIONS:
2612 case GIMPLE_OMP_SINGLE:
2613 for (; ctx != NULL; ctx = ctx->outer)
2614 switch (gimple_code (ctx->stmt))
2616 case GIMPLE_OMP_FOR:
2617 case GIMPLE_OMP_SECTIONS:
2618 case GIMPLE_OMP_SINGLE:
2619 case GIMPLE_OMP_ORDERED:
2620 case GIMPLE_OMP_MASTER:
2621 case GIMPLE_OMP_TASK:
2622 case GIMPLE_OMP_CRITICAL:
2623 if (is_gimple_call (stmt))
2625 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2626 != BUILT_IN_GOMP_BARRIER)
2627 return true;
2628 error_at (gimple_location (stmt),
2629 "barrier region may not be closely nested inside "
2630 "of work-sharing, critical, ordered, master or "
2631 "explicit task region");
2632 return false;
2634 error_at (gimple_location (stmt),
2635 "work-sharing region may not be closely nested inside "
2636 "of work-sharing, critical, ordered, master or explicit "
2637 "task region");
2638 return false;
2639 case GIMPLE_OACC_KERNELS:
2640 case GIMPLE_OACC_PARALLEL:
2641 case GIMPLE_OMP_PARALLEL:
2642 return true;
2643 default:
2644 break;
2646 break;
2647 case GIMPLE_OMP_MASTER:
2648 for (; ctx != NULL; ctx = ctx->outer)
2649 switch (gimple_code (ctx->stmt))
2651 case GIMPLE_OMP_FOR:
2652 case GIMPLE_OMP_SECTIONS:
2653 case GIMPLE_OMP_SINGLE:
2654 case GIMPLE_OMP_TASK:
2655 error_at (gimple_location (stmt),
2656 "master region may not be closely nested inside "
2657 "of work-sharing or explicit task region");
2658 return false;
2659 case GIMPLE_OMP_PARALLEL:
2660 return true;
2661 default:
2662 break;
2664 break;
2665 case GIMPLE_OMP_ORDERED:
2666 for (; ctx != NULL; ctx = ctx->outer)
2667 switch (gimple_code (ctx->stmt))
2669 case GIMPLE_OMP_CRITICAL:
2670 case GIMPLE_OMP_TASK:
2671 error_at (gimple_location (stmt),
2672 "ordered region may not be closely nested inside "
2673 "of critical or explicit task region");
2674 return false;
2675 case GIMPLE_OMP_FOR:
2676 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2677 OMP_CLAUSE_ORDERED) == NULL)
2679 error_at (gimple_location (stmt),
2680 "ordered region must be closely nested inside "
2681 "a loop region with an ordered clause");
2682 return false;
2684 return true;
2685 case GIMPLE_OMP_PARALLEL:
2686 error_at (gimple_location (stmt),
2687 "ordered region must be closely nested inside "
2688 "a loop region with an ordered clause");
2689 return false;
2690 default:
2691 break;
2693 break;
2694 case GIMPLE_OMP_CRITICAL:
2695 for (; ctx != NULL; ctx = ctx->outer)
2696 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2697 && (gimple_omp_critical_name (stmt)
2698 == gimple_omp_critical_name (ctx->stmt)))
2700 error_at (gimple_location (stmt),
2701 "critical region may not be nested inside a critical "
2702 "region with the same name");
2703 return false;
2705 break;
2706 case GIMPLE_OMP_TEAMS:
2707 if (ctx == NULL
2708 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2709 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2711 error_at (gimple_location (stmt),
2712 "teams construct not closely nested inside of target "
2713 "region");
2714 return false;
2716 break;
2717 default:
2718 break;
2720 return true;
2724 /* Helper function scan_omp.
2726 Callback for walk_tree or operators in walk_gimple_stmt used to
2727 scan for OpenMP directives in TP. */
2729 static tree
2730 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2732 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2733 omp_context *ctx = (omp_context *) wi->info;
2734 tree t = *tp;
2736 switch (TREE_CODE (t))
2738 case VAR_DECL:
2739 case PARM_DECL:
2740 case LABEL_DECL:
2741 case RESULT_DECL:
2742 if (ctx)
2743 *tp = remap_decl (t, &ctx->cb);
2744 break;
2746 default:
2747 if (ctx && TYPE_P (t))
2748 *tp = remap_type (t, &ctx->cb);
2749 else if (!DECL_P (t))
2751 *walk_subtrees = 1;
2752 if (ctx)
2754 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2755 if (tem != TREE_TYPE (t))
2757 if (TREE_CODE (t) == INTEGER_CST)
2758 *tp = build_int_cst_wide (tem,
2759 TREE_INT_CST_LOW (t),
2760 TREE_INT_CST_HIGH (t));
2761 else
2762 TREE_TYPE (t) = tem;
2766 break;
2769 return NULL_TREE;
2772 /* Return true if FNDECL is a setjmp or a longjmp. */
2774 static bool
2775 setjmp_or_longjmp_p (const_tree fndecl)
2777 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2778 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2779 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2780 return true;
2782 tree declname = DECL_NAME (fndecl);
2783 if (!declname)
2784 return false;
2785 const char *name = IDENTIFIER_POINTER (declname);
2786 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2790 /* Helper function for scan_omp.
2792 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2793 the current statement in GSI. */
2795 static tree
2796 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2797 struct walk_stmt_info *wi)
2799 gimple stmt = gsi_stmt (*gsi);
2800 omp_context *ctx = (omp_context *) wi->info;
2802 if (gimple_has_location (stmt))
2803 input_location = gimple_location (stmt);
2805 /* Check the OpenMP nesting restrictions. */
2806 bool remove = false;
2807 if (is_gimple_omp (stmt))
2808 remove = !check_omp_nesting_restrictions (stmt, ctx);
2809 else if (is_gimple_call (stmt))
2811 tree fndecl = gimple_call_fndecl (stmt);
2812 if (fndecl)
2814 if (setjmp_or_longjmp_p (fndecl)
2815 && ctx
2816 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2817 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2819 remove = true;
2820 error_at (gimple_location (stmt),
2821 "setjmp/longjmp inside simd construct");
2823 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2824 switch (DECL_FUNCTION_CODE (fndecl))
2826 case BUILT_IN_GOMP_BARRIER:
2827 case BUILT_IN_GOMP_CANCEL:
2828 case BUILT_IN_GOMP_CANCELLATION_POINT:
2829 case BUILT_IN_GOMP_TASKYIELD:
2830 case BUILT_IN_GOMP_TASKWAIT:
2831 case BUILT_IN_GOMP_TASKGROUP_START:
2832 case BUILT_IN_GOMP_TASKGROUP_END:
2833 remove = !check_omp_nesting_restrictions (stmt, ctx);
2834 break;
2835 default:
2836 break;
2840 if (remove)
2842 stmt = gimple_build_nop ();
2843 gsi_replace (gsi, stmt, false);
2846 *handled_ops_p = true;
2848 switch (gimple_code (stmt))
2850 case GIMPLE_OACC_KERNELS:
2851 case GIMPLE_OACC_PARALLEL:
2852 scan_oacc_offload (stmt, ctx);
2853 break;
2855 case GIMPLE_OMP_PARALLEL:
2856 taskreg_nesting_level++;
2857 scan_omp_parallel (gsi, ctx);
2858 taskreg_nesting_level--;
2859 break;
2861 case GIMPLE_OMP_TASK:
2862 taskreg_nesting_level++;
2863 scan_omp_task (gsi, ctx);
2864 taskreg_nesting_level--;
2865 break;
2867 case GIMPLE_OMP_FOR:
2868 scan_omp_for (stmt, ctx);
2869 break;
2871 case GIMPLE_OMP_SECTIONS:
2872 scan_omp_sections (stmt, ctx);
2873 break;
2875 case GIMPLE_OMP_SINGLE:
2876 scan_omp_single (stmt, ctx);
2877 break;
2879 case GIMPLE_OMP_SECTION:
2880 case GIMPLE_OMP_MASTER:
2881 case GIMPLE_OMP_TASKGROUP:
2882 case GIMPLE_OMP_ORDERED:
2883 case GIMPLE_OMP_CRITICAL:
2884 ctx = new_omp_context (stmt, ctx);
2885 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2886 break;
2888 case GIMPLE_OMP_TARGET:
2889 scan_omp_target (stmt, ctx);
2890 break;
2892 case GIMPLE_OMP_TEAMS:
2893 scan_omp_teams (stmt, ctx);
2894 break;
2896 case GIMPLE_BIND:
2898 tree var;
2900 *handled_ops_p = false;
2901 if (ctx)
2902 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2903 insert_decl_map (&ctx->cb, var, var);
2905 break;
2906 default:
2907 *handled_ops_p = false;
2908 break;
2911 return NULL_TREE;
2915 /* Scan all the statements starting at the current statement. CTX
2916 contains context information about the OpenMP directives and
2917 clauses found during the scan. */
2919 static void
2920 scan_omp (gimple_seq *body_p, omp_context *ctx)
2922 location_t saved_location;
2923 struct walk_stmt_info wi;
2925 memset (&wi, 0, sizeof (wi));
2926 wi.info = ctx;
2927 wi.want_locations = true;
2929 saved_location = input_location;
2930 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2931 input_location = saved_location;
2934 /* Re-gimplification and code generation routines. */
2936 /* Build a call to GOMP_barrier. */
2938 static gimple
2939 build_omp_barrier (tree lhs)
2941 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2942 : BUILT_IN_GOMP_BARRIER);
2943 gimple g = gimple_build_call (fndecl, 0);
2944 if (lhs)
2945 gimple_call_set_lhs (g, lhs);
2946 return g;
2949 /* If a context was created for STMT when it was scanned, return it. */
2951 static omp_context *
2952 maybe_lookup_ctx (gimple stmt)
2954 splay_tree_node n;
2955 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2956 return n ? (omp_context *) n->value : NULL;
2960 /* Find the mapping for DECL in CTX or the immediately enclosing
2961 context that has a mapping for DECL.
2963 If CTX is a nested parallel directive, we may have to use the decl
2964 mappings created in CTX's parent context. Suppose that we have the
2965 following parallel nesting (variable UIDs showed for clarity):
2967 iD.1562 = 0;
2968 #omp parallel shared(iD.1562) -> outer parallel
2969 iD.1562 = iD.1562 + 1;
2971 #omp parallel shared (iD.1562) -> inner parallel
2972 iD.1562 = iD.1562 - 1;
2974 Each parallel structure will create a distinct .omp_data_s structure
2975 for copying iD.1562 in/out of the directive:
2977 outer parallel .omp_data_s.1.i -> iD.1562
2978 inner parallel .omp_data_s.2.i -> iD.1562
2980 A shared variable mapping will produce a copy-out operation before
2981 the parallel directive and a copy-in operation after it. So, in
2982 this case we would have:
2984 iD.1562 = 0;
2985 .omp_data_o.1.i = iD.1562;
2986 #omp parallel shared(iD.1562) -> outer parallel
2987 .omp_data_i.1 = &.omp_data_o.1
2988 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2990 .omp_data_o.2.i = iD.1562; -> **
2991 #omp parallel shared(iD.1562) -> inner parallel
2992 .omp_data_i.2 = &.omp_data_o.2
2993 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2996 ** This is a problem. The symbol iD.1562 cannot be referenced
2997 inside the body of the outer parallel region. But since we are
2998 emitting this copy operation while expanding the inner parallel
2999 directive, we need to access the CTX structure of the outer
3000 parallel directive to get the correct mapping:
3002 .omp_data_o.2.i = .omp_data_i.1->i
3004 Since there may be other workshare or parallel directives enclosing
3005 the parallel directive, it may be necessary to walk up the context
3006 parent chain. This is not a problem in general because nested
3007 parallelism happens only rarely. */
3009 static tree
3010 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3012 tree t;
3013 omp_context *up;
3015 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3016 t = maybe_lookup_decl (decl, up);
3018 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3020 return t ? t : decl;
3024 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3025 in outer contexts. */
3027 static tree
3028 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3030 tree t = NULL;
3031 omp_context *up;
3033 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3034 t = maybe_lookup_decl (decl, up);
3036 return t ? t : decl;
3040 /* Construct the initialization value for reduction CLAUSE. */
3042 tree
3043 omp_reduction_init (tree clause, tree type)
3045 location_t loc = OMP_CLAUSE_LOCATION (clause);
3046 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3048 case PLUS_EXPR:
3049 case MINUS_EXPR:
3050 case BIT_IOR_EXPR:
3051 case BIT_XOR_EXPR:
3052 case TRUTH_OR_EXPR:
3053 case TRUTH_ORIF_EXPR:
3054 case TRUTH_XOR_EXPR:
3055 case NE_EXPR:
3056 return build_zero_cst (type);
3058 case MULT_EXPR:
3059 case TRUTH_AND_EXPR:
3060 case TRUTH_ANDIF_EXPR:
3061 case EQ_EXPR:
3062 return fold_convert_loc (loc, type, integer_one_node);
3064 case BIT_AND_EXPR:
3065 return fold_convert_loc (loc, type, integer_minus_one_node);
3067 case MAX_EXPR:
3068 if (SCALAR_FLOAT_TYPE_P (type))
3070 REAL_VALUE_TYPE max, min;
3071 if (HONOR_INFINITIES (TYPE_MODE (type)))
3073 real_inf (&max);
3074 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3076 else
3077 real_maxval (&min, 1, TYPE_MODE (type));
3078 return build_real (type, min);
3080 else
3082 gcc_assert (INTEGRAL_TYPE_P (type));
3083 return TYPE_MIN_VALUE (type);
3086 case MIN_EXPR:
3087 if (SCALAR_FLOAT_TYPE_P (type))
3089 REAL_VALUE_TYPE max;
3090 if (HONOR_INFINITIES (TYPE_MODE (type)))
3091 real_inf (&max);
3092 else
3093 real_maxval (&max, 0, TYPE_MODE (type));
3094 return build_real (type, max);
3096 else
3098 gcc_assert (INTEGRAL_TYPE_P (type));
3099 return TYPE_MAX_VALUE (type);
3102 default:
3103 gcc_unreachable ();
3107 /* Return alignment to be assumed for var in CLAUSE, which should be
3108 OMP_CLAUSE_ALIGNED. */
3110 static tree
3111 omp_clause_aligned_alignment (tree clause)
3113 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3114 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3116 /* Otherwise return implementation defined alignment. */
3117 unsigned int al = 1;
3118 enum machine_mode mode, vmode;
3119 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3120 if (vs)
3121 vs = 1 << floor_log2 (vs);
3122 static enum mode_class classes[]
3123 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3124 for (int i = 0; i < 4; i += 2)
3125 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3126 mode != VOIDmode;
3127 mode = GET_MODE_WIDER_MODE (mode))
3129 vmode = targetm.vectorize.preferred_simd_mode (mode);
3130 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3131 continue;
3132 while (vs
3133 && GET_MODE_SIZE (vmode) < vs
3134 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3135 vmode = GET_MODE_2XWIDER_MODE (vmode);
3137 tree type = lang_hooks.types.type_for_mode (mode, 1);
3138 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3139 continue;
3140 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3141 / GET_MODE_SIZE (mode));
3142 if (TYPE_MODE (type) != vmode)
3143 continue;
3144 if (TYPE_ALIGN_UNIT (type) > al)
3145 al = TYPE_ALIGN_UNIT (type);
3147 return build_int_cst (integer_type_node, al);
3150 /* Return maximum possible vectorization factor for the target. */
3152 static int
3153 omp_max_vf (void)
3155 if (!optimize
3156 || optimize_debug
3157 || (!flag_tree_loop_vectorize
3158 && (global_options_set.x_flag_tree_loop_vectorize
3159 || global_options_set.x_flag_tree_vectorize)))
3160 return 1;
3162 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3163 if (vs)
3165 vs = 1 << floor_log2 (vs);
3166 return vs;
3168 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3169 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3170 return GET_MODE_NUNITS (vqimode);
3171 return 1;
3174 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3175 privatization. */
3177 static bool
3178 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3179 tree &idx, tree &lane, tree &ivar, tree &lvar)
3181 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
3183 if (max_vf == 0)
3185 max_vf = omp_max_vf ();
3186 if (max_vf > 1)
3188 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3189 OMP_CLAUSE_SAFELEN);
3190 if (c
3191 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
3192 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3194 if (max_vf > 1)
3196 idx = create_tmp_var (unsigned_type_node, NULL);
3197 lane = create_tmp_var (unsigned_type_node, NULL);
3200 if (max_vf == 1)
3201 return false;
3203 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3204 tree avar = create_tmp_var_raw (atype, NULL);
3205 if (TREE_ADDRESSABLE (new_var))
3206 TREE_ADDRESSABLE (avar) = 1;
3207 DECL_ATTRIBUTES (avar)
3208 = tree_cons (get_identifier ("omp simd array"), NULL,
3209 DECL_ATTRIBUTES (avar));
3210 gimple_add_tmp_var (avar);
3211 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3212 NULL_TREE, NULL_TREE);
3213 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3214 NULL_TREE, NULL_TREE);
3215 if (DECL_P (new_var))
3217 SET_DECL_VALUE_EXPR (new_var, lvar);
3218 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3220 return true;
3223 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3224 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3225 private variables. Initialization statements go in ILIST, while calls
3226 to destructors go in DLIST. */
3228 static void
3229 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3230 omp_context *ctx, struct omp_for_data *fd)
3232 tree c, dtor, copyin_seq, x, ptr;
3233 bool copyin_by_ref = false;
3234 bool lastprivate_firstprivate = false;
3235 bool reduction_omp_orig_ref = false;
3236 int pass;
3237 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3238 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3239 int max_vf = 0;
3240 tree lane = NULL_TREE, idx = NULL_TREE;
3241 tree ivar = NULL_TREE, lvar = NULL_TREE;
3242 gimple_seq llist[2] = { NULL, NULL };
3244 copyin_seq = NULL;
3246 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3247 with data sharing clauses referencing variable sized vars. That
3248 is unnecessarily hard to support and very unlikely to result in
3249 vectorized code anyway. */
3250 if (is_simd)
3251 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3252 switch (OMP_CLAUSE_CODE (c))
3254 case OMP_CLAUSE_REDUCTION:
3255 case OMP_CLAUSE_PRIVATE:
3256 case OMP_CLAUSE_FIRSTPRIVATE:
3257 case OMP_CLAUSE_LASTPRIVATE:
3258 case OMP_CLAUSE_LINEAR:
3259 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3260 max_vf = 1;
3261 break;
3262 default:
3263 continue;
3266 /* Do all the fixed sized types in the first pass, and the variable sized
3267 types in the second pass. This makes sure that the scalar arguments to
3268 the variable sized types are processed before we use them in the
3269 variable sized operations. */
3270 for (pass = 0; pass < 2; ++pass)
3272 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3274 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3275 tree var, new_var;
3276 bool by_ref;
3277 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3279 switch (c_kind)
3281 case OMP_CLAUSE_PRIVATE:
3282 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3283 continue;
3284 break;
3285 case OMP_CLAUSE_SHARED:
3286 /* Ignore shared directives in teams construct. */
3287 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3288 continue;
3289 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3291 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3292 continue;
3294 case OMP_CLAUSE_FIRSTPRIVATE:
3295 case OMP_CLAUSE_COPYIN:
3296 case OMP_CLAUSE_LINEAR:
3297 break;
3298 case OMP_CLAUSE_REDUCTION:
3299 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3300 reduction_omp_orig_ref = true;
3301 break;
3302 case OMP_CLAUSE__LOOPTEMP_:
3303 /* Handle _looptemp_ clauses only on parallel. */
3304 if (fd)
3305 continue;
3306 break;
3307 case OMP_CLAUSE_LASTPRIVATE:
3308 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3310 lastprivate_firstprivate = true;
3311 if (pass != 0)
3312 continue;
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 gimple 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 with placeholder in SIMD loop,
3415 defer adding the initialization of the reference,
3416 because if we decide to use SIMD array for it,
3417 the initilization could cause expansion ICE. */
3418 if (c_kind == OMP_CLAUSE_REDUCTION
3419 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
3420 && is_simd)
3421 x = NULL_TREE;
3422 else
3424 const char *name = NULL;
3425 if (DECL_NAME (var))
3426 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3428 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3429 name);
3430 gimple_add_tmp_var (x);
3431 TREE_ADDRESSABLE (x) = 1;
3432 x = build_fold_addr_expr_loc (clause_loc, x);
3435 else
3437 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3438 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3441 if (x)
3443 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3444 gimplify_assign (new_var, x, ilist);
3447 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3449 else if (c_kind == OMP_CLAUSE_REDUCTION
3450 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3452 if (pass == 0)
3453 continue;
3455 else if (pass != 0)
3456 continue;
3458 switch (OMP_CLAUSE_CODE (c))
3460 case OMP_CLAUSE_SHARED:
3461 /* Ignore shared directives in teams construct. */
3462 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3463 continue;
3464 /* Shared global vars are just accessed directly. */
3465 if (is_global_var (new_var))
3466 break;
3467 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3468 needs to be delayed until after fixup_child_record_type so
3469 that we get the correct type during the dereference. */
3470 by_ref = use_pointer_for_field (var, ctx);
3471 x = build_receiver_ref (var, by_ref, ctx);
3472 SET_DECL_VALUE_EXPR (new_var, x);
3473 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3475 /* ??? If VAR is not passed by reference, and the variable
3476 hasn't been initialized yet, then we'll get a warning for
3477 the store into the omp_data_s structure. Ideally, we'd be
3478 able to notice this and not store anything at all, but
3479 we're generating code too early. Suppress the warning. */
3480 if (!by_ref)
3481 TREE_NO_WARNING (var) = 1;
3482 break;
3484 case OMP_CLAUSE_LASTPRIVATE:
3485 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3486 break;
3487 /* FALLTHRU */
3489 case OMP_CLAUSE_PRIVATE:
3490 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3491 x = build_outer_var_ref (var, ctx);
3492 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3494 if (is_task_ctx (ctx))
3495 x = build_receiver_ref (var, false, ctx);
3496 else
3497 x = build_outer_var_ref (var, ctx);
3499 else
3500 x = NULL;
3501 do_private:
3502 tree nx;
3503 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3504 if (is_simd)
3506 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3507 if ((TREE_ADDRESSABLE (new_var) || nx || y
3508 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3509 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3510 idx, lane, ivar, lvar))
3512 if (nx)
3513 x = lang_hooks.decls.omp_clause_default_ctor
3514 (c, unshare_expr (ivar), x);
3515 if (nx && x)
3516 gimplify_and_add (x, &llist[0]);
3517 if (y)
3519 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3520 if (y)
3522 gimple_seq tseq = NULL;
3524 dtor = y;
3525 gimplify_stmt (&dtor, &tseq);
3526 gimple_seq_add_seq (&llist[1], tseq);
3529 break;
3532 if (nx)
3533 gimplify_and_add (nx, ilist);
3534 /* FALLTHRU */
3536 do_dtor:
3537 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3538 if (x)
3540 gimple_seq tseq = NULL;
3542 dtor = x;
3543 gimplify_stmt (&dtor, &tseq);
3544 gimple_seq_add_seq (dlist, tseq);
3546 break;
3548 case OMP_CLAUSE_LINEAR:
3549 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3550 goto do_firstprivate;
3551 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3552 x = NULL;
3553 else
3554 x = build_outer_var_ref (var, ctx);
3555 goto do_private;
3557 case OMP_CLAUSE_FIRSTPRIVATE:
3558 if (is_task_ctx (ctx))
3560 if (is_reference (var) || is_variable_sized (var))
3561 goto do_dtor;
3562 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3563 ctx))
3564 || use_pointer_for_field (var, NULL))
3566 x = build_receiver_ref (var, false, ctx);
3567 SET_DECL_VALUE_EXPR (new_var, x);
3568 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3569 goto do_dtor;
3572 do_firstprivate:
3573 x = build_outer_var_ref (var, ctx);
3574 if (is_simd)
3576 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3577 && gimple_omp_for_combined_into_p (ctx->stmt))
3579 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3580 ? sizetype : TREE_TYPE (x);
3581 tree t = fold_convert (stept,
3582 OMP_CLAUSE_LINEAR_STEP (c));
3583 tree c = find_omp_clause (clauses,
3584 OMP_CLAUSE__LOOPTEMP_);
3585 gcc_assert (c);
3586 tree l = OMP_CLAUSE_DECL (c);
3587 if (fd->collapse == 1)
3589 tree n1 = fd->loop.n1;
3590 tree step = fd->loop.step;
3591 tree itype = TREE_TYPE (l);
3592 if (POINTER_TYPE_P (itype))
3593 itype = signed_type_for (itype);
3594 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3595 if (TYPE_UNSIGNED (itype)
3596 && fd->loop.cond_code == GT_EXPR)
3597 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3598 fold_build1 (NEGATE_EXPR,
3599 itype, l),
3600 fold_build1 (NEGATE_EXPR,
3601 itype, step));
3602 else
3603 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3605 t = fold_build2 (MULT_EXPR, stept,
3606 fold_convert (stept, l), t);
3607 if (POINTER_TYPE_P (TREE_TYPE (x)))
3608 x = fold_build2 (POINTER_PLUS_EXPR,
3609 TREE_TYPE (x), x, t);
3610 else
3611 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3614 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3615 || TREE_ADDRESSABLE (new_var))
3616 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3617 idx, lane, ivar, lvar))
3619 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3621 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3622 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3623 gimplify_and_add (x, ilist);
3624 gimple_stmt_iterator gsi
3625 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3626 gimple g
3627 = gimple_build_assign (unshare_expr (lvar), iv);
3628 gsi_insert_before_without_update (&gsi, g,
3629 GSI_SAME_STMT);
3630 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3631 ? sizetype : TREE_TYPE (x);
3632 tree t = fold_convert (stept,
3633 OMP_CLAUSE_LINEAR_STEP (c));
3634 enum tree_code code = PLUS_EXPR;
3635 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3636 code = POINTER_PLUS_EXPR;
3637 g = gimple_build_assign_with_ops (code, iv, iv, t);
3638 gsi_insert_before_without_update (&gsi, g,
3639 GSI_SAME_STMT);
3640 break;
3642 x = lang_hooks.decls.omp_clause_copy_ctor
3643 (c, unshare_expr (ivar), x);
3644 gimplify_and_add (x, &llist[0]);
3645 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3646 if (x)
3648 gimple_seq tseq = NULL;
3650 dtor = x;
3651 gimplify_stmt (&dtor, &tseq);
3652 gimple_seq_add_seq (&llist[1], tseq);
3654 break;
3657 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3658 gimplify_and_add (x, ilist);
3659 goto do_dtor;
3661 case OMP_CLAUSE__LOOPTEMP_:
3662 gcc_assert (is_parallel_ctx (ctx));
3663 x = build_outer_var_ref (var, ctx);
3664 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3665 gimplify_and_add (x, ilist);
3666 break;
3668 case OMP_CLAUSE_COPYIN:
3669 by_ref = use_pointer_for_field (var, NULL);
3670 x = build_receiver_ref (var, by_ref, ctx);
3671 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3672 append_to_statement_list (x, &copyin_seq);
3673 copyin_by_ref |= by_ref;
3674 break;
3676 case OMP_CLAUSE_REDUCTION:
3677 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3679 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3680 gimple tseq;
3681 x = build_outer_var_ref (var, ctx);
3683 if (is_reference (var)
3684 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3685 TREE_TYPE (x)))
3686 x = build_fold_addr_expr_loc (clause_loc, x);
3687 SET_DECL_VALUE_EXPR (placeholder, x);
3688 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3689 tree new_vard = new_var;
3690 if (is_reference (var))
3692 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3693 new_vard = TREE_OPERAND (new_var, 0);
3694 gcc_assert (DECL_P (new_vard));
3696 if (is_simd
3697 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3698 idx, lane, ivar, lvar))
3700 if (new_vard == new_var)
3702 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3703 SET_DECL_VALUE_EXPR (new_var, ivar);
3705 else
3707 SET_DECL_VALUE_EXPR (new_vard,
3708 build_fold_addr_expr (ivar));
3709 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3711 x = lang_hooks.decls.omp_clause_default_ctor
3712 (c, unshare_expr (ivar),
3713 build_outer_var_ref (var, ctx));
3714 if (x)
3715 gimplify_and_add (x, &llist[0]);
3716 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3718 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3719 lower_omp (&tseq, ctx);
3720 gimple_seq_add_seq (&llist[0], tseq);
3722 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3723 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3724 lower_omp (&tseq, ctx);
3725 gimple_seq_add_seq (&llist[1], tseq);
3726 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3727 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3728 if (new_vard == new_var)
3729 SET_DECL_VALUE_EXPR (new_var, lvar);
3730 else
3731 SET_DECL_VALUE_EXPR (new_vard,
3732 build_fold_addr_expr (lvar));
3733 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3734 if (x)
3736 tseq = NULL;
3737 dtor = x;
3738 gimplify_stmt (&dtor, &tseq);
3739 gimple_seq_add_seq (&llist[1], tseq);
3741 break;
3743 /* If this is a reference to constant size reduction var
3744 with placeholder, we haven't emitted the initializer
3745 for it because it is undesirable if SIMD arrays are used.
3746 But if they aren't used, we need to emit the deferred
3747 initialization now. */
3748 else if (is_reference (var) && is_simd)
3750 tree z
3751 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3752 if (TREE_CONSTANT (z))
3754 const char *name = NULL;
3755 if (DECL_NAME (var))
3756 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3758 z = create_tmp_var_raw
3759 (TREE_TYPE (TREE_TYPE (new_vard)), name);
3760 gimple_add_tmp_var (z);
3761 TREE_ADDRESSABLE (z) = 1;
3762 z = build_fold_addr_expr_loc (clause_loc, z);
3763 gimplify_assign (new_vard, z, ilist);
3766 x = lang_hooks.decls.omp_clause_default_ctor
3767 (c, new_var, unshare_expr (x));
3768 if (x)
3769 gimplify_and_add (x, ilist);
3770 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3772 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3773 lower_omp (&tseq, ctx);
3774 gimple_seq_add_seq (ilist, tseq);
3776 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3777 if (is_simd)
3779 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3780 lower_omp (&tseq, ctx);
3781 gimple_seq_add_seq (dlist, tseq);
3782 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3784 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3785 goto do_dtor;
3787 else
3789 x = omp_reduction_init (c, TREE_TYPE (new_var));
3790 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3791 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3793 /* reduction(-:var) sums up the partial results, so it
3794 acts identically to reduction(+:var). */
3795 if (code == MINUS_EXPR)
3796 code = PLUS_EXPR;
3798 if (is_simd
3799 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3800 idx, lane, ivar, lvar))
3802 tree ref = build_outer_var_ref (var, ctx);
3804 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3806 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3807 ref = build_outer_var_ref (var, ctx);
3808 gimplify_assign (ref, x, &llist[1]);
3810 else
3812 gimplify_assign (new_var, x, ilist);
3813 if (is_simd)
3815 tree ref = build_outer_var_ref (var, ctx);
3817 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3818 ref = build_outer_var_ref (var, ctx);
3819 gimplify_assign (ref, x, dlist);
3823 break;
3825 default:
3826 gcc_unreachable ();
3831 if (lane)
3833 tree uid = create_tmp_var (ptr_type_node, "simduid");
3834 /* Don't want uninit warnings on simduid, it is always uninitialized,
3835 but we use it not for the value, but for the DECL_UID only. */
3836 TREE_NO_WARNING (uid) = 1;
3837 gimple g
3838 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3839 gimple_call_set_lhs (g, lane);
3840 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3841 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3842 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3843 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3844 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3845 gimple_omp_for_set_clauses (ctx->stmt, c);
3846 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3847 build_int_cst (unsigned_type_node, 0),
3848 NULL_TREE);
3849 gimple_seq_add_stmt (ilist, g);
3850 for (int i = 0; i < 2; i++)
3851 if (llist[i])
3853 tree vf = create_tmp_var (unsigned_type_node, NULL);
3854 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3855 gimple_call_set_lhs (g, vf);
3856 gimple_seq *seq = i == 0 ? ilist : dlist;
3857 gimple_seq_add_stmt (seq, g);
3858 tree t = build_int_cst (unsigned_type_node, 0);
3859 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3860 gimple_seq_add_stmt (seq, g);
3861 tree body = create_artificial_label (UNKNOWN_LOCATION);
3862 tree header = create_artificial_label (UNKNOWN_LOCATION);
3863 tree end = create_artificial_label (UNKNOWN_LOCATION);
3864 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3865 gimple_seq_add_stmt (seq, gimple_build_label (body));
3866 gimple_seq_add_seq (seq, llist[i]);
3867 t = build_int_cst (unsigned_type_node, 1);
3868 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3869 gimple_seq_add_stmt (seq, g);
3870 gimple_seq_add_stmt (seq, gimple_build_label (header));
3871 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3872 gimple_seq_add_stmt (seq, g);
3873 gimple_seq_add_stmt (seq, gimple_build_label (end));
3877 /* The copyin sequence is not to be executed by the main thread, since
3878 that would result in self-copies. Perhaps not visible to scalars,
3879 but it certainly is to C++ operator=. */
3880 if (copyin_seq)
3882 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3884 x = build2 (NE_EXPR, boolean_type_node, x,
3885 build_int_cst (TREE_TYPE (x), 0));
3886 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3887 gimplify_and_add (x, ilist);
3890 /* If any copyin variable is passed by reference, we must ensure the
3891 master thread doesn't modify it before it is copied over in all
3892 threads. Similarly for variables in both firstprivate and
3893 lastprivate clauses we need to ensure the lastprivate copying
3894 happens after firstprivate copying in all threads. And similarly
3895 for UDRs if initializer expression refers to omp_orig. */
3896 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3898 /* Don't add any barrier for #pragma omp simd or
3899 #pragma omp distribute. */
3900 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3901 || gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_FOR)
3902 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3905 /* If max_vf is non-zero, then we can use only a vectorization factor
3906 up to the max_vf we chose. So stick it into the safelen clause. */
3907 if (max_vf)
3909 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3910 OMP_CLAUSE_SAFELEN);
3911 if (c == NULL_TREE
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 gimple 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 gimple 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;
4033 x = build_outer_var_ref (var, ctx);
4034 if (is_reference (var))
4035 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4036 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4037 gimplify_and_add (x, stmt_list);
4039 c = OMP_CLAUSE_CHAIN (c);
4040 if (c == NULL && !par_clauses)
4042 /* If this was a workshare clause, see if it had been combined
4043 with its parallel. In that case, continue looking for the
4044 clauses also on the parallel statement itself. */
4045 if (is_parallel_ctx (ctx))
4046 break;
4048 ctx = ctx->outer;
4049 if (ctx == NULL || !is_parallel_ctx (ctx))
4050 break;
4052 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4053 OMP_CLAUSE_LASTPRIVATE);
4054 par_clauses = true;
4058 if (label)
4059 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4063 /* Generate code to implement the REDUCTION clauses. */
4065 static void
4066 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4068 gimple_seq sub_seq = NULL;
4069 gimple stmt;
4070 tree x, c;
4071 int count = 0;
4073 /* SIMD reductions are handled in lower_rec_input_clauses. */
4074 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4075 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4076 return;
4078 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4079 update in that case, otherwise use a lock. */
4080 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4081 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4083 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4085 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4086 count = -1;
4087 break;
4089 count++;
4092 if (count == 0)
4093 return;
4095 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4097 tree var, ref, new_var;
4098 enum tree_code code;
4099 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4101 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4102 continue;
4104 var = OMP_CLAUSE_DECL (c);
4105 new_var = lookup_decl (var, ctx);
4106 if (is_reference (var))
4107 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4108 ref = build_outer_var_ref (var, ctx);
4109 code = OMP_CLAUSE_REDUCTION_CODE (c);
4111 /* reduction(-:var) sums up the partial results, so it acts
4112 identically to reduction(+:var). */
4113 if (code == MINUS_EXPR)
4114 code = PLUS_EXPR;
4116 if (count == 1)
4118 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4120 addr = save_expr (addr);
4121 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4122 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4123 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4124 gimplify_and_add (x, stmt_seqp);
4125 return;
4128 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4130 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4132 if (is_reference (var)
4133 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4134 TREE_TYPE (ref)))
4135 ref = build_fold_addr_expr_loc (clause_loc, ref);
4136 SET_DECL_VALUE_EXPR (placeholder, ref);
4137 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4138 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4139 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4140 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4141 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4143 else
4145 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4146 ref = build_outer_var_ref (var, ctx);
4147 gimplify_assign (ref, x, &sub_seq);
4151 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4153 gimple_seq_add_stmt (stmt_seqp, stmt);
4155 gimple_seq_add_seq (stmt_seqp, sub_seq);
4157 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4159 gimple_seq_add_stmt (stmt_seqp, stmt);
4163 /* Generate code to implement the COPYPRIVATE clauses. */
4165 static void
4166 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4167 omp_context *ctx)
4169 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
4171 tree c;
4173 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4175 tree var, new_var, ref, x;
4176 bool by_ref;
4177 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4179 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4180 continue;
4182 var = OMP_CLAUSE_DECL (c);
4183 by_ref = use_pointer_for_field (var, NULL);
4185 ref = build_sender_ref (var, ctx);
4186 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4187 if (by_ref)
4189 x = build_fold_addr_expr_loc (clause_loc, new_var);
4190 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4192 gimplify_assign (ref, x, slist);
4194 ref = build_receiver_ref (var, false, ctx);
4195 if (by_ref)
4197 ref = fold_convert_loc (clause_loc,
4198 build_pointer_type (TREE_TYPE (new_var)),
4199 ref);
4200 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4202 if (is_reference (var))
4204 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4205 ref = build_simple_mem_ref_loc (clause_loc, ref);
4206 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4208 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4209 gimplify_and_add (x, rlist);
4214 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4215 and REDUCTION from the sender (aka parent) side. */
4217 static void
4218 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4219 omp_context *ctx)
4221 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
4223 tree c;
4225 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4227 tree val, ref, x, var;
4228 bool by_ref, do_in = false, do_out = false;
4229 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4231 switch (OMP_CLAUSE_CODE (c))
4233 case OMP_CLAUSE_PRIVATE:
4234 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4235 break;
4236 continue;
4237 case OMP_CLAUSE_FIRSTPRIVATE:
4238 case OMP_CLAUSE_COPYIN:
4239 case OMP_CLAUSE_LASTPRIVATE:
4240 case OMP_CLAUSE_REDUCTION:
4241 case OMP_CLAUSE__LOOPTEMP_:
4242 break;
4243 default:
4244 continue;
4247 val = OMP_CLAUSE_DECL (c);
4248 var = lookup_decl_in_outer_ctx (val, ctx);
4250 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4251 && is_global_var (var))
4252 continue;
4253 if (is_variable_sized (val))
4254 continue;
4255 by_ref = use_pointer_for_field (val, NULL);
4257 switch (OMP_CLAUSE_CODE (c))
4259 case OMP_CLAUSE_PRIVATE:
4260 case OMP_CLAUSE_FIRSTPRIVATE:
4261 case OMP_CLAUSE_COPYIN:
4262 case OMP_CLAUSE__LOOPTEMP_:
4263 do_in = true;
4264 break;
4266 case OMP_CLAUSE_LASTPRIVATE:
4267 if (by_ref || is_reference (val))
4269 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4270 continue;
4271 do_in = true;
4273 else
4275 do_out = true;
4276 if (lang_hooks.decls.omp_private_outer_ref (val))
4277 do_in = true;
4279 break;
4281 case OMP_CLAUSE_REDUCTION:
4282 do_in = true;
4283 do_out = !(by_ref || is_reference (val));
4284 break;
4286 default:
4287 gcc_unreachable ();
4290 if (do_in)
4292 ref = build_sender_ref (val, ctx);
4293 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4294 gimplify_assign (ref, x, ilist);
4295 if (is_task_ctx (ctx))
4296 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4299 if (do_out)
4301 ref = build_sender_ref (val, ctx);
4302 gimplify_assign (var, ref, olist);
4307 /* Generate code to implement SHARED from the sender (aka parent)
4308 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4309 list things that got automatically shared. */
4311 static void
4312 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4314 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
4316 tree var, ovar, nvar, f, x, record_type;
4318 if (ctx->record_type == NULL)
4319 return;
4321 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4322 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4324 ovar = DECL_ABSTRACT_ORIGIN (f);
4325 nvar = maybe_lookup_decl (ovar, ctx);
4326 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4327 continue;
4329 /* If CTX is a nested parallel directive. Find the immediately
4330 enclosing parallel or workshare construct that contains a
4331 mapping for OVAR. */
4332 var = lookup_decl_in_outer_ctx (ovar, ctx);
4334 if (use_pointer_for_field (ovar, ctx))
4336 x = build_sender_ref (ovar, ctx);
4337 var = build_fold_addr_expr (var);
4338 gimplify_assign (x, var, ilist);
4340 else
4342 x = build_sender_ref (ovar, ctx);
4343 gimplify_assign (x, var, ilist);
4345 if (!TREE_READONLY (var)
4346 /* We don't need to receive a new reference to a result
4347 or parm decl. In fact we may not store to it as we will
4348 invalidate any pending RSO and generate wrong gimple
4349 during inlining. */
4350 && !((TREE_CODE (var) == RESULT_DECL
4351 || TREE_CODE (var) == PARM_DECL)
4352 && DECL_BY_REFERENCE (var)))
4354 x = build_sender_ref (ovar, ctx);
4355 gimplify_assign (var, x, olist);
4362 /* A convenience function to build an empty GIMPLE_COND with just the
4363 condition. */
4365 static gimple
4366 gimple_build_cond_empty (tree cond)
4368 enum tree_code pred_code;
4369 tree lhs, rhs;
4371 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4372 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4376 /* Build the function calls to GOMP_parallel_start etc to actually
4377 generate the parallel operation. REGION is the parallel region
4378 being expanded. BB is the block where to insert the code. WS_ARGS
4379 will be set if this is a call to a combined parallel+workshare
4380 construct, it contains the list of additional arguments needed by
4381 the workshare construct. */
4383 static void
4384 expand_parallel_call (struct omp_region *region, basic_block bb,
4385 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4387 tree t, t1, t2, val, cond, c, clauses, flags;
4388 gimple_stmt_iterator gsi;
4389 gimple stmt;
4390 enum built_in_function start_ix;
4391 int start_ix2;
4392 location_t clause_loc;
4393 vec<tree, va_gc> *args;
4395 clauses = gimple_omp_parallel_clauses (entry_stmt);
4397 /* Determine what flavor of GOMP_parallel we will be
4398 emitting. */
4399 start_ix = BUILT_IN_GOMP_PARALLEL;
4400 if (is_combined_parallel (region))
4402 switch (region->inner->type)
4404 case GIMPLE_OMP_FOR:
4405 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4406 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4407 + (region->inner->sched_kind
4408 == OMP_CLAUSE_SCHEDULE_RUNTIME
4409 ? 3 : region->inner->sched_kind));
4410 start_ix = (enum built_in_function)start_ix2;
4411 break;
4412 case GIMPLE_OMP_SECTIONS:
4413 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4414 break;
4415 default:
4416 gcc_unreachable ();
4420 /* By default, the value of NUM_THREADS is zero (selected at run time)
4421 and there is no conditional. */
4422 cond = NULL_TREE;
4423 val = build_int_cst (unsigned_type_node, 0);
4424 flags = build_int_cst (unsigned_type_node, 0);
4426 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4427 if (c)
4428 cond = OMP_CLAUSE_IF_EXPR (c);
4430 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4431 if (c)
4433 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4434 clause_loc = OMP_CLAUSE_LOCATION (c);
4436 else
4437 clause_loc = gimple_location (entry_stmt);
4439 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4440 if (c)
4441 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4443 /* Ensure 'val' is of the correct type. */
4444 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4446 /* If we found the clause 'if (cond)', build either
4447 (cond != 0) or (cond ? val : 1u). */
4448 if (cond)
4450 gimple_stmt_iterator gsi;
4452 cond = gimple_boolify (cond);
4454 if (integer_zerop (val))
4455 val = fold_build2_loc (clause_loc,
4456 EQ_EXPR, unsigned_type_node, cond,
4457 build_int_cst (TREE_TYPE (cond), 0));
4458 else
4460 basic_block cond_bb, then_bb, else_bb;
4461 edge e, e_then, e_else;
4462 tree tmp_then, tmp_else, tmp_join, tmp_var;
4464 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4465 if (gimple_in_ssa_p (cfun))
4467 tmp_then = make_ssa_name (tmp_var, NULL);
4468 tmp_else = make_ssa_name (tmp_var, NULL);
4469 tmp_join = make_ssa_name (tmp_var, NULL);
4471 else
4473 tmp_then = tmp_var;
4474 tmp_else = tmp_var;
4475 tmp_join = tmp_var;
4478 e = split_block (bb, NULL);
4479 cond_bb = e->src;
4480 bb = e->dest;
4481 remove_edge (e);
4483 then_bb = create_empty_bb (cond_bb);
4484 else_bb = create_empty_bb (then_bb);
4485 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4486 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4488 stmt = gimple_build_cond_empty (cond);
4489 gsi = gsi_start_bb (cond_bb);
4490 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4492 gsi = gsi_start_bb (then_bb);
4493 stmt = gimple_build_assign (tmp_then, val);
4494 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4496 gsi = gsi_start_bb (else_bb);
4497 stmt = gimple_build_assign
4498 (tmp_else, build_int_cst (unsigned_type_node, 1));
4499 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4501 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4502 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4503 if (current_loops)
4505 add_bb_to_loop (then_bb, cond_bb->loop_father);
4506 add_bb_to_loop (else_bb, cond_bb->loop_father);
4508 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4509 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4511 if (gimple_in_ssa_p (cfun))
4513 gimple phi = create_phi_node (tmp_join, bb);
4514 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4515 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4518 val = tmp_join;
4521 gsi = gsi_start_bb (bb);
4522 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4523 false, GSI_CONTINUE_LINKING);
4526 gsi = gsi_last_bb (bb);
4527 t = gimple_omp_parallel_data_arg (entry_stmt);
4528 if (t == NULL)
4529 t1 = null_pointer_node;
4530 else
4531 t1 = build_fold_addr_expr (t);
4532 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4534 vec_alloc (args, 4 + vec_safe_length (ws_args));
4535 args->quick_push (t2);
4536 args->quick_push (t1);
4537 args->quick_push (val);
4538 if (ws_args)
4539 args->splice (*ws_args);
4540 args->quick_push (flags);
4542 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4543 builtin_decl_explicit (start_ix), args);
4545 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4546 false, GSI_CONTINUE_LINKING);
4550 /* Build the function call to GOMP_task to actually
4551 generate the task operation. BB is the block where to insert the code. */
4553 static void
4554 expand_task_call (basic_block bb, gimple entry_stmt)
4556 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4557 gimple_stmt_iterator gsi;
4558 location_t loc = gimple_location (entry_stmt);
4560 clauses = gimple_omp_task_clauses (entry_stmt);
4562 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4563 if (c)
4564 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4565 else
4566 cond = boolean_true_node;
4568 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4569 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4570 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4571 flags = build_int_cst (unsigned_type_node,
4572 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4574 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4575 if (c)
4577 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4578 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4579 build_int_cst (unsigned_type_node, 2),
4580 build_int_cst (unsigned_type_node, 0));
4581 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4583 if (depend)
4584 depend = OMP_CLAUSE_DECL (depend);
4585 else
4586 depend = build_int_cst (ptr_type_node, 0);
4588 gsi = gsi_last_bb (bb);
4589 t = gimple_omp_task_data_arg (entry_stmt);
4590 if (t == NULL)
4591 t2 = null_pointer_node;
4592 else
4593 t2 = build_fold_addr_expr_loc (loc, t);
4594 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4595 t = gimple_omp_task_copy_fn (entry_stmt);
4596 if (t == NULL)
4597 t3 = null_pointer_node;
4598 else
4599 t3 = build_fold_addr_expr_loc (loc, t);
4601 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4602 8, t1, t2, t3,
4603 gimple_omp_task_arg_size (entry_stmt),
4604 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4605 depend);
4607 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4608 false, GSI_CONTINUE_LINKING);
4612 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4613 catch handler and return it. This prevents programs from violating the
4614 structured block semantics with throws. */
4616 static gimple_seq
4617 maybe_catch_exception (gimple_seq body)
4619 gimple g;
4620 tree decl;
4622 if (!flag_exceptions)
4623 return body;
4625 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4626 decl = lang_hooks.eh_protect_cleanup_actions ();
4627 else
4628 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4630 g = gimple_build_eh_must_not_throw (decl);
4631 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4632 GIMPLE_TRY_CATCH);
4634 return gimple_seq_alloc_with_stmt (g);
4637 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4639 static tree
4640 vec2chain (vec<tree, va_gc> *v)
4642 tree chain = NULL_TREE, t;
4643 unsigned ix;
4645 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4647 DECL_CHAIN (t) = chain;
4648 chain = t;
4651 return chain;
4655 /* Remove barriers in REGION->EXIT's block. Note that this is only
4656 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4657 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4658 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4659 removed. */
4661 static void
4662 remove_exit_barrier (struct omp_region *region)
4664 gimple_stmt_iterator gsi;
4665 basic_block exit_bb;
4666 edge_iterator ei;
4667 edge e;
4668 gimple stmt;
4669 int any_addressable_vars = -1;
4671 exit_bb = region->exit;
4673 /* If the parallel region doesn't return, we don't have REGION->EXIT
4674 block at all. */
4675 if (! exit_bb)
4676 return;
4678 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4679 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4680 statements that can appear in between are extremely limited -- no
4681 memory operations at all. Here, we allow nothing at all, so the
4682 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4683 gsi = gsi_last_bb (exit_bb);
4684 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4685 gsi_prev (&gsi);
4686 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4687 return;
4689 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4691 gsi = gsi_last_bb (e->src);
4692 if (gsi_end_p (gsi))
4693 continue;
4694 stmt = gsi_stmt (gsi);
4695 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4696 && !gimple_omp_return_nowait_p (stmt))
4698 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4699 in many cases. If there could be tasks queued, the barrier
4700 might be needed to let the tasks run before some local
4701 variable of the parallel that the task uses as shared
4702 runs out of scope. The task can be spawned either
4703 from within current function (this would be easy to check)
4704 or from some function it calls and gets passed an address
4705 of such a variable. */
4706 if (any_addressable_vars < 0)
4708 gimple parallel_stmt = last_stmt (region->entry);
4709 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4710 tree local_decls, block, decl;
4711 unsigned ix;
4713 any_addressable_vars = 0;
4714 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4715 if (TREE_ADDRESSABLE (decl))
4717 any_addressable_vars = 1;
4718 break;
4720 for (block = gimple_block (stmt);
4721 !any_addressable_vars
4722 && block
4723 && TREE_CODE (block) == BLOCK;
4724 block = BLOCK_SUPERCONTEXT (block))
4726 for (local_decls = BLOCK_VARS (block);
4727 local_decls;
4728 local_decls = DECL_CHAIN (local_decls))
4729 if (TREE_ADDRESSABLE (local_decls))
4731 any_addressable_vars = 1;
4732 break;
4734 if (block == gimple_block (parallel_stmt))
4735 break;
4738 if (!any_addressable_vars)
4739 gimple_omp_return_set_nowait (stmt);
4744 static void
4745 remove_exit_barriers (struct omp_region *region)
4747 if (region->type == GIMPLE_OMP_PARALLEL)
4748 remove_exit_barrier (region);
4750 if (region->inner)
4752 region = region->inner;
4753 remove_exit_barriers (region);
4754 while (region->next)
4756 region = region->next;
4757 remove_exit_barriers (region);
4762 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4763 calls. These can't be declared as const functions, but
4764 within one parallel body they are constant, so they can be
4765 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4766 which are declared const. Similarly for task body, except
4767 that in untied task omp_get_thread_num () can change at any task
4768 scheduling point. */
4770 static void
4771 optimize_omp_library_calls (gimple entry_stmt)
4773 basic_block bb;
4774 gimple_stmt_iterator gsi;
4775 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4776 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4777 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4778 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4779 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4780 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4781 OMP_CLAUSE_UNTIED) != NULL);
4783 FOR_EACH_BB_FN (bb, cfun)
4784 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4786 gimple call = gsi_stmt (gsi);
4787 tree decl;
4789 if (is_gimple_call (call)
4790 && (decl = gimple_call_fndecl (call))
4791 && DECL_EXTERNAL (decl)
4792 && TREE_PUBLIC (decl)
4793 && DECL_INITIAL (decl) == NULL)
4795 tree built_in;
4797 if (DECL_NAME (decl) == thr_num_id)
4799 /* In #pragma omp task untied omp_get_thread_num () can change
4800 during the execution of the task region. */
4801 if (untied_task)
4802 continue;
4803 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4805 else if (DECL_NAME (decl) == num_thr_id)
4806 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4807 else
4808 continue;
4810 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4811 || gimple_call_num_args (call) != 0)
4812 continue;
4814 if (flag_exceptions && !TREE_NOTHROW (decl))
4815 continue;
4817 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4818 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4819 TREE_TYPE (TREE_TYPE (built_in))))
4820 continue;
4822 gimple_call_set_fndecl (call, built_in);
4827 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4828 regimplified. */
4830 static tree
4831 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4833 tree t = *tp;
4835 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4836 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4837 return t;
4839 if (TREE_CODE (t) == ADDR_EXPR)
4840 recompute_tree_invariant_for_addr_expr (t);
4842 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4843 return NULL_TREE;
4846 /* Prepend TO = FROM assignment before *GSI_P. */
4848 static void
4849 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4851 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4852 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4853 true, GSI_SAME_STMT);
4854 gimple stmt = gimple_build_assign (to, from);
4855 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4856 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4857 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4859 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4860 gimple_regimplify_operands (stmt, &gsi);
4864 /* Expand the OpenACC offload directive starting at REGION. */
4866 static void
4867 expand_oacc_offload (struct omp_region *region)
4869 basic_block entry_bb, exit_bb, new_bb;
4870 struct function *child_cfun;
4871 tree child_fn, block, t;
4872 gimple_stmt_iterator gsi;
4873 gimple entry_stmt, stmt;
4874 edge e;
4875 tree (*gimple_omp_child_fn) (const_gimple);
4876 tree (*gimple_omp_data_arg) (const_gimple);
4877 switch (region->type)
4879 case GIMPLE_OACC_KERNELS:
4880 gimple_omp_child_fn = gimple_oacc_kernels_child_fn;
4881 gimple_omp_data_arg = gimple_oacc_kernels_data_arg;
4882 break;
4883 case GIMPLE_OACC_PARALLEL:
4884 gimple_omp_child_fn = gimple_oacc_parallel_child_fn;
4885 gimple_omp_data_arg = gimple_oacc_parallel_data_arg;
4886 break;
4887 default:
4888 gcc_unreachable ();
4891 entry_stmt = last_stmt (region->entry);
4892 child_fn = gimple_omp_child_fn (entry_stmt);
4893 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4895 /* Supported by expand_omp_taskreg, but not here. */
4896 gcc_assert (!child_cfun->cfg);
4897 gcc_assert (!gimple_in_ssa_p (cfun));
4899 entry_bb = region->entry;
4900 exit_bb = region->exit;
4902 /* Preserve indentation of expand_omp_target and expand_omp_taskreg. */
4903 if (1)
4905 unsigned srcidx, dstidx, num;
4907 /* If the parallel region needs data sent from the parent
4908 function, then the very first statement (except possible
4909 tree profile counter updates) of the parallel body
4910 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4911 &.OMP_DATA_O is passed as an argument to the child function,
4912 we need to replace it with the argument as seen by the child
4913 function.
4915 In most cases, this will end up being the identity assignment
4916 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4917 a function call that has been inlined, the original PARM_DECL
4918 .OMP_DATA_I may have been converted into a different local
4919 variable. In which case, we need to keep the assignment. */
4920 if (gimple_omp_data_arg (entry_stmt))
4922 basic_block entry_succ_bb = single_succ (entry_bb);
4923 gimple_stmt_iterator gsi;
4924 tree arg;
4925 gimple parcopy_stmt = NULL;
4926 tree sender = TREE_VEC_ELT (gimple_omp_data_arg (entry_stmt), 0);
4928 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4930 gcc_assert (!gsi_end_p (gsi));
4931 stmt = gsi_stmt (gsi);
4932 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4933 continue;
4935 if (gimple_num_ops (stmt) == 2)
4937 tree arg = gimple_assign_rhs1 (stmt);
4939 /* We're ignore the subcode because we're
4940 effectively doing a STRIP_NOPS. */
4942 if (TREE_CODE (arg) == ADDR_EXPR
4943 && TREE_OPERAND (arg, 0) == sender)
4945 parcopy_stmt = stmt;
4946 break;
4951 gcc_assert (parcopy_stmt != NULL);
4952 arg = DECL_ARGUMENTS (child_fn);
4954 gcc_assert (gimple_assign_lhs (parcopy_stmt) == arg);
4955 gsi_remove (&gsi, true);
4958 /* Declare local variables needed in CHILD_CFUN. */
4959 block = DECL_INITIAL (child_fn);
4960 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4961 /* The gimplifier could record temporaries in the block
4962 rather than in containing function's local_decls chain,
4963 which would mean cgraph missed finalizing them. Do it now. */
4964 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4965 if (TREE_CODE (t) == VAR_DECL
4966 && TREE_STATIC (t)
4967 && !DECL_EXTERNAL (t))
4968 varpool_finalize_decl (t);
4969 DECL_SAVED_TREE (child_fn) = NULL;
4970 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4971 gimple_set_body (child_fn, NULL);
4972 TREE_USED (block) = 1;
4974 /* Reset DECL_CONTEXT on function arguments. */
4975 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
4976 DECL_CONTEXT (t) = child_fn;
4978 /* Split ENTRY_BB at GIMPLE_OACC_PARALLEL,
4979 so that it can be moved to the child function. */
4980 gsi = gsi_last_bb (entry_bb);
4981 stmt = gsi_stmt (gsi);
4982 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OACC_KERNELS
4983 || gimple_code (stmt) == GIMPLE_OACC_PARALLEL));
4984 gsi_remove (&gsi, true);
4985 e = split_block (entry_bb, stmt);
4986 entry_bb = e->dest;
4987 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4989 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4990 if (exit_bb)
4992 gsi = gsi_last_bb (exit_bb);
4993 gcc_assert (!gsi_end_p (gsi)
4994 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4995 stmt = gimple_build_return (NULL);
4996 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4997 gsi_remove (&gsi, true);
5000 /* Move the region into CHILD_CFUN. */
5002 block = gimple_block (entry_stmt);
5004 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5005 if (exit_bb)
5006 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5007 /* When the expansion process cannot guarantee an up-to-date
5008 loop tree arrange for the child function to fixup loops. */
5009 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5010 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5012 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5013 num = vec_safe_length (child_cfun->local_decls);
5014 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5016 t = (*child_cfun->local_decls)[srcidx];
5017 if (DECL_CONTEXT (t) == cfun->decl)
5018 continue;
5019 if (srcidx != dstidx)
5020 (*child_cfun->local_decls)[dstidx] = t;
5021 dstidx++;
5023 if (dstidx != num)
5024 vec_safe_truncate (child_cfun->local_decls, dstidx);
5026 /* Inform the callgraph about the new function. */
5027 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5028 cgraph_add_new_function (child_fn, true);
5030 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5031 fixed in a following pass. */
5032 push_cfun (child_cfun);
5033 rebuild_cgraph_edges ();
5035 /* Some EH regions might become dead, see PR34608. If
5036 pass_cleanup_cfg isn't the first pass to happen with the
5037 new child, these dead EH edges might cause problems.
5038 Clean them up now. */
5039 if (flag_exceptions)
5041 basic_block bb;
5042 bool changed = false;
5044 FOR_EACH_BB_FN (bb, cfun)
5045 changed |= gimple_purge_dead_eh_edges (bb);
5046 if (changed)
5047 cleanup_tree_cfg ();
5049 pop_cfun ();
5052 /* Emit a library call to launch CHILD_FN. */
5053 tree t1, t2, t3, t4,
5054 t_num_gangs, t_num_workers, t_vector_length,
5055 device, c, clauses;
5056 enum built_in_function start_ix;
5057 location_t clause_loc;
5058 tree (*gimple_omp_clauses) (const_gimple);
5059 switch (region->type)
5061 case GIMPLE_OACC_KERNELS:
5062 gimple_omp_clauses = gimple_oacc_kernels_clauses;
5063 start_ix = BUILT_IN_GOACC_KERNELS;
5064 break;
5065 case GIMPLE_OACC_PARALLEL:
5066 gimple_omp_clauses = gimple_oacc_parallel_clauses;
5067 start_ix = BUILT_IN_GOACC_PARALLEL;
5068 break;
5069 default:
5070 gcc_unreachable ();
5073 clauses = gimple_omp_clauses (entry_stmt);
5075 /* Default values for NUM_GANGS, NUM_WORKERS, and VECTOR_LENGTH. */
5076 t_num_gangs = t_num_workers = t_vector_length
5077 = fold_convert_loc (gimple_location (entry_stmt),
5078 integer_type_node, integer_one_node);
5079 switch (region->type)
5081 case GIMPLE_OACC_PARALLEL:
5082 /* ..., but if present, use the values specified by the respective
5083 clauses, making sure these are of the correct type. */
5084 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
5085 if (c)
5086 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
5087 integer_type_node,
5088 OMP_CLAUSE_NUM_GANGS_EXPR (c));
5089 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
5090 if (c)
5091 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
5092 integer_type_node,
5093 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
5094 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
5095 if (c)
5096 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
5097 integer_type_node,
5098 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
5099 break;
5101 default:
5102 break;
5105 /* By default, the value of DEVICE is -1 (let runtime library choose). */
5106 device = build_int_cst (integer_type_node, -1);
5108 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
5109 gcc_assert (c == NULL);
5110 if (c)
5112 device = OMP_CLAUSE_DEVICE_ID (c);
5113 clause_loc = OMP_CLAUSE_LOCATION (c);
5115 else
5116 clause_loc = gimple_location (entry_stmt);
5118 /* Ensure 'device' is of the correct type. */
5119 device = fold_convert_loc (clause_loc, integer_type_node, device);
5121 gsi = gsi_last_bb (new_bb);
5122 t = gimple_omp_data_arg (entry_stmt);
5123 if (t == NULL)
5125 t1 = size_zero_node;
5126 t2 = build_zero_cst (ptr_type_node);
5127 t3 = t2;
5128 t4 = t2;
5130 else
5132 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
5133 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
5134 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
5135 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
5136 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
5139 gimple g;
5140 /* FIXME: This will be address of
5141 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
5142 symbol, as soon as the linker plugin is able to create it for us. */
5143 tree openmp_target = build_zero_cst (ptr_type_node);
5144 tree fnaddr = build_fold_addr_expr (child_fn);
5145 g = gimple_build_call (builtin_decl_explicit (start_ix),
5146 10, device, fnaddr, openmp_target, t1, t2, t3, t4,
5147 t_num_gangs, t_num_workers, t_vector_length);
5148 gimple_set_location (g, gimple_location (entry_stmt));
5149 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
5152 /* Expand the OpenMP parallel or task directive starting at REGION. */
5154 static void
5155 expand_omp_taskreg (struct omp_region *region)
5157 basic_block entry_bb, exit_bb, new_bb;
5158 struct function *child_cfun;
5159 tree child_fn, block, t;
5160 gimple_stmt_iterator gsi;
5161 gimple entry_stmt, stmt;
5162 edge e;
5163 vec<tree, va_gc> *ws_args;
5165 entry_stmt = last_stmt (region->entry);
5166 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5167 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5169 entry_bb = region->entry;
5170 exit_bb = region->exit;
5172 if (is_combined_parallel (region))
5173 ws_args = region->ws_args;
5174 else
5175 ws_args = NULL;
5177 if (child_cfun->cfg)
5179 /* Due to inlining, it may happen that we have already outlined
5180 the region, in which case all we need to do is make the
5181 sub-graph unreachable and emit the parallel call. */
5182 edge entry_succ_e, exit_succ_e;
5183 gimple_stmt_iterator gsi;
5185 entry_succ_e = single_succ_edge (entry_bb);
5187 gsi = gsi_last_bb (entry_bb);
5188 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5189 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5190 gsi_remove (&gsi, true);
5192 new_bb = entry_bb;
5193 if (exit_bb)
5195 exit_succ_e = single_succ_edge (exit_bb);
5196 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5198 remove_edge_and_dominated_blocks (entry_succ_e);
5200 else
5202 unsigned srcidx, dstidx, num;
5204 /* If the parallel region needs data sent from the parent
5205 function, then the very first statement (except possible
5206 tree profile counter updates) of the parallel body
5207 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5208 &.OMP_DATA_O is passed as an argument to the child function,
5209 we need to replace it with the argument as seen by the child
5210 function.
5212 In most cases, this will end up being the identity assignment
5213 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5214 a function call that has been inlined, the original PARM_DECL
5215 .OMP_DATA_I may have been converted into a different local
5216 variable. In which case, we need to keep the assignment. */
5217 if (gimple_omp_taskreg_data_arg (entry_stmt))
5219 basic_block entry_succ_bb = single_succ (entry_bb);
5220 gimple_stmt_iterator gsi;
5221 tree arg, narg;
5222 gimple parcopy_stmt = NULL;
5224 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5226 gimple stmt;
5228 gcc_assert (!gsi_end_p (gsi));
5229 stmt = gsi_stmt (gsi);
5230 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5231 continue;
5233 if (gimple_num_ops (stmt) == 2)
5235 tree arg = gimple_assign_rhs1 (stmt);
5237 /* We're ignore the subcode because we're
5238 effectively doing a STRIP_NOPS. */
5240 if (TREE_CODE (arg) == ADDR_EXPR
5241 && TREE_OPERAND (arg, 0)
5242 == gimple_omp_taskreg_data_arg (entry_stmt))
5244 parcopy_stmt = stmt;
5245 break;
5250 gcc_assert (parcopy_stmt != NULL);
5251 arg = DECL_ARGUMENTS (child_fn);
5253 if (!gimple_in_ssa_p (cfun))
5255 if (gimple_assign_lhs (parcopy_stmt) == arg)
5256 gsi_remove (&gsi, true);
5257 else
5259 /* ?? Is setting the subcode really necessary ?? */
5260 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5261 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5264 else
5266 /* If we are in ssa form, we must load the value from the default
5267 definition of the argument. That should not be defined now,
5268 since the argument is not used uninitialized. */
5269 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5270 narg = make_ssa_name (arg, gimple_build_nop ());
5271 set_ssa_default_def (cfun, arg, narg);
5272 /* ?? Is setting the subcode really necessary ?? */
5273 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5274 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5275 update_stmt (parcopy_stmt);
5279 /* Declare local variables needed in CHILD_CFUN. */
5280 block = DECL_INITIAL (child_fn);
5281 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5282 /* The gimplifier could record temporaries in parallel/task block
5283 rather than in containing function's local_decls chain,
5284 which would mean cgraph missed finalizing them. Do it now. */
5285 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5286 if (TREE_CODE (t) == VAR_DECL
5287 && TREE_STATIC (t)
5288 && !DECL_EXTERNAL (t))
5289 varpool_finalize_decl (t);
5290 DECL_SAVED_TREE (child_fn) = NULL;
5291 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5292 gimple_set_body (child_fn, NULL);
5293 TREE_USED (block) = 1;
5295 /* Reset DECL_CONTEXT on function arguments. */
5296 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5297 DECL_CONTEXT (t) = child_fn;
5299 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5300 so that it can be moved to the child function. */
5301 gsi = gsi_last_bb (entry_bb);
5302 stmt = gsi_stmt (gsi);
5303 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5304 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5305 gsi_remove (&gsi, true);
5306 e = split_block (entry_bb, stmt);
5307 entry_bb = e->dest;
5308 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5310 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5311 if (exit_bb)
5313 gsi = gsi_last_bb (exit_bb);
5314 gcc_assert (!gsi_end_p (gsi)
5315 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5316 stmt = gimple_build_return (NULL);
5317 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5318 gsi_remove (&gsi, true);
5321 /* Move the parallel region into CHILD_CFUN. */
5323 if (gimple_in_ssa_p (cfun))
5325 init_tree_ssa (child_cfun);
5326 init_ssa_operands (child_cfun);
5327 child_cfun->gimple_df->in_ssa_p = true;
5328 block = NULL_TREE;
5330 else
5331 block = gimple_block (entry_stmt);
5333 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5334 if (exit_bb)
5335 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5336 /* When the OMP expansion process cannot guarantee an up-to-date
5337 loop tree arrange for the child function to fixup loops. */
5338 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5339 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5341 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5342 num = vec_safe_length (child_cfun->local_decls);
5343 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5345 t = (*child_cfun->local_decls)[srcidx];
5346 if (DECL_CONTEXT (t) == cfun->decl)
5347 continue;
5348 if (srcidx != dstidx)
5349 (*child_cfun->local_decls)[dstidx] = t;
5350 dstidx++;
5352 if (dstidx != num)
5353 vec_safe_truncate (child_cfun->local_decls, dstidx);
5355 /* Inform the callgraph about the new function. */
5356 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5357 cgraph_add_new_function (child_fn, true);
5359 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5360 fixed in a following pass. */
5361 push_cfun (child_cfun);
5362 if (optimize)
5363 optimize_omp_library_calls (entry_stmt);
5364 rebuild_cgraph_edges ();
5366 /* Some EH regions might become dead, see PR34608. If
5367 pass_cleanup_cfg isn't the first pass to happen with the
5368 new child, these dead EH edges might cause problems.
5369 Clean them up now. */
5370 if (flag_exceptions)
5372 basic_block bb;
5373 bool changed = false;
5375 FOR_EACH_BB_FN (bb, cfun)
5376 changed |= gimple_purge_dead_eh_edges (bb);
5377 if (changed)
5378 cleanup_tree_cfg ();
5380 if (gimple_in_ssa_p (cfun))
5381 update_ssa (TODO_update_ssa);
5382 pop_cfun ();
5385 /* Emit a library call to launch the children threads. */
5386 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5387 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
5388 else
5389 expand_task_call (new_bb, entry_stmt);
5390 if (gimple_in_ssa_p (cfun))
5391 update_ssa (TODO_update_ssa_only_virtuals);
5395 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5396 of the combined collapse > 1 loop constructs, generate code like:
5397 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5398 if (cond3 is <)
5399 adj = STEP3 - 1;
5400 else
5401 adj = STEP3 + 1;
5402 count3 = (adj + N32 - N31) / STEP3;
5403 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5404 if (cond2 is <)
5405 adj = STEP2 - 1;
5406 else
5407 adj = STEP2 + 1;
5408 count2 = (adj + N22 - N21) / STEP2;
5409 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5410 if (cond1 is <)
5411 adj = STEP1 - 1;
5412 else
5413 adj = STEP1 + 1;
5414 count1 = (adj + N12 - N11) / STEP1;
5415 count = count1 * count2 * count3;
5416 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5417 count = 0;
5418 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5419 of the combined loop constructs, just initialize COUNTS array
5420 from the _looptemp_ clauses. */
5422 /* NOTE: It *could* be better to moosh all of the BBs together,
5423 creating one larger BB with all the computation and the unexpected
5424 jump at the end. I.e.
5426 bool zero3, zero2, zero1, zero;
5428 zero3 = N32 c3 N31;
5429 count3 = (N32 - N31) /[cl] STEP3;
5430 zero2 = N22 c2 N21;
5431 count2 = (N22 - N21) /[cl] STEP2;
5432 zero1 = N12 c1 N11;
5433 count1 = (N12 - N11) /[cl] STEP1;
5434 zero = zero3 || zero2 || zero1;
5435 count = count1 * count2 * count3;
5436 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5438 After all, we expect the zero=false, and thus we expect to have to
5439 evaluate all of the comparison expressions, so short-circuiting
5440 oughtn't be a win. Since the condition isn't protecting a
5441 denominator, we're not concerned about divide-by-zero, so we can
5442 fully evaluate count even if a numerator turned out to be wrong.
5444 It seems like putting this all together would create much better
5445 scheduling opportunities, and less pressure on the chip's branch
5446 predictor. */
5448 static void
5449 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5450 basic_block &entry_bb, tree *counts,
5451 basic_block &zero_iter_bb, int &first_zero_iter,
5452 basic_block &l2_dom_bb)
5454 tree t, type = TREE_TYPE (fd->loop.v);
5455 gimple stmt;
5456 edge e, ne;
5457 int i;
5459 /* Collapsed loops need work for expansion into SSA form. */
5460 gcc_assert (!gimple_in_ssa_p (cfun));
5462 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5463 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5465 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5466 isn't supposed to be handled, as the inner loop doesn't
5467 use it. */
5468 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5469 OMP_CLAUSE__LOOPTEMP_);
5470 gcc_assert (innerc);
5471 for (i = 0; i < fd->collapse; i++)
5473 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5474 OMP_CLAUSE__LOOPTEMP_);
5475 gcc_assert (innerc);
5476 if (i)
5477 counts[i] = OMP_CLAUSE_DECL (innerc);
5478 else
5479 counts[0] = NULL_TREE;
5481 return;
5484 for (i = 0; i < fd->collapse; i++)
5486 tree itype = TREE_TYPE (fd->loops[i].v);
5488 if (SSA_VAR_P (fd->loop.n2)
5489 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5490 fold_convert (itype, fd->loops[i].n1),
5491 fold_convert (itype, fd->loops[i].n2)))
5492 == NULL_TREE || !integer_onep (t)))
5494 tree n1, n2;
5495 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5496 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5497 true, GSI_SAME_STMT);
5498 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5499 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5500 true, GSI_SAME_STMT);
5501 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5502 NULL_TREE, NULL_TREE);
5503 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5504 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5505 expand_omp_regimplify_p, NULL, NULL)
5506 || walk_tree (gimple_cond_rhs_ptr (stmt),
5507 expand_omp_regimplify_p, NULL, NULL))
5509 *gsi = gsi_for_stmt (stmt);
5510 gimple_regimplify_operands (stmt, gsi);
5512 e = split_block (entry_bb, stmt);
5513 if (zero_iter_bb == NULL)
5515 first_zero_iter = i;
5516 zero_iter_bb = create_empty_bb (entry_bb);
5517 if (current_loops)
5518 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5519 *gsi = gsi_after_labels (zero_iter_bb);
5520 stmt = gimple_build_assign (fd->loop.n2,
5521 build_zero_cst (type));
5522 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5523 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5524 entry_bb);
5526 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5527 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5528 e->flags = EDGE_TRUE_VALUE;
5529 e->probability = REG_BR_PROB_BASE - ne->probability;
5530 if (l2_dom_bb == NULL)
5531 l2_dom_bb = entry_bb;
5532 entry_bb = e->dest;
5533 *gsi = gsi_last_bb (entry_bb);
5536 if (POINTER_TYPE_P (itype))
5537 itype = signed_type_for (itype);
5538 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5539 ? -1 : 1));
5540 t = fold_build2 (PLUS_EXPR, itype,
5541 fold_convert (itype, fd->loops[i].step), t);
5542 t = fold_build2 (PLUS_EXPR, itype, t,
5543 fold_convert (itype, fd->loops[i].n2));
5544 t = fold_build2 (MINUS_EXPR, itype, t,
5545 fold_convert (itype, fd->loops[i].n1));
5546 /* ?? We could probably use CEIL_DIV_EXPR instead of
5547 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5548 generate the same code in the end because generically we
5549 don't know that the values involved must be negative for
5550 GT?? */
5551 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5552 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5553 fold_build1 (NEGATE_EXPR, itype, t),
5554 fold_build1 (NEGATE_EXPR, itype,
5555 fold_convert (itype,
5556 fd->loops[i].step)));
5557 else
5558 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5559 fold_convert (itype, fd->loops[i].step));
5560 t = fold_convert (type, t);
5561 if (TREE_CODE (t) == INTEGER_CST)
5562 counts[i] = t;
5563 else
5565 counts[i] = create_tmp_reg (type, ".count");
5566 expand_omp_build_assign (gsi, counts[i], t);
5568 if (SSA_VAR_P (fd->loop.n2))
5570 if (i == 0)
5571 t = counts[0];
5572 else
5573 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5574 expand_omp_build_assign (gsi, fd->loop.n2, t);
5580 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5581 T = V;
5582 V3 = N31 + (T % count3) * STEP3;
5583 T = T / count3;
5584 V2 = N21 + (T % count2) * STEP2;
5585 T = T / count2;
5586 V1 = N11 + T * STEP1;
5587 if this loop doesn't have an inner loop construct combined with it.
5588 If it does have an inner loop construct combined with it and the
5589 iteration count isn't known constant, store values from counts array
5590 into its _looptemp_ temporaries instead. */
5592 static void
5593 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5594 tree *counts, gimple inner_stmt, tree startvar)
5596 int i;
5597 if (gimple_omp_for_combined_p (fd->for_stmt))
5599 /* If fd->loop.n2 is constant, then no propagation of the counts
5600 is needed, they are constant. */
5601 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5602 return;
5604 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5605 ? gimple_omp_parallel_clauses (inner_stmt)
5606 : gimple_omp_for_clauses (inner_stmt);
5607 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5608 isn't supposed to be handled, as the inner loop doesn't
5609 use it. */
5610 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5611 gcc_assert (innerc);
5612 for (i = 0; i < fd->collapse; i++)
5614 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5615 OMP_CLAUSE__LOOPTEMP_);
5616 gcc_assert (innerc);
5617 if (i)
5619 tree tem = OMP_CLAUSE_DECL (innerc);
5620 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5621 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5622 false, GSI_CONTINUE_LINKING);
5623 gimple stmt = gimple_build_assign (tem, t);
5624 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5627 return;
5630 tree type = TREE_TYPE (fd->loop.v);
5631 tree tem = create_tmp_reg (type, ".tem");
5632 gimple stmt = gimple_build_assign (tem, startvar);
5633 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5635 for (i = fd->collapse - 1; i >= 0; i--)
5637 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5638 itype = vtype;
5639 if (POINTER_TYPE_P (vtype))
5640 itype = signed_type_for (vtype);
5641 if (i != 0)
5642 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5643 else
5644 t = tem;
5645 t = fold_convert (itype, t);
5646 t = fold_build2 (MULT_EXPR, itype, t,
5647 fold_convert (itype, fd->loops[i].step));
5648 if (POINTER_TYPE_P (vtype))
5649 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5650 else
5651 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5652 t = force_gimple_operand_gsi (gsi, t,
5653 DECL_P (fd->loops[i].v)
5654 && TREE_ADDRESSABLE (fd->loops[i].v),
5655 NULL_TREE, false,
5656 GSI_CONTINUE_LINKING);
5657 stmt = gimple_build_assign (fd->loops[i].v, t);
5658 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5659 if (i != 0)
5661 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5662 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5663 false, GSI_CONTINUE_LINKING);
5664 stmt = gimple_build_assign (tem, t);
5665 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5671 /* Helper function for expand_omp_for_*. Generate code like:
5672 L10:
5673 V3 += STEP3;
5674 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5675 L11:
5676 V3 = N31;
5677 V2 += STEP2;
5678 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5679 L12:
5680 V2 = N21;
5681 V1 += STEP1;
5682 goto BODY_BB; */
5684 static basic_block
5685 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5686 basic_block body_bb)
5688 basic_block last_bb, bb, collapse_bb = NULL;
5689 int i;
5690 gimple_stmt_iterator gsi;
5691 edge e;
5692 tree t;
5693 gimple stmt;
5695 last_bb = cont_bb;
5696 for (i = fd->collapse - 1; i >= 0; i--)
5698 tree vtype = TREE_TYPE (fd->loops[i].v);
5700 bb = create_empty_bb (last_bb);
5701 if (current_loops)
5702 add_bb_to_loop (bb, last_bb->loop_father);
5703 gsi = gsi_start_bb (bb);
5705 if (i < fd->collapse - 1)
5707 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5708 e->probability = REG_BR_PROB_BASE / 8;
5710 t = fd->loops[i + 1].n1;
5711 t = force_gimple_operand_gsi (&gsi, t,
5712 DECL_P (fd->loops[i + 1].v)
5713 && TREE_ADDRESSABLE (fd->loops[i
5714 + 1].v),
5715 NULL_TREE, false,
5716 GSI_CONTINUE_LINKING);
5717 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5718 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5720 else
5721 collapse_bb = bb;
5723 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5725 if (POINTER_TYPE_P (vtype))
5726 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5727 else
5728 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5729 t = force_gimple_operand_gsi (&gsi, t,
5730 DECL_P (fd->loops[i].v)
5731 && TREE_ADDRESSABLE (fd->loops[i].v),
5732 NULL_TREE, false, GSI_CONTINUE_LINKING);
5733 stmt = gimple_build_assign (fd->loops[i].v, t);
5734 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5736 if (i > 0)
5738 t = fd->loops[i].n2;
5739 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5740 false, GSI_CONTINUE_LINKING);
5741 tree v = fd->loops[i].v;
5742 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5743 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5744 false, GSI_CONTINUE_LINKING);
5745 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5746 stmt = gimple_build_cond_empty (t);
5747 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5748 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5749 e->probability = REG_BR_PROB_BASE * 7 / 8;
5751 else
5752 make_edge (bb, body_bb, EDGE_FALLTHRU);
5753 last_bb = bb;
5756 return collapse_bb;
5760 /* A subroutine of expand_omp_for. Generate code for a parallel
5761 loop with any schedule. Given parameters:
5763 for (V = N1; V cond N2; V += STEP) BODY;
5765 where COND is "<" or ">", we generate pseudocode
5767 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5768 if (more) goto L0; else goto L3;
5770 V = istart0;
5771 iend = iend0;
5773 BODY;
5774 V += STEP;
5775 if (V cond iend) goto L1; else goto L2;
5777 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5780 If this is a combined omp parallel loop, instead of the call to
5781 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5782 If this is gimple_omp_for_combined_p loop, then instead of assigning
5783 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5784 inner GIMPLE_OMP_FOR and V += STEP; and
5785 if (V cond iend) goto L1; else goto L2; are removed.
5787 For collapsed loops, given parameters:
5788 collapse(3)
5789 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5790 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5791 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5792 BODY;
5794 we generate pseudocode
5796 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5797 if (cond3 is <)
5798 adj = STEP3 - 1;
5799 else
5800 adj = STEP3 + 1;
5801 count3 = (adj + N32 - N31) / STEP3;
5802 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5803 if (cond2 is <)
5804 adj = STEP2 - 1;
5805 else
5806 adj = STEP2 + 1;
5807 count2 = (adj + N22 - N21) / STEP2;
5808 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5809 if (cond1 is <)
5810 adj = STEP1 - 1;
5811 else
5812 adj = STEP1 + 1;
5813 count1 = (adj + N12 - N11) / STEP1;
5814 count = count1 * count2 * count3;
5815 goto Z1;
5817 count = 0;
5819 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5820 if (more) goto L0; else goto L3;
5822 V = istart0;
5823 T = V;
5824 V3 = N31 + (T % count3) * STEP3;
5825 T = T / count3;
5826 V2 = N21 + (T % count2) * STEP2;
5827 T = T / count2;
5828 V1 = N11 + T * STEP1;
5829 iend = iend0;
5831 BODY;
5832 V += 1;
5833 if (V < iend) goto L10; else goto L2;
5834 L10:
5835 V3 += STEP3;
5836 if (V3 cond3 N32) goto L1; else goto L11;
5837 L11:
5838 V3 = N31;
5839 V2 += STEP2;
5840 if (V2 cond2 N22) goto L1; else goto L12;
5841 L12:
5842 V2 = N21;
5843 V1 += STEP1;
5844 goto L1;
5846 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5851 static void
5852 expand_omp_for_generic (struct omp_region *region,
5853 struct omp_for_data *fd,
5854 enum built_in_function start_fn,
5855 enum built_in_function next_fn,
5856 gimple inner_stmt)
5858 gcc_assert (gimple_omp_for_kind (fd->for_stmt) != GF_OMP_FOR_KIND_OACC_LOOP);
5860 tree type, istart0, iend0, iend;
5861 tree t, vmain, vback, bias = NULL_TREE;
5862 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5863 basic_block l2_bb = NULL, l3_bb = NULL;
5864 gimple_stmt_iterator gsi;
5865 gimple stmt;
5866 bool in_combined_parallel = is_combined_parallel (region);
5867 bool broken_loop = region->cont == NULL;
5868 edge e, ne;
5869 tree *counts = NULL;
5870 int i;
5872 gcc_assert (!broken_loop || !in_combined_parallel);
5873 gcc_assert (fd->iter_type == long_integer_type_node
5874 || !in_combined_parallel);
5876 type = TREE_TYPE (fd->loop.v);
5877 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5878 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5879 TREE_ADDRESSABLE (istart0) = 1;
5880 TREE_ADDRESSABLE (iend0) = 1;
5882 /* See if we need to bias by LLONG_MIN. */
5883 if (fd->iter_type == long_long_unsigned_type_node
5884 && TREE_CODE (type) == INTEGER_TYPE
5885 && !TYPE_UNSIGNED (type))
5887 tree n1, n2;
5889 if (fd->loop.cond_code == LT_EXPR)
5891 n1 = fd->loop.n1;
5892 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5894 else
5896 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5897 n2 = fd->loop.n1;
5899 if (TREE_CODE (n1) != INTEGER_CST
5900 || TREE_CODE (n2) != INTEGER_CST
5901 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5902 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5905 entry_bb = region->entry;
5906 cont_bb = region->cont;
5907 collapse_bb = NULL;
5908 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5909 gcc_assert (broken_loop
5910 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5911 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5912 l1_bb = single_succ (l0_bb);
5913 if (!broken_loop)
5915 l2_bb = create_empty_bb (cont_bb);
5916 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5917 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5919 else
5920 l2_bb = NULL;
5921 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5922 exit_bb = region->exit;
5924 gsi = gsi_last_bb (entry_bb);
5926 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5927 if (fd->collapse > 1)
5929 gcc_assert (gimple_omp_for_kind (gsi_stmt (gsi))
5930 != GF_OMP_FOR_KIND_OACC_LOOP);
5932 int first_zero_iter = -1;
5933 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5935 counts = XALLOCAVEC (tree, fd->collapse);
5936 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5937 zero_iter_bb, first_zero_iter,
5938 l2_dom_bb);
5940 if (zero_iter_bb)
5942 /* Some counts[i] vars might be uninitialized if
5943 some loop has zero iterations. But the body shouldn't
5944 be executed in that case, so just avoid uninit warnings. */
5945 for (i = first_zero_iter; i < fd->collapse; i++)
5946 if (SSA_VAR_P (counts[i]))
5947 TREE_NO_WARNING (counts[i]) = 1;
5948 gsi_prev (&gsi);
5949 e = split_block (entry_bb, gsi_stmt (gsi));
5950 entry_bb = e->dest;
5951 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5952 gsi = gsi_last_bb (entry_bb);
5953 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5954 get_immediate_dominator (CDI_DOMINATORS,
5955 zero_iter_bb));
5958 if (in_combined_parallel)
5960 gcc_assert (gimple_omp_for_kind (gsi_stmt (gsi))
5961 != GF_OMP_FOR_KIND_OACC_LOOP);
5963 /* In a combined parallel loop, emit a call to
5964 GOMP_loop_foo_next. */
5965 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5966 build_fold_addr_expr (istart0),
5967 build_fold_addr_expr (iend0));
5969 else
5971 tree t0, t1, t2, t3, t4;
5972 /* If this is not a combined parallel loop, emit a call to
5973 GOMP_loop_foo_start in ENTRY_BB. */
5974 t4 = build_fold_addr_expr (iend0);
5975 t3 = build_fold_addr_expr (istart0);
5976 t2 = fold_convert (fd->iter_type, fd->loop.step);
5977 t1 = fd->loop.n2;
5978 t0 = fd->loop.n1;
5979 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5981 gcc_assert (gimple_omp_for_kind (gsi_stmt (gsi))
5982 != GF_OMP_FOR_KIND_OACC_LOOP);
5984 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5985 OMP_CLAUSE__LOOPTEMP_);
5986 gcc_assert (innerc);
5987 t0 = OMP_CLAUSE_DECL (innerc);
5988 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5989 OMP_CLAUSE__LOOPTEMP_);
5990 gcc_assert (innerc);
5991 t1 = OMP_CLAUSE_DECL (innerc);
5993 if (POINTER_TYPE_P (TREE_TYPE (t0))
5994 && TYPE_PRECISION (TREE_TYPE (t0))
5995 != TYPE_PRECISION (fd->iter_type))
5997 /* Avoid casting pointers to integer of a different size. */
5998 tree itype = signed_type_for (type);
5999 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6000 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6002 else
6004 t1 = fold_convert (fd->iter_type, t1);
6005 t0 = fold_convert (fd->iter_type, t0);
6007 if (bias)
6009 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6010 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6012 if (fd->iter_type == long_integer_type_node)
6014 if (fd->chunk_size)
6016 t = fold_convert (fd->iter_type, fd->chunk_size);
6017 t = build_call_expr (builtin_decl_explicit (start_fn),
6018 6, t0, t1, t2, t, t3, t4);
6020 else
6021 t = build_call_expr (builtin_decl_explicit (start_fn),
6022 5, t0, t1, t2, t3, t4);
6024 else
6026 tree t5;
6027 tree c_bool_type;
6028 tree bfn_decl;
6030 /* The GOMP_loop_ull_*start functions have additional boolean
6031 argument, true for < loops and false for > loops.
6032 In Fortran, the C bool type can be different from
6033 boolean_type_node. */
6034 bfn_decl = builtin_decl_explicit (start_fn);
6035 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6036 t5 = build_int_cst (c_bool_type,
6037 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6038 if (fd->chunk_size)
6040 tree bfn_decl = builtin_decl_explicit (start_fn);
6041 t = fold_convert (fd->iter_type, fd->chunk_size);
6042 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6044 else
6045 t = build_call_expr (builtin_decl_explicit (start_fn),
6046 6, t5, t0, t1, t2, t3, t4);
6049 if (TREE_TYPE (t) != boolean_type_node)
6050 t = fold_build2 (NE_EXPR, boolean_type_node,
6051 t, build_int_cst (TREE_TYPE (t), 0));
6052 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6053 true, GSI_SAME_STMT);
6054 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6056 /* Remove the GIMPLE_OMP_FOR statement. */
6057 gsi_remove (&gsi, true);
6059 /* Iteration setup for sequential loop goes in L0_BB. */
6060 tree startvar = fd->loop.v;
6061 tree endvar = NULL_TREE;
6063 if (gimple_omp_for_combined_p (fd->for_stmt))
6065 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6066 && gimple_omp_for_kind (inner_stmt)
6067 == GF_OMP_FOR_KIND_SIMD);
6068 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6069 OMP_CLAUSE__LOOPTEMP_);
6070 gcc_assert (innerc);
6071 startvar = OMP_CLAUSE_DECL (innerc);
6072 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6073 OMP_CLAUSE__LOOPTEMP_);
6074 gcc_assert (innerc);
6075 endvar = OMP_CLAUSE_DECL (innerc);
6078 gsi = gsi_start_bb (l0_bb);
6079 t = istart0;
6080 if (bias)
6081 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6082 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6083 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6084 t = fold_convert (TREE_TYPE (startvar), t);
6085 t = force_gimple_operand_gsi (&gsi, t,
6086 DECL_P (startvar)
6087 && TREE_ADDRESSABLE (startvar),
6088 NULL_TREE, false, GSI_CONTINUE_LINKING);
6089 stmt = gimple_build_assign (startvar, t);
6090 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6092 t = iend0;
6093 if (bias)
6094 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6095 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6096 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6097 t = fold_convert (TREE_TYPE (startvar), t);
6098 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6099 false, GSI_CONTINUE_LINKING);
6100 if (endvar)
6102 stmt = gimple_build_assign (endvar, iend);
6103 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6105 if (fd->collapse > 1)
6106 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6108 if (!broken_loop)
6110 /* Code to control the increment and predicate for the sequential
6111 loop goes in the CONT_BB. */
6112 gsi = gsi_last_bb (cont_bb);
6113 stmt = gsi_stmt (gsi);
6114 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6115 vmain = gimple_omp_continue_control_use (stmt);
6116 vback = gimple_omp_continue_control_def (stmt);
6118 if (!gimple_omp_for_combined_p (fd->for_stmt))
6120 if (POINTER_TYPE_P (type))
6121 t = fold_build_pointer_plus (vmain, fd->loop.step);
6122 else
6123 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6124 t = force_gimple_operand_gsi (&gsi, t,
6125 DECL_P (vback)
6126 && TREE_ADDRESSABLE (vback),
6127 NULL_TREE, true, GSI_SAME_STMT);
6128 stmt = gimple_build_assign (vback, t);
6129 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6131 t = build2 (fd->loop.cond_code, boolean_type_node,
6132 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6133 iend);
6134 stmt = gimple_build_cond_empty (t);
6135 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6138 /* Remove GIMPLE_OMP_CONTINUE. */
6139 gsi_remove (&gsi, true);
6141 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6142 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6144 /* Emit code to get the next parallel iteration in L2_BB. */
6145 gsi = gsi_start_bb (l2_bb);
6147 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6148 build_fold_addr_expr (istart0),
6149 build_fold_addr_expr (iend0));
6150 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6151 false, GSI_CONTINUE_LINKING);
6152 if (TREE_TYPE (t) != boolean_type_node)
6153 t = fold_build2 (NE_EXPR, boolean_type_node,
6154 t, build_int_cst (TREE_TYPE (t), 0));
6155 stmt = gimple_build_cond_empty (t);
6156 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6159 /* Add the loop cleanup function. */
6160 gsi = gsi_last_bb (exit_bb);
6161 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6162 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6163 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6164 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6165 else
6166 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6167 stmt = gimple_build_call (t, 0);
6168 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6169 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6170 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
6171 gsi_remove (&gsi, true);
6173 /* Connect the new blocks. */
6174 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6175 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6177 if (!broken_loop)
6179 gimple_seq phis;
6181 e = find_edge (cont_bb, l3_bb);
6182 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6184 phis = phi_nodes (l3_bb);
6185 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6187 gimple phi = gsi_stmt (gsi);
6188 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6189 PHI_ARG_DEF_FROM_EDGE (phi, e));
6191 remove_edge (e);
6193 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6194 if (current_loops)
6195 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6196 e = find_edge (cont_bb, l1_bb);
6197 if (gimple_omp_for_combined_p (fd->for_stmt))
6199 remove_edge (e);
6200 e = NULL;
6202 else if (fd->collapse > 1)
6204 remove_edge (e);
6205 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6207 else
6208 e->flags = EDGE_TRUE_VALUE;
6209 if (e)
6211 e->probability = REG_BR_PROB_BASE * 7 / 8;
6212 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6214 else
6216 e = find_edge (cont_bb, l2_bb);
6217 e->flags = EDGE_FALLTHRU;
6219 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6221 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6222 recompute_dominator (CDI_DOMINATORS, l2_bb));
6223 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6224 recompute_dominator (CDI_DOMINATORS, l3_bb));
6225 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6226 recompute_dominator (CDI_DOMINATORS, l0_bb));
6227 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6228 recompute_dominator (CDI_DOMINATORS, l1_bb));
6230 struct loop *outer_loop = alloc_loop ();
6231 outer_loop->header = l0_bb;
6232 outer_loop->latch = l2_bb;
6233 add_loop (outer_loop, l0_bb->loop_father);
6235 if (!gimple_omp_for_combined_p (fd->for_stmt))
6237 struct loop *loop = alloc_loop ();
6238 loop->header = l1_bb;
6239 /* The loop may have multiple latches. */
6240 add_loop (loop, outer_loop);
6246 /* A subroutine of expand_omp_for. Generate code for a parallel
6247 loop with static schedule and no specified chunk size. Given
6248 parameters:
6250 for (V = N1; V cond N2; V += STEP) BODY;
6252 where COND is "<" or ">", we generate pseudocode
6254 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6255 if (cond is <)
6256 adj = STEP - 1;
6257 else
6258 adj = STEP + 1;
6259 if ((__typeof (V)) -1 > 0 && cond is >)
6260 n = -(adj + N2 - N1) / -STEP;
6261 else
6262 n = (adj + N2 - N1) / STEP;
6263 q = n / nthreads;
6264 tt = n % nthreads;
6265 if (threadid < tt) goto L3; else goto L4;
6267 tt = 0;
6268 q = q + 1;
6270 s0 = q * threadid + tt;
6271 e0 = s0 + q;
6272 V = s0 * STEP + N1;
6273 if (s0 >= e0) goto L2; else goto L0;
6275 e = e0 * STEP + N1;
6277 BODY;
6278 V += STEP;
6279 if (V cond e) goto L1;
6283 static void
6284 expand_omp_for_static_nochunk (struct omp_region *region,
6285 struct omp_for_data *fd,
6286 gimple inner_stmt)
6288 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6289 tree type, itype, vmain, vback;
6290 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6291 basic_block body_bb, cont_bb, collapse_bb = NULL;
6292 basic_block fin_bb;
6293 gimple_stmt_iterator gsi;
6294 gimple stmt;
6295 edge ep;
6296 bool broken_loop = region->cont == NULL;
6297 tree *counts = NULL;
6298 tree n1, n2, step;
6300 gcc_assert ((gimple_omp_for_kind (fd->for_stmt)
6301 != GF_OMP_FOR_KIND_OACC_LOOP)
6302 || !inner_stmt);
6304 itype = type = TREE_TYPE (fd->loop.v);
6305 if (POINTER_TYPE_P (type))
6306 itype = signed_type_for (type);
6308 entry_bb = region->entry;
6309 cont_bb = region->cont;
6310 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6311 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6312 gcc_assert (broken_loop
6313 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6314 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6315 body_bb = single_succ (seq_start_bb);
6316 if (!broken_loop)
6318 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6319 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6321 exit_bb = region->exit;
6323 /* Iteration space partitioning goes in ENTRY_BB. */
6324 gsi = gsi_last_bb (entry_bb);
6325 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6327 if (fd->collapse > 1)
6329 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
6330 != GF_OMP_FOR_KIND_OACC_LOOP);
6332 int first_zero_iter = -1;
6333 basic_block l2_dom_bb = NULL;
6335 counts = XALLOCAVEC (tree, fd->collapse);
6336 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6337 fin_bb, first_zero_iter,
6338 l2_dom_bb);
6339 t = NULL_TREE;
6341 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6343 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
6344 != GF_OMP_FOR_KIND_OACC_LOOP);
6346 t = integer_one_node;
6348 else
6349 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6350 fold_convert (type, fd->loop.n1),
6351 fold_convert (type, fd->loop.n2));
6352 if (fd->collapse == 1
6353 && TYPE_UNSIGNED (type)
6354 && (t == NULL_TREE || !integer_onep (t)))
6356 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6357 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6358 true, GSI_SAME_STMT);
6359 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6360 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6361 true, GSI_SAME_STMT);
6362 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6363 NULL_TREE, NULL_TREE);
6364 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6365 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6366 expand_omp_regimplify_p, NULL, NULL)
6367 || walk_tree (gimple_cond_rhs_ptr (stmt),
6368 expand_omp_regimplify_p, NULL, NULL))
6370 gsi = gsi_for_stmt (stmt);
6371 gimple_regimplify_operands (stmt, &gsi);
6373 ep = split_block (entry_bb, stmt);
6374 ep->flags = EDGE_TRUE_VALUE;
6375 entry_bb = ep->dest;
6376 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6377 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6378 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6379 if (gimple_in_ssa_p (cfun))
6381 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
6382 != GF_OMP_FOR_KIND_OACC_LOOP);
6384 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6385 for (gsi = gsi_start_phis (fin_bb);
6386 !gsi_end_p (gsi); gsi_next (&gsi))
6388 gimple phi = gsi_stmt (gsi);
6389 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6390 ep, UNKNOWN_LOCATION);
6393 gsi = gsi_last_bb (entry_bb);
6396 switch (gimple_omp_for_kind (fd->for_stmt))
6398 case GF_OMP_FOR_KIND_FOR:
6399 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6400 nthreads = build_call_expr (nthreads, 0);
6401 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6402 threadid = build_call_expr (threadid, 0);
6403 break;
6404 case GF_OMP_FOR_KIND_DISTRIBUTE:
6405 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6406 nthreads = build_call_expr (nthreads, 0);
6407 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6408 threadid = build_call_expr (threadid, 0);
6409 break;
6410 case GF_OMP_FOR_KIND_OACC_LOOP:
6411 nthreads = integer_one_node;
6412 threadid = integer_zero_node;
6413 break;
6414 default:
6415 gcc_unreachable ();
6417 nthreads = fold_convert (itype, nthreads);
6418 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6419 true, GSI_SAME_STMT);
6420 threadid = fold_convert (itype, threadid);
6421 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6422 true, GSI_SAME_STMT);
6424 n1 = fd->loop.n1;
6425 n2 = fd->loop.n2;
6426 step = fd->loop.step;
6427 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6429 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
6430 != GF_OMP_FOR_KIND_OACC_LOOP);
6432 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6433 OMP_CLAUSE__LOOPTEMP_);
6434 gcc_assert (innerc);
6435 n1 = OMP_CLAUSE_DECL (innerc);
6436 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6437 OMP_CLAUSE__LOOPTEMP_);
6438 gcc_assert (innerc);
6439 n2 = OMP_CLAUSE_DECL (innerc);
6441 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6442 true, NULL_TREE, true, GSI_SAME_STMT);
6443 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6444 true, NULL_TREE, true, GSI_SAME_STMT);
6445 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6446 true, NULL_TREE, true, GSI_SAME_STMT);
6448 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6449 t = fold_build2 (PLUS_EXPR, itype, step, t);
6450 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6451 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6452 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6453 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6454 fold_build1 (NEGATE_EXPR, itype, t),
6455 fold_build1 (NEGATE_EXPR, itype, step));
6456 else
6457 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6458 t = fold_convert (itype, t);
6459 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6461 q = create_tmp_reg (itype, "q");
6462 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6463 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6464 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6466 tt = create_tmp_reg (itype, "tt");
6467 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6468 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6469 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6471 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6472 stmt = gimple_build_cond_empty (t);
6473 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6475 second_bb = split_block (entry_bb, stmt)->dest;
6476 gsi = gsi_last_bb (second_bb);
6477 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6479 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6480 GSI_SAME_STMT);
6481 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
6482 build_int_cst (itype, 1));
6483 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6485 third_bb = split_block (second_bb, stmt)->dest;
6486 gsi = gsi_last_bb (third_bb);
6487 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6489 t = build2 (MULT_EXPR, itype, q, threadid);
6490 t = build2 (PLUS_EXPR, itype, t, tt);
6491 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6493 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6494 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6496 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6497 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6499 /* Remove the GIMPLE_OMP_FOR statement. */
6500 gsi_remove (&gsi, true);
6502 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6503 gsi = gsi_start_bb (seq_start_bb);
6505 tree startvar = fd->loop.v;
6506 tree endvar = NULL_TREE;
6508 if (gimple_omp_for_combined_p (fd->for_stmt))
6510 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
6511 != GF_OMP_FOR_KIND_OACC_LOOP);
6513 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6514 ? gimple_omp_parallel_clauses (inner_stmt)
6515 : gimple_omp_for_clauses (inner_stmt);
6516 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6517 gcc_assert (innerc);
6518 startvar = OMP_CLAUSE_DECL (innerc);
6519 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6520 OMP_CLAUSE__LOOPTEMP_);
6521 gcc_assert (innerc);
6522 endvar = OMP_CLAUSE_DECL (innerc);
6524 t = fold_convert (itype, s0);
6525 t = fold_build2 (MULT_EXPR, itype, t, step);
6526 if (POINTER_TYPE_P (type))
6527 t = fold_build_pointer_plus (n1, t);
6528 else
6529 t = fold_build2 (PLUS_EXPR, type, t, n1);
6530 t = fold_convert (TREE_TYPE (startvar), t);
6531 t = force_gimple_operand_gsi (&gsi, t,
6532 DECL_P (startvar)
6533 && TREE_ADDRESSABLE (startvar),
6534 NULL_TREE, false, GSI_CONTINUE_LINKING);
6535 stmt = gimple_build_assign (startvar, t);
6536 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6538 t = fold_convert (itype, e0);
6539 t = fold_build2 (MULT_EXPR, itype, t, step);
6540 if (POINTER_TYPE_P (type))
6541 t = fold_build_pointer_plus (n1, t);
6542 else
6543 t = fold_build2 (PLUS_EXPR, type, t, n1);
6544 t = fold_convert (TREE_TYPE (startvar), t);
6545 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6546 false, GSI_CONTINUE_LINKING);
6547 if (endvar)
6549 stmt = gimple_build_assign (endvar, e);
6550 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6552 if (fd->collapse > 1)
6554 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
6555 != GF_OMP_FOR_KIND_OACC_LOOP);
6557 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6560 if (!broken_loop)
6562 /* The code controlling the sequential loop replaces the
6563 GIMPLE_OMP_CONTINUE. */
6564 gsi = gsi_last_bb (cont_bb);
6565 stmt = gsi_stmt (gsi);
6566 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6567 vmain = gimple_omp_continue_control_use (stmt);
6568 vback = gimple_omp_continue_control_def (stmt);
6570 if (!gimple_omp_for_combined_p (fd->for_stmt))
6572 if (POINTER_TYPE_P (type))
6573 t = fold_build_pointer_plus (vmain, step);
6574 else
6575 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6576 t = force_gimple_operand_gsi (&gsi, t,
6577 DECL_P (vback)
6578 && TREE_ADDRESSABLE (vback),
6579 NULL_TREE, true, GSI_SAME_STMT);
6580 stmt = gimple_build_assign (vback, t);
6581 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6583 t = build2 (fd->loop.cond_code, boolean_type_node,
6584 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6585 ? t : vback, e);
6586 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6589 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6590 gsi_remove (&gsi, true);
6592 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6594 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
6595 != GF_OMP_FOR_KIND_OACC_LOOP);
6597 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6601 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6602 gsi = gsi_last_bb (exit_bb);
6603 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6605 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
6606 != GF_OMP_FOR_KIND_OACC_LOOP);
6608 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6609 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6611 gsi_remove (&gsi, true);
6613 /* Connect all the blocks. */
6614 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6615 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6616 ep = find_edge (entry_bb, second_bb);
6617 ep->flags = EDGE_TRUE_VALUE;
6618 ep->probability = REG_BR_PROB_BASE / 4;
6619 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6620 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6622 if (!broken_loop)
6624 ep = find_edge (cont_bb, body_bb);
6625 if (gimple_omp_for_combined_p (fd->for_stmt))
6627 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
6628 != GF_OMP_FOR_KIND_OACC_LOOP);
6630 remove_edge (ep);
6631 ep = NULL;
6633 else if (fd->collapse > 1)
6635 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
6636 != GF_OMP_FOR_KIND_OACC_LOOP);
6638 remove_edge (ep);
6639 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6641 else
6642 ep->flags = EDGE_TRUE_VALUE;
6643 find_edge (cont_bb, fin_bb)->flags
6644 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6647 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6648 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6649 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6651 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6652 recompute_dominator (CDI_DOMINATORS, body_bb));
6653 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6654 recompute_dominator (CDI_DOMINATORS, fin_bb));
6656 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6658 struct loop *loop = alloc_loop ();
6659 loop->header = body_bb;
6660 if (collapse_bb == NULL)
6661 loop->latch = cont_bb;
6662 add_loop (loop, body_bb->loop_father);
6667 /* A subroutine of expand_omp_for. Generate code for a parallel
6668 loop with static schedule and a specified chunk size. Given
6669 parameters:
6671 for (V = N1; V cond N2; V += STEP) BODY;
6673 where COND is "<" or ">", we generate pseudocode
6675 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6676 if (cond is <)
6677 adj = STEP - 1;
6678 else
6679 adj = STEP + 1;
6680 if ((__typeof (V)) -1 > 0 && cond is >)
6681 n = -(adj + N2 - N1) / -STEP;
6682 else
6683 n = (adj + N2 - N1) / STEP;
6684 trip = 0;
6685 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6686 here so that V is defined
6687 if the loop is not entered
6689 s0 = (trip * nthreads + threadid) * CHUNK;
6690 e0 = min(s0 + CHUNK, n);
6691 if (s0 < n) goto L1; else goto L4;
6693 V = s0 * STEP + N1;
6694 e = e0 * STEP + N1;
6696 BODY;
6697 V += STEP;
6698 if (V cond e) goto L2; else goto L3;
6700 trip += 1;
6701 goto L0;
6705 static void
6706 expand_omp_for_static_chunk (struct omp_region *region,
6707 struct omp_for_data *fd, gimple inner_stmt)
6709 gcc_assert (gimple_omp_for_kind (fd->for_stmt) != GF_OMP_FOR_KIND_OACC_LOOP);
6711 tree n, s0, e0, e, t;
6712 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6713 tree type, itype, v_main, v_back, v_extra;
6714 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6715 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6716 gimple_stmt_iterator si;
6717 gimple stmt;
6718 edge se;
6719 bool broken_loop = region->cont == NULL;
6720 tree *counts = NULL;
6721 tree n1, n2, step;
6723 itype = type = TREE_TYPE (fd->loop.v);
6724 if (POINTER_TYPE_P (type))
6725 itype = signed_type_for (type);
6727 entry_bb = region->entry;
6728 se = split_block (entry_bb, last_stmt (entry_bb));
6729 entry_bb = se->src;
6730 iter_part_bb = se->dest;
6731 cont_bb = region->cont;
6732 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6733 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6734 gcc_assert (broken_loop
6735 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6736 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6737 body_bb = single_succ (seq_start_bb);
6738 if (!broken_loop)
6740 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6741 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6742 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6744 exit_bb = region->exit;
6746 /* Trip and adjustment setup goes in ENTRY_BB. */
6747 si = gsi_last_bb (entry_bb);
6748 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
6750 if (fd->collapse > 1)
6752 int first_zero_iter = -1;
6753 basic_block l2_dom_bb = NULL;
6755 counts = XALLOCAVEC (tree, fd->collapse);
6756 expand_omp_for_init_counts (fd, &si, entry_bb, counts,
6757 fin_bb, first_zero_iter,
6758 l2_dom_bb);
6759 t = NULL_TREE;
6761 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6762 t = integer_one_node;
6763 else
6764 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6765 fold_convert (type, fd->loop.n1),
6766 fold_convert (type, fd->loop.n2));
6767 if (fd->collapse == 1
6768 && TYPE_UNSIGNED (type)
6769 && (t == NULL_TREE || !integer_onep (t)))
6771 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6772 n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
6773 true, GSI_SAME_STMT);
6774 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6775 n2 = force_gimple_operand_gsi (&si, n2, true, NULL_TREE,
6776 true, GSI_SAME_STMT);
6777 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6778 NULL_TREE, NULL_TREE);
6779 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6780 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6781 expand_omp_regimplify_p, NULL, NULL)
6782 || walk_tree (gimple_cond_rhs_ptr (stmt),
6783 expand_omp_regimplify_p, NULL, NULL))
6785 si = gsi_for_stmt (stmt);
6786 gimple_regimplify_operands (stmt, &si);
6788 se = split_block (entry_bb, stmt);
6789 se->flags = EDGE_TRUE_VALUE;
6790 entry_bb = se->dest;
6791 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6792 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6793 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6794 if (gimple_in_ssa_p (cfun))
6796 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6797 for (si = gsi_start_phis (fin_bb);
6798 !gsi_end_p (si); gsi_next (&si))
6800 gimple phi = gsi_stmt (si);
6801 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6802 se, UNKNOWN_LOCATION);
6805 si = gsi_last_bb (entry_bb);
6808 switch (gimple_omp_for_kind (fd->for_stmt))
6810 case GF_OMP_FOR_KIND_FOR:
6811 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6812 nthreads = build_call_expr (nthreads, 0);
6813 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6814 threadid = build_call_expr (threadid, 0);
6815 break;
6816 case GF_OMP_FOR_KIND_DISTRIBUTE:
6817 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6818 nthreads = build_call_expr (nthreads, 0);
6819 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6820 threadid = build_call_expr (threadid, 0);
6821 break;
6822 default:
6823 gcc_unreachable ();
6825 nthreads = fold_convert (itype, nthreads);
6826 nthreads = force_gimple_operand_gsi (&si, nthreads, true, NULL_TREE,
6827 true, GSI_SAME_STMT);
6828 threadid = fold_convert (itype, threadid);
6829 threadid = force_gimple_operand_gsi (&si, threadid, true, NULL_TREE,
6830 true, GSI_SAME_STMT);
6832 n1 = fd->loop.n1;
6833 n2 = fd->loop.n2;
6834 step = fd->loop.step;
6835 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6837 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6838 OMP_CLAUSE__LOOPTEMP_);
6839 gcc_assert (innerc);
6840 n1 = OMP_CLAUSE_DECL (innerc);
6841 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6842 OMP_CLAUSE__LOOPTEMP_);
6843 gcc_assert (innerc);
6844 n2 = OMP_CLAUSE_DECL (innerc);
6846 n1 = force_gimple_operand_gsi (&si, fold_convert (type, n1),
6847 true, NULL_TREE, true, GSI_SAME_STMT);
6848 n2 = force_gimple_operand_gsi (&si, fold_convert (itype, n2),
6849 true, NULL_TREE, true, GSI_SAME_STMT);
6850 step = force_gimple_operand_gsi (&si, fold_convert (itype, step),
6851 true, NULL_TREE, true, GSI_SAME_STMT);
6852 fd->chunk_size
6853 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
6854 true, NULL_TREE, true, GSI_SAME_STMT);
6856 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6857 t = fold_build2 (PLUS_EXPR, itype, step, t);
6858 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6859 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6860 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6861 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6862 fold_build1 (NEGATE_EXPR, itype, t),
6863 fold_build1 (NEGATE_EXPR, itype, step));
6864 else
6865 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6866 t = fold_convert (itype, t);
6867 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6868 true, GSI_SAME_STMT);
6870 trip_var = create_tmp_reg (itype, ".trip");
6871 if (gimple_in_ssa_p (cfun))
6873 trip_init = make_ssa_name (trip_var, NULL);
6874 trip_main = make_ssa_name (trip_var, NULL);
6875 trip_back = make_ssa_name (trip_var, NULL);
6877 else
6879 trip_init = trip_var;
6880 trip_main = trip_var;
6881 trip_back = trip_var;
6884 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6885 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6887 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6888 t = fold_build2 (MULT_EXPR, itype, t, step);
6889 if (POINTER_TYPE_P (type))
6890 t = fold_build_pointer_plus (n1, t);
6891 else
6892 t = fold_build2 (PLUS_EXPR, type, t, n1);
6893 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6894 true, GSI_SAME_STMT);
6896 /* Remove the GIMPLE_OMP_FOR. */
6897 gsi_remove (&si, true);
6899 /* Iteration space partitioning goes in ITER_PART_BB. */
6900 si = gsi_last_bb (iter_part_bb);
6902 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6903 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6904 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6905 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6906 false, GSI_CONTINUE_LINKING);
6908 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6909 t = fold_build2 (MIN_EXPR, itype, t, n);
6910 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6911 false, GSI_CONTINUE_LINKING);
6913 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6914 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6916 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6917 si = gsi_start_bb (seq_start_bb);
6919 tree startvar = fd->loop.v;
6920 tree endvar = NULL_TREE;
6922 if (gimple_omp_for_combined_p (fd->for_stmt))
6924 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6925 ? gimple_omp_parallel_clauses (inner_stmt)
6926 : gimple_omp_for_clauses (inner_stmt);
6927 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6928 gcc_assert (innerc);
6929 startvar = OMP_CLAUSE_DECL (innerc);
6930 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6931 OMP_CLAUSE__LOOPTEMP_);
6932 gcc_assert (innerc);
6933 endvar = OMP_CLAUSE_DECL (innerc);
6936 t = fold_convert (itype, s0);
6937 t = fold_build2 (MULT_EXPR, itype, t, step);
6938 if (POINTER_TYPE_P (type))
6939 t = fold_build_pointer_plus (n1, t);
6940 else
6941 t = fold_build2 (PLUS_EXPR, type, t, n1);
6942 t = fold_convert (TREE_TYPE (startvar), t);
6943 t = force_gimple_operand_gsi (&si, t,
6944 DECL_P (startvar)
6945 && TREE_ADDRESSABLE (startvar),
6946 NULL_TREE, false, GSI_CONTINUE_LINKING);
6947 stmt = gimple_build_assign (startvar, t);
6948 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6950 t = fold_convert (itype, e0);
6951 t = fold_build2 (MULT_EXPR, itype, t, step);
6952 if (POINTER_TYPE_P (type))
6953 t = fold_build_pointer_plus (n1, t);
6954 else
6955 t = fold_build2 (PLUS_EXPR, type, t, n1);
6956 t = fold_convert (TREE_TYPE (startvar), t);
6957 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6958 false, GSI_CONTINUE_LINKING);
6959 if (endvar)
6961 stmt = gimple_build_assign (endvar, e);
6962 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6964 if (fd->collapse > 1)
6965 expand_omp_for_init_vars (fd, &si, counts, inner_stmt, startvar);
6967 if (!broken_loop)
6969 /* The code controlling the sequential loop goes in CONT_BB,
6970 replacing the GIMPLE_OMP_CONTINUE. */
6971 si = gsi_last_bb (cont_bb);
6972 stmt = gsi_stmt (si);
6973 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6974 v_main = gimple_omp_continue_control_use (stmt);
6975 v_back = gimple_omp_continue_control_def (stmt);
6977 if (!gimple_omp_for_combined_p (fd->for_stmt))
6979 if (POINTER_TYPE_P (type))
6980 t = fold_build_pointer_plus (v_main, step);
6981 else
6982 t = fold_build2 (PLUS_EXPR, type, v_main, step);
6983 if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
6984 t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6985 true, GSI_SAME_STMT);
6986 stmt = gimple_build_assign (v_back, t);
6987 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6989 t = build2 (fd->loop.cond_code, boolean_type_node,
6990 DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
6991 ? t : v_back, e);
6992 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
6995 /* Remove GIMPLE_OMP_CONTINUE. */
6996 gsi_remove (&si, true);
6998 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6999 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7001 /* Trip update code goes into TRIP_UPDATE_BB. */
7002 si = gsi_start_bb (trip_update_bb);
7004 t = build_int_cst (itype, 1);
7005 t = build2 (PLUS_EXPR, itype, trip_main, t);
7006 stmt = gimple_build_assign (trip_back, t);
7007 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7010 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7011 si = gsi_last_bb (exit_bb);
7012 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7014 t = gimple_omp_return_lhs (gsi_stmt (si));
7015 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7017 gsi_remove (&si, true);
7019 /* Connect the new blocks. */
7020 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7021 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7023 if (!broken_loop)
7025 se = find_edge (cont_bb, body_bb);
7026 if (gimple_omp_for_combined_p (fd->for_stmt))
7028 remove_edge (se);
7029 se = NULL;
7031 else if (fd->collapse > 1)
7033 remove_edge (se);
7034 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7036 else
7037 se->flags = EDGE_TRUE_VALUE;
7038 find_edge (cont_bb, trip_update_bb)->flags
7039 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7041 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7044 if (gimple_in_ssa_p (cfun))
7046 gimple_stmt_iterator psi;
7047 gimple phi;
7048 edge re, ene;
7049 edge_var_map_vector *head;
7050 edge_var_map *vm;
7051 size_t i;
7053 gcc_assert (fd->collapse == 1 && !broken_loop);
7055 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7056 remove arguments of the phi nodes in fin_bb. We need to create
7057 appropriate phi nodes in iter_part_bb instead. */
7058 se = single_pred_edge (fin_bb);
7059 re = single_succ_edge (trip_update_bb);
7060 head = redirect_edge_var_map_vector (re);
7061 ene = single_succ_edge (entry_bb);
7063 psi = gsi_start_phis (fin_bb);
7064 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7065 gsi_next (&psi), ++i)
7067 gimple nphi;
7068 source_location locus;
7070 phi = gsi_stmt (psi);
7071 t = gimple_phi_result (phi);
7072 gcc_assert (t == redirect_edge_var_map_result (vm));
7073 nphi = create_phi_node (t, iter_part_bb);
7075 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7076 locus = gimple_phi_arg_location_from_edge (phi, se);
7078 /* A special case -- fd->loop.v is not yet computed in
7079 iter_part_bb, we need to use v_extra instead. */
7080 if (t == fd->loop.v)
7081 t = v_extra;
7082 add_phi_arg (nphi, t, ene, locus);
7083 locus = redirect_edge_var_map_location (vm);
7084 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7086 gcc_assert (!gsi_end_p (psi) && i == head->length ());
7087 redirect_edge_var_map_clear (re);
7088 while (1)
7090 psi = gsi_start_phis (fin_bb);
7091 if (gsi_end_p (psi))
7092 break;
7093 remove_phi_node (&psi, false);
7096 /* Make phi node for trip. */
7097 phi = create_phi_node (trip_main, iter_part_bb);
7098 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7099 UNKNOWN_LOCATION);
7100 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7101 UNKNOWN_LOCATION);
7104 if (!broken_loop)
7105 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7106 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7107 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7108 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7109 recompute_dominator (CDI_DOMINATORS, fin_bb));
7110 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7111 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7112 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7113 recompute_dominator (CDI_DOMINATORS, body_bb));
7115 if (!broken_loop)
7117 struct loop *trip_loop = alloc_loop ();
7118 trip_loop->header = iter_part_bb;
7119 trip_loop->latch = trip_update_bb;
7120 add_loop (trip_loop, iter_part_bb->loop_father);
7122 if (!gimple_omp_for_combined_p (fd->for_stmt))
7124 struct loop *loop = alloc_loop ();
7125 loop->header = body_bb;
7126 if (collapse_bb == NULL)
7127 loop->latch = cont_bb;
7128 add_loop (loop, trip_loop);
7134 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7135 loop. Given parameters:
7137 for (V = N1; V cond N2; V += STEP) BODY;
7139 where COND is "<" or ">", we generate pseudocode
7141 V = N1;
7142 goto L1;
7144 BODY;
7145 V += STEP;
7147 if (V cond N2) goto L0; else goto L2;
7150 For collapsed loops, given parameters:
7151 collapse(3)
7152 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7153 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7154 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7155 BODY;
7157 we generate pseudocode
7159 if (cond3 is <)
7160 adj = STEP3 - 1;
7161 else
7162 adj = STEP3 + 1;
7163 count3 = (adj + N32 - N31) / STEP3;
7164 if (cond2 is <)
7165 adj = STEP2 - 1;
7166 else
7167 adj = STEP2 + 1;
7168 count2 = (adj + N22 - N21) / STEP2;
7169 if (cond1 is <)
7170 adj = STEP1 - 1;
7171 else
7172 adj = STEP1 + 1;
7173 count1 = (adj + N12 - N11) / STEP1;
7174 count = count1 * count2 * count3;
7175 V = 0;
7176 V1 = N11;
7177 V2 = N21;
7178 V3 = N31;
7179 goto L1;
7181 BODY;
7182 V += 1;
7183 V3 += STEP3;
7184 V2 += (V3 cond3 N32) ? 0 : STEP2;
7185 V3 = (V3 cond3 N32) ? V3 : N31;
7186 V1 += (V2 cond2 N22) ? 0 : STEP1;
7187 V2 = (V2 cond2 N22) ? V2 : N21;
7189 if (V < count) goto L0; else goto L2;
7194 static void
7195 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7197 tree type, t;
7198 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7199 gimple_stmt_iterator gsi;
7200 gimple stmt;
7201 bool broken_loop = region->cont == NULL;
7202 edge e, ne;
7203 tree *counts = NULL;
7204 int i;
7205 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7206 OMP_CLAUSE_SAFELEN);
7207 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7208 OMP_CLAUSE__SIMDUID_);
7209 tree n1, n2;
7211 type = TREE_TYPE (fd->loop.v);
7212 entry_bb = region->entry;
7213 cont_bb = region->cont;
7214 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7215 gcc_assert (broken_loop
7216 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7217 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7218 if (!broken_loop)
7220 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7221 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7222 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7223 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7225 else
7227 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7228 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7229 l2_bb = single_succ (l1_bb);
7231 exit_bb = region->exit;
7232 l2_dom_bb = NULL;
7234 gsi = gsi_last_bb (entry_bb);
7236 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7237 /* Not needed in SSA form right now. */
7238 gcc_assert (!gimple_in_ssa_p (cfun));
7239 if (fd->collapse > 1)
7241 int first_zero_iter = -1;
7242 basic_block zero_iter_bb = l2_bb;
7244 counts = XALLOCAVEC (tree, fd->collapse);
7245 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7246 zero_iter_bb, first_zero_iter,
7247 l2_dom_bb);
7249 if (l2_dom_bb == NULL)
7250 l2_dom_bb = l1_bb;
7252 n1 = fd->loop.n1;
7253 n2 = fd->loop.n2;
7254 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7256 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7257 OMP_CLAUSE__LOOPTEMP_);
7258 gcc_assert (innerc);
7259 n1 = OMP_CLAUSE_DECL (innerc);
7260 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7261 OMP_CLAUSE__LOOPTEMP_);
7262 gcc_assert (innerc);
7263 n2 = OMP_CLAUSE_DECL (innerc);
7264 expand_omp_build_assign (&gsi, fd->loop.v,
7265 fold_convert (type, n1));
7266 if (fd->collapse > 1)
7268 gsi_prev (&gsi);
7269 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7270 gsi_next (&gsi);
7273 else
7275 expand_omp_build_assign (&gsi, fd->loop.v,
7276 fold_convert (type, fd->loop.n1));
7277 if (fd->collapse > 1)
7278 for (i = 0; i < fd->collapse; i++)
7280 tree itype = TREE_TYPE (fd->loops[i].v);
7281 if (POINTER_TYPE_P (itype))
7282 itype = signed_type_for (itype);
7283 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7284 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7288 /* Remove the GIMPLE_OMP_FOR statement. */
7289 gsi_remove (&gsi, true);
7291 if (!broken_loop)
7293 /* Code to control the increment goes in the CONT_BB. */
7294 gsi = gsi_last_bb (cont_bb);
7295 stmt = gsi_stmt (gsi);
7296 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7298 if (POINTER_TYPE_P (type))
7299 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7300 else
7301 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7302 expand_omp_build_assign (&gsi, fd->loop.v, t);
7304 if (fd->collapse > 1)
7306 i = fd->collapse - 1;
7307 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7309 t = fold_convert (sizetype, fd->loops[i].step);
7310 t = fold_build_pointer_plus (fd->loops[i].v, t);
7312 else
7314 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7315 fd->loops[i].step);
7316 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7317 fd->loops[i].v, t);
7319 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7321 for (i = fd->collapse - 1; i > 0; i--)
7323 tree itype = TREE_TYPE (fd->loops[i].v);
7324 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7325 if (POINTER_TYPE_P (itype2))
7326 itype2 = signed_type_for (itype2);
7327 t = build3 (COND_EXPR, itype2,
7328 build2 (fd->loops[i].cond_code, boolean_type_node,
7329 fd->loops[i].v,
7330 fold_convert (itype, fd->loops[i].n2)),
7331 build_int_cst (itype2, 0),
7332 fold_convert (itype2, fd->loops[i - 1].step));
7333 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7334 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7335 else
7336 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7337 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7339 t = build3 (COND_EXPR, itype,
7340 build2 (fd->loops[i].cond_code, boolean_type_node,
7341 fd->loops[i].v,
7342 fold_convert (itype, fd->loops[i].n2)),
7343 fd->loops[i].v,
7344 fold_convert (itype, fd->loops[i].n1));
7345 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7349 /* Remove GIMPLE_OMP_CONTINUE. */
7350 gsi_remove (&gsi, true);
7353 /* Emit the condition in L1_BB. */
7354 gsi = gsi_start_bb (l1_bb);
7356 t = fold_convert (type, n2);
7357 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7358 false, GSI_CONTINUE_LINKING);
7359 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7360 stmt = gimple_build_cond_empty (t);
7361 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7362 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
7363 NULL, NULL)
7364 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
7365 NULL, NULL))
7367 gsi = gsi_for_stmt (stmt);
7368 gimple_regimplify_operands (stmt, &gsi);
7371 /* Remove GIMPLE_OMP_RETURN. */
7372 gsi = gsi_last_bb (exit_bb);
7373 gsi_remove (&gsi, true);
7375 /* Connect the new blocks. */
7376 remove_edge (FALLTHRU_EDGE (entry_bb));
7378 if (!broken_loop)
7380 remove_edge (BRANCH_EDGE (entry_bb));
7381 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7383 e = BRANCH_EDGE (l1_bb);
7384 ne = FALLTHRU_EDGE (l1_bb);
7385 e->flags = EDGE_TRUE_VALUE;
7387 else
7389 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7391 ne = single_succ_edge (l1_bb);
7392 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7395 ne->flags = EDGE_FALSE_VALUE;
7396 e->probability = REG_BR_PROB_BASE * 7 / 8;
7397 ne->probability = REG_BR_PROB_BASE / 8;
7399 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7400 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7401 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7403 if (!broken_loop)
7405 struct loop *loop = alloc_loop ();
7406 loop->header = l1_bb;
7407 loop->latch = cont_bb;
7408 add_loop (loop, l1_bb->loop_father);
7409 if (safelen == NULL_TREE)
7410 loop->safelen = INT_MAX;
7411 else
7413 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7414 if (!tree_fits_uhwi_p (safelen)
7415 || tree_to_uhwi (safelen) > INT_MAX)
7416 loop->safelen = INT_MAX;
7417 else
7418 loop->safelen = tree_to_uhwi (safelen);
7419 if (loop->safelen == 1)
7420 loop->safelen = 0;
7422 if (simduid)
7424 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7425 cfun->has_simduid_loops = true;
7427 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7428 the loop. */
7429 if ((flag_tree_loop_vectorize
7430 || (!global_options_set.x_flag_tree_loop_vectorize
7431 && !global_options_set.x_flag_tree_vectorize))
7432 && loop->safelen > 1)
7434 loop->force_vect = true;
7435 cfun->has_force_vect_loops = true;
7441 /* Expand the OpenMP loop defined by REGION. */
7443 static void
7444 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7446 struct omp_for_data fd;
7447 struct omp_for_data_loop *loops;
7449 loops
7450 = (struct omp_for_data_loop *)
7451 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7452 * sizeof (struct omp_for_data_loop));
7453 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
7454 region->sched_kind = fd.sched_kind;
7456 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7457 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7458 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7459 if (region->cont)
7461 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7462 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7463 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7465 else
7466 /* If there isn't a continue then this is a degerate case where
7467 the introduction of abnormal edges during lowering will prevent
7468 original loops from being detected. Fix that up. */
7469 loops_state_set (LOOPS_NEED_FIXUP);
7471 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7472 expand_omp_simd (region, &fd);
7473 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7474 && !fd.have_ordered)
7476 if (fd.chunk_size == NULL)
7477 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7478 else
7479 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7481 else
7483 int fn_index, start_ix, next_ix;
7485 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7486 == GF_OMP_FOR_KIND_FOR);
7487 if (fd.chunk_size == NULL
7488 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7489 fd.chunk_size = integer_zero_node;
7490 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7491 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7492 ? 3 : fd.sched_kind;
7493 fn_index += fd.have_ordered * 4;
7494 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7495 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7496 if (fd.iter_type == long_long_unsigned_type_node)
7498 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7499 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7500 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7501 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7503 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7504 (enum built_in_function) next_ix, inner_stmt);
7507 if (gimple_in_ssa_p (cfun))
7508 update_ssa (TODO_update_ssa_only_virtuals);
7512 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7514 v = GOMP_sections_start (n);
7516 switch (v)
7518 case 0:
7519 goto L2;
7520 case 1:
7521 section 1;
7522 goto L1;
7523 case 2:
7525 case n:
7527 default:
7528 abort ();
7531 v = GOMP_sections_next ();
7532 goto L0;
7534 reduction;
7536 If this is a combined parallel sections, replace the call to
7537 GOMP_sections_start with call to GOMP_sections_next. */
7539 static void
7540 expand_omp_sections (struct omp_region *region)
7542 tree t, u, vin = NULL, vmain, vnext, l2;
7543 unsigned len;
7544 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7545 gimple_stmt_iterator si, switch_si;
7546 gimple sections_stmt, stmt, cont;
7547 edge_iterator ei;
7548 edge e;
7549 struct omp_region *inner;
7550 unsigned i, casei;
7551 bool exit_reachable = region->cont != NULL;
7553 gcc_assert (region->exit != NULL);
7554 entry_bb = region->entry;
7555 l0_bb = single_succ (entry_bb);
7556 l1_bb = region->cont;
7557 l2_bb = region->exit;
7558 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7559 l2 = gimple_block_label (l2_bb);
7560 else
7562 /* This can happen if there are reductions. */
7563 len = EDGE_COUNT (l0_bb->succs);
7564 gcc_assert (len > 0);
7565 e = EDGE_SUCC (l0_bb, len - 1);
7566 si = gsi_last_bb (e->dest);
7567 l2 = NULL_TREE;
7568 if (gsi_end_p (si)
7569 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7570 l2 = gimple_block_label (e->dest);
7571 else
7572 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7574 si = gsi_last_bb (e->dest);
7575 if (gsi_end_p (si)
7576 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7578 l2 = gimple_block_label (e->dest);
7579 break;
7583 if (exit_reachable)
7584 default_bb = create_empty_bb (l1_bb->prev_bb);
7585 else
7586 default_bb = create_empty_bb (l0_bb);
7588 /* We will build a switch() with enough cases for all the
7589 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7590 and a default case to abort if something goes wrong. */
7591 len = EDGE_COUNT (l0_bb->succs);
7593 /* Use vec::quick_push on label_vec throughout, since we know the size
7594 in advance. */
7595 auto_vec<tree> label_vec (len);
7597 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7598 GIMPLE_OMP_SECTIONS statement. */
7599 si = gsi_last_bb (entry_bb);
7600 sections_stmt = gsi_stmt (si);
7601 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7602 vin = gimple_omp_sections_control (sections_stmt);
7603 if (!is_combined_parallel (region))
7605 /* If we are not inside a combined parallel+sections region,
7606 call GOMP_sections_start. */
7607 t = build_int_cst (unsigned_type_node, len - 1);
7608 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7609 stmt = gimple_build_call (u, 1, t);
7611 else
7613 /* Otherwise, call GOMP_sections_next. */
7614 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7615 stmt = gimple_build_call (u, 0);
7617 gimple_call_set_lhs (stmt, vin);
7618 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7619 gsi_remove (&si, true);
7621 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7622 L0_BB. */
7623 switch_si = gsi_last_bb (l0_bb);
7624 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7625 if (exit_reachable)
7627 cont = last_stmt (l1_bb);
7628 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7629 vmain = gimple_omp_continue_control_use (cont);
7630 vnext = gimple_omp_continue_control_def (cont);
7632 else
7634 vmain = vin;
7635 vnext = NULL_TREE;
7638 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7639 label_vec.quick_push (t);
7640 i = 1;
7642 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7643 for (inner = region->inner, casei = 1;
7644 inner;
7645 inner = inner->next, i++, casei++)
7647 basic_block s_entry_bb, s_exit_bb;
7649 /* Skip optional reduction region. */
7650 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7652 --i;
7653 --casei;
7654 continue;
7657 s_entry_bb = inner->entry;
7658 s_exit_bb = inner->exit;
7660 t = gimple_block_label (s_entry_bb);
7661 u = build_int_cst (unsigned_type_node, casei);
7662 u = build_case_label (u, NULL, t);
7663 label_vec.quick_push (u);
7665 si = gsi_last_bb (s_entry_bb);
7666 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7667 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7668 gsi_remove (&si, true);
7669 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7671 if (s_exit_bb == NULL)
7672 continue;
7674 si = gsi_last_bb (s_exit_bb);
7675 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7676 gsi_remove (&si, true);
7678 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7681 /* Error handling code goes in DEFAULT_BB. */
7682 t = gimple_block_label (default_bb);
7683 u = build_case_label (NULL, NULL, t);
7684 make_edge (l0_bb, default_bb, 0);
7685 if (current_loops)
7686 add_bb_to_loop (default_bb, current_loops->tree_root);
7688 stmt = gimple_build_switch (vmain, u, label_vec);
7689 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7690 gsi_remove (&switch_si, true);
7692 si = gsi_start_bb (default_bb);
7693 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7694 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7696 if (exit_reachable)
7698 tree bfn_decl;
7700 /* Code to get the next section goes in L1_BB. */
7701 si = gsi_last_bb (l1_bb);
7702 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7704 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7705 stmt = gimple_build_call (bfn_decl, 0);
7706 gimple_call_set_lhs (stmt, vnext);
7707 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7708 gsi_remove (&si, true);
7710 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7713 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7714 si = gsi_last_bb (l2_bb);
7715 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7716 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7717 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7718 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7719 else
7720 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7721 stmt = gimple_build_call (t, 0);
7722 if (gimple_omp_return_lhs (gsi_stmt (si)))
7723 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7724 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7725 gsi_remove (&si, true);
7727 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7731 /* Expand code for an OpenMP single directive. We've already expanded
7732 much of the code, here we simply place the GOMP_barrier call. */
7734 static void
7735 expand_omp_single (struct omp_region *region)
7737 basic_block entry_bb, exit_bb;
7738 gimple_stmt_iterator si;
7740 entry_bb = region->entry;
7741 exit_bb = region->exit;
7743 si = gsi_last_bb (entry_bb);
7744 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7745 gsi_remove (&si, true);
7746 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7748 si = gsi_last_bb (exit_bb);
7749 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7751 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7752 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7754 gsi_remove (&si, true);
7755 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7759 /* Generic expansion for OpenMP synchronization directives: master,
7760 ordered and critical. All we need to do here is remove the entry
7761 and exit markers for REGION. */
7763 static void
7764 expand_omp_synch (struct omp_region *region)
7766 basic_block entry_bb, exit_bb;
7767 gimple_stmt_iterator si;
7769 entry_bb = region->entry;
7770 exit_bb = region->exit;
7772 si = gsi_last_bb (entry_bb);
7773 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7774 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7775 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7776 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7777 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7778 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7779 gsi_remove (&si, true);
7780 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7782 if (exit_bb)
7784 si = gsi_last_bb (exit_bb);
7785 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7786 gsi_remove (&si, true);
7787 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7791 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7792 operation as a normal volatile load. */
7794 static bool
7795 expand_omp_atomic_load (basic_block load_bb, tree addr,
7796 tree loaded_val, int index)
7798 enum built_in_function tmpbase;
7799 gimple_stmt_iterator gsi;
7800 basic_block store_bb;
7801 location_t loc;
7802 gimple stmt;
7803 tree decl, call, type, itype;
7805 gsi = gsi_last_bb (load_bb);
7806 stmt = gsi_stmt (gsi);
7807 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7808 loc = gimple_location (stmt);
7810 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7811 is smaller than word size, then expand_atomic_load assumes that the load
7812 is atomic. We could avoid the builtin entirely in this case. */
7814 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7815 decl = builtin_decl_explicit (tmpbase);
7816 if (decl == NULL_TREE)
7817 return false;
7819 type = TREE_TYPE (loaded_val);
7820 itype = TREE_TYPE (TREE_TYPE (decl));
7822 call = build_call_expr_loc (loc, decl, 2, addr,
7823 build_int_cst (NULL,
7824 gimple_omp_atomic_seq_cst_p (stmt)
7825 ? MEMMODEL_SEQ_CST
7826 : MEMMODEL_RELAXED));
7827 if (!useless_type_conversion_p (type, itype))
7828 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7829 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7831 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7832 gsi_remove (&gsi, true);
7834 store_bb = single_succ (load_bb);
7835 gsi = gsi_last_bb (store_bb);
7836 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7837 gsi_remove (&gsi, true);
7839 if (gimple_in_ssa_p (cfun))
7840 update_ssa (TODO_update_ssa_no_phi);
7842 return true;
7845 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7846 operation as a normal volatile store. */
7848 static bool
7849 expand_omp_atomic_store (basic_block load_bb, tree addr,
7850 tree loaded_val, tree stored_val, int index)
7852 enum built_in_function tmpbase;
7853 gimple_stmt_iterator gsi;
7854 basic_block store_bb = single_succ (load_bb);
7855 location_t loc;
7856 gimple stmt;
7857 tree decl, call, type, itype;
7858 enum machine_mode imode;
7859 bool exchange;
7861 gsi = gsi_last_bb (load_bb);
7862 stmt = gsi_stmt (gsi);
7863 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7865 /* If the load value is needed, then this isn't a store but an exchange. */
7866 exchange = gimple_omp_atomic_need_value_p (stmt);
7868 gsi = gsi_last_bb (store_bb);
7869 stmt = gsi_stmt (gsi);
7870 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7871 loc = gimple_location (stmt);
7873 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7874 is smaller than word size, then expand_atomic_store assumes that the store
7875 is atomic. We could avoid the builtin entirely in this case. */
7877 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7878 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7879 decl = builtin_decl_explicit (tmpbase);
7880 if (decl == NULL_TREE)
7881 return false;
7883 type = TREE_TYPE (stored_val);
7885 /* Dig out the type of the function's second argument. */
7886 itype = TREE_TYPE (decl);
7887 itype = TYPE_ARG_TYPES (itype);
7888 itype = TREE_CHAIN (itype);
7889 itype = TREE_VALUE (itype);
7890 imode = TYPE_MODE (itype);
7892 if (exchange && !can_atomic_exchange_p (imode, true))
7893 return false;
7895 if (!useless_type_conversion_p (itype, type))
7896 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7897 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7898 build_int_cst (NULL,
7899 gimple_omp_atomic_seq_cst_p (stmt)
7900 ? MEMMODEL_SEQ_CST
7901 : MEMMODEL_RELAXED));
7902 if (exchange)
7904 if (!useless_type_conversion_p (type, itype))
7905 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7906 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7909 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7910 gsi_remove (&gsi, true);
7912 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7913 gsi = gsi_last_bb (load_bb);
7914 gsi_remove (&gsi, true);
7916 if (gimple_in_ssa_p (cfun))
7917 update_ssa (TODO_update_ssa_no_phi);
7919 return true;
7922 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7923 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7924 size of the data type, and thus usable to find the index of the builtin
7925 decl. Returns false if the expression is not of the proper form. */
7927 static bool
7928 expand_omp_atomic_fetch_op (basic_block load_bb,
7929 tree addr, tree loaded_val,
7930 tree stored_val, int index)
7932 enum built_in_function oldbase, newbase, tmpbase;
7933 tree decl, itype, call;
7934 tree lhs, rhs;
7935 basic_block store_bb = single_succ (load_bb);
7936 gimple_stmt_iterator gsi;
7937 gimple stmt;
7938 location_t loc;
7939 enum tree_code code;
7940 bool need_old, need_new;
7941 enum machine_mode imode;
7942 bool seq_cst;
7944 /* We expect to find the following sequences:
7946 load_bb:
7947 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7949 store_bb:
7950 val = tmp OP something; (or: something OP tmp)
7951 GIMPLE_OMP_STORE (val)
7953 ???FIXME: Allow a more flexible sequence.
7954 Perhaps use data flow to pick the statements.
7958 gsi = gsi_after_labels (store_bb);
7959 stmt = gsi_stmt (gsi);
7960 loc = gimple_location (stmt);
7961 if (!is_gimple_assign (stmt))
7962 return false;
7963 gsi_next (&gsi);
7964 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7965 return false;
7966 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7967 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7968 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7969 gcc_checking_assert (!need_old || !need_new);
7971 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7972 return false;
7974 /* Check for one of the supported fetch-op operations. */
7975 code = gimple_assign_rhs_code (stmt);
7976 switch (code)
7978 case PLUS_EXPR:
7979 case POINTER_PLUS_EXPR:
7980 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7981 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7982 break;
7983 case MINUS_EXPR:
7984 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7985 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7986 break;
7987 case BIT_AND_EXPR:
7988 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7989 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7990 break;
7991 case BIT_IOR_EXPR:
7992 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7993 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7994 break;
7995 case BIT_XOR_EXPR:
7996 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7997 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7998 break;
7999 default:
8000 return false;
8003 /* Make sure the expression is of the proper form. */
8004 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8005 rhs = gimple_assign_rhs2 (stmt);
8006 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8007 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8008 rhs = gimple_assign_rhs1 (stmt);
8009 else
8010 return false;
8012 tmpbase = ((enum built_in_function)
8013 ((need_new ? newbase : oldbase) + index + 1));
8014 decl = builtin_decl_explicit (tmpbase);
8015 if (decl == NULL_TREE)
8016 return false;
8017 itype = TREE_TYPE (TREE_TYPE (decl));
8018 imode = TYPE_MODE (itype);
8020 /* We could test all of the various optabs involved, but the fact of the
8021 matter is that (with the exception of i486 vs i586 and xadd) all targets
8022 that support any atomic operaton optab also implements compare-and-swap.
8023 Let optabs.c take care of expanding any compare-and-swap loop. */
8024 if (!can_compare_and_swap_p (imode, true))
8025 return false;
8027 gsi = gsi_last_bb (load_bb);
8028 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8030 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8031 It only requires that the operation happen atomically. Thus we can
8032 use the RELAXED memory model. */
8033 call = build_call_expr_loc (loc, decl, 3, addr,
8034 fold_convert_loc (loc, itype, rhs),
8035 build_int_cst (NULL,
8036 seq_cst ? MEMMODEL_SEQ_CST
8037 : MEMMODEL_RELAXED));
8039 if (need_old || need_new)
8041 lhs = need_old ? loaded_val : stored_val;
8042 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8043 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8045 else
8046 call = fold_convert_loc (loc, void_type_node, call);
8047 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8048 gsi_remove (&gsi, true);
8050 gsi = gsi_last_bb (store_bb);
8051 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8052 gsi_remove (&gsi, true);
8053 gsi = gsi_last_bb (store_bb);
8054 gsi_remove (&gsi, true);
8056 if (gimple_in_ssa_p (cfun))
8057 update_ssa (TODO_update_ssa_no_phi);
8059 return true;
8062 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8064 oldval = *addr;
8065 repeat:
8066 newval = rhs; // with oldval replacing *addr in rhs
8067 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8068 if (oldval != newval)
8069 goto repeat;
8071 INDEX is log2 of the size of the data type, and thus usable to find the
8072 index of the builtin decl. */
8074 static bool
8075 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8076 tree addr, tree loaded_val, tree stored_val,
8077 int index)
8079 tree loadedi, storedi, initial, new_storedi, old_vali;
8080 tree type, itype, cmpxchg, iaddr;
8081 gimple_stmt_iterator si;
8082 basic_block loop_header = single_succ (load_bb);
8083 gimple phi, stmt;
8084 edge e;
8085 enum built_in_function fncode;
8087 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8088 order to use the RELAXED memory model effectively. */
8089 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8090 + index + 1);
8091 cmpxchg = builtin_decl_explicit (fncode);
8092 if (cmpxchg == NULL_TREE)
8093 return false;
8094 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8095 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8097 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8098 return false;
8100 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8101 si = gsi_last_bb (load_bb);
8102 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8104 /* For floating-point values, we'll need to view-convert them to integers
8105 so that we can perform the atomic compare and swap. Simplify the
8106 following code by always setting up the "i"ntegral variables. */
8107 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8109 tree iaddr_val;
8111 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8112 true), NULL);
8113 iaddr_val
8114 = force_gimple_operand_gsi (&si,
8115 fold_convert (TREE_TYPE (iaddr), addr),
8116 false, NULL_TREE, true, GSI_SAME_STMT);
8117 stmt = gimple_build_assign (iaddr, iaddr_val);
8118 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8119 loadedi = create_tmp_var (itype, NULL);
8120 if (gimple_in_ssa_p (cfun))
8121 loadedi = make_ssa_name (loadedi, NULL);
8123 else
8125 iaddr = addr;
8126 loadedi = loaded_val;
8129 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8130 tree loaddecl = builtin_decl_explicit (fncode);
8131 if (loaddecl)
8132 initial
8133 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8134 build_call_expr (loaddecl, 2, iaddr,
8135 build_int_cst (NULL_TREE,
8136 MEMMODEL_RELAXED)));
8137 else
8138 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8139 build_int_cst (TREE_TYPE (iaddr), 0));
8141 initial
8142 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8143 GSI_SAME_STMT);
8145 /* Move the value to the LOADEDI temporary. */
8146 if (gimple_in_ssa_p (cfun))
8148 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8149 phi = create_phi_node (loadedi, loop_header);
8150 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8151 initial);
8153 else
8154 gsi_insert_before (&si,
8155 gimple_build_assign (loadedi, initial),
8156 GSI_SAME_STMT);
8157 if (loadedi != loaded_val)
8159 gimple_stmt_iterator gsi2;
8160 tree x;
8162 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8163 gsi2 = gsi_start_bb (loop_header);
8164 if (gimple_in_ssa_p (cfun))
8166 gimple stmt;
8167 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8168 true, GSI_SAME_STMT);
8169 stmt = gimple_build_assign (loaded_val, x);
8170 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8172 else
8174 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8175 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8176 true, GSI_SAME_STMT);
8179 gsi_remove (&si, true);
8181 si = gsi_last_bb (store_bb);
8182 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8184 if (iaddr == addr)
8185 storedi = stored_val;
8186 else
8187 storedi =
8188 force_gimple_operand_gsi (&si,
8189 build1 (VIEW_CONVERT_EXPR, itype,
8190 stored_val), true, NULL_TREE, true,
8191 GSI_SAME_STMT);
8193 /* Build the compare&swap statement. */
8194 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8195 new_storedi = force_gimple_operand_gsi (&si,
8196 fold_convert (TREE_TYPE (loadedi),
8197 new_storedi),
8198 true, NULL_TREE,
8199 true, GSI_SAME_STMT);
8201 if (gimple_in_ssa_p (cfun))
8202 old_vali = loadedi;
8203 else
8205 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
8206 stmt = gimple_build_assign (old_vali, loadedi);
8207 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8209 stmt = gimple_build_assign (loadedi, new_storedi);
8210 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8213 /* Note that we always perform the comparison as an integer, even for
8214 floating point. This allows the atomic operation to properly
8215 succeed even with NaNs and -0.0. */
8216 stmt = gimple_build_cond_empty
8217 (build2 (NE_EXPR, boolean_type_node,
8218 new_storedi, old_vali));
8219 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8221 /* Update cfg. */
8222 e = single_succ_edge (store_bb);
8223 e->flags &= ~EDGE_FALLTHRU;
8224 e->flags |= EDGE_FALSE_VALUE;
8226 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8228 /* Copy the new value to loadedi (we already did that before the condition
8229 if we are not in SSA). */
8230 if (gimple_in_ssa_p (cfun))
8232 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8233 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8236 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8237 gsi_remove (&si, true);
8239 struct loop *loop = alloc_loop ();
8240 loop->header = loop_header;
8241 loop->latch = store_bb;
8242 add_loop (loop, loop_header->loop_father);
8244 if (gimple_in_ssa_p (cfun))
8245 update_ssa (TODO_update_ssa_no_phi);
8247 return true;
8250 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8252 GOMP_atomic_start ();
8253 *addr = rhs;
8254 GOMP_atomic_end ();
8256 The result is not globally atomic, but works so long as all parallel
8257 references are within #pragma omp atomic directives. According to
8258 responses received from omp@openmp.org, appears to be within spec.
8259 Which makes sense, since that's how several other compilers handle
8260 this situation as well.
8261 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8262 expanding. STORED_VAL is the operand of the matching
8263 GIMPLE_OMP_ATOMIC_STORE.
8265 We replace
8266 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8267 loaded_val = *addr;
8269 and replace
8270 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8271 *addr = stored_val;
8274 static bool
8275 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8276 tree addr, tree loaded_val, tree stored_val)
8278 gimple_stmt_iterator si;
8279 gimple stmt;
8280 tree t;
8282 si = gsi_last_bb (load_bb);
8283 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8285 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8286 t = build_call_expr (t, 0);
8287 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8289 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8290 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8291 gsi_remove (&si, true);
8293 si = gsi_last_bb (store_bb);
8294 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8296 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8297 stored_val);
8298 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8300 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8301 t = build_call_expr (t, 0);
8302 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8303 gsi_remove (&si, true);
8305 if (gimple_in_ssa_p (cfun))
8306 update_ssa (TODO_update_ssa_no_phi);
8307 return true;
8310 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8311 using expand_omp_atomic_fetch_op. If it failed, we try to
8312 call expand_omp_atomic_pipeline, and if it fails too, the
8313 ultimate fallback is wrapping the operation in a mutex
8314 (expand_omp_atomic_mutex). REGION is the atomic region built
8315 by build_omp_regions_1(). */
8317 static void
8318 expand_omp_atomic (struct omp_region *region)
8320 basic_block load_bb = region->entry, store_bb = region->exit;
8321 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
8322 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8323 tree addr = gimple_omp_atomic_load_rhs (load);
8324 tree stored_val = gimple_omp_atomic_store_val (store);
8325 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8326 HOST_WIDE_INT index;
8328 /* Make sure the type is one of the supported sizes. */
8329 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8330 index = exact_log2 (index);
8331 if (index >= 0 && index <= 4)
8333 unsigned int align = TYPE_ALIGN_UNIT (type);
8335 /* __sync builtins require strict data alignment. */
8336 if (exact_log2 (align) >= index)
8338 /* Atomic load. */
8339 if (loaded_val == stored_val
8340 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8341 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8342 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8343 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8344 return;
8346 /* Atomic store. */
8347 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8348 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8349 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8350 && store_bb == single_succ (load_bb)
8351 && first_stmt (store_bb) == store
8352 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8353 stored_val, index))
8354 return;
8356 /* When possible, use specialized atomic update functions. */
8357 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8358 && store_bb == single_succ (load_bb)
8359 && expand_omp_atomic_fetch_op (load_bb, addr,
8360 loaded_val, stored_val, index))
8361 return;
8363 /* If we don't have specialized __sync builtins, try and implement
8364 as a compare and swap loop. */
8365 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8366 loaded_val, stored_val, index))
8367 return;
8371 /* The ultimate fallback is wrapping the operation in a mutex. */
8372 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8376 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8378 static void
8379 expand_omp_target (struct omp_region *region)
8381 basic_block entry_bb, exit_bb, new_bb;
8382 struct function *child_cfun = NULL;
8383 tree child_fn = NULL_TREE, block, t;
8384 gimple_stmt_iterator gsi;
8385 gimple entry_stmt, stmt;
8386 edge e;
8388 entry_stmt = last_stmt (region->entry);
8389 new_bb = region->entry;
8390 int kind = gimple_omp_target_kind (entry_stmt);
8391 if (kind == GF_OMP_TARGET_KIND_REGION)
8393 child_fn = gimple_omp_target_child_fn (entry_stmt);
8394 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8397 entry_bb = region->entry;
8398 exit_bb = region->exit;
8400 if (kind == GF_OMP_TARGET_KIND_REGION)
8402 unsigned srcidx, dstidx, num;
8404 /* If the target region needs data sent from the parent
8405 function, then the very first statement (except possible
8406 tree profile counter updates) of the parallel body
8407 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8408 &.OMP_DATA_O is passed as an argument to the child function,
8409 we need to replace it with the argument as seen by the child
8410 function.
8412 In most cases, this will end up being the identity assignment
8413 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8414 a function call that has been inlined, the original PARM_DECL
8415 .OMP_DATA_I may have been converted into a different local
8416 variable. In which case, we need to keep the assignment. */
8417 if (gimple_omp_target_data_arg (entry_stmt))
8419 basic_block entry_succ_bb = single_succ (entry_bb);
8420 gimple_stmt_iterator gsi;
8421 tree arg;
8422 gimple tgtcopy_stmt = NULL;
8423 tree sender
8424 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
8426 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8428 gcc_assert (!gsi_end_p (gsi));
8429 stmt = gsi_stmt (gsi);
8430 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8431 continue;
8433 if (gimple_num_ops (stmt) == 2)
8435 tree arg = gimple_assign_rhs1 (stmt);
8437 /* We're ignoring the subcode because we're
8438 effectively doing a STRIP_NOPS. */
8440 if (TREE_CODE (arg) == ADDR_EXPR
8441 && TREE_OPERAND (arg, 0) == sender)
8443 tgtcopy_stmt = stmt;
8444 break;
8449 gcc_assert (tgtcopy_stmt != NULL);
8450 arg = DECL_ARGUMENTS (child_fn);
8452 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8453 gsi_remove (&gsi, true);
8456 /* Declare local variables needed in CHILD_CFUN. */
8457 block = DECL_INITIAL (child_fn);
8458 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8459 /* The gimplifier could record temporaries in target block
8460 rather than in containing function's local_decls chain,
8461 which would mean cgraph missed finalizing them. Do it now. */
8462 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8463 if (TREE_CODE (t) == VAR_DECL
8464 && TREE_STATIC (t)
8465 && !DECL_EXTERNAL (t))
8466 varpool_finalize_decl (t);
8467 DECL_SAVED_TREE (child_fn) = NULL;
8468 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8469 gimple_set_body (child_fn, NULL);
8470 TREE_USED (block) = 1;
8472 /* Reset DECL_CONTEXT on function arguments. */
8473 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8474 DECL_CONTEXT (t) = child_fn;
8476 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8477 so that it can be moved to the child function. */
8478 gsi = gsi_last_bb (entry_bb);
8479 stmt = gsi_stmt (gsi);
8480 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
8481 && gimple_omp_target_kind (stmt)
8482 == GF_OMP_TARGET_KIND_REGION);
8483 gsi_remove (&gsi, true);
8484 e = split_block (entry_bb, stmt);
8485 entry_bb = e->dest;
8486 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8488 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8489 if (exit_bb)
8491 gsi = gsi_last_bb (exit_bb);
8492 gcc_assert (!gsi_end_p (gsi)
8493 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8494 stmt = gimple_build_return (NULL);
8495 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8496 gsi_remove (&gsi, true);
8499 /* Move the target region into CHILD_CFUN. */
8501 block = gimple_block (entry_stmt);
8503 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8504 if (exit_bb)
8505 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8506 /* When the OMP expansion process cannot guarantee an up-to-date
8507 loop tree arrange for the child function to fixup loops. */
8508 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8509 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8511 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8512 num = vec_safe_length (child_cfun->local_decls);
8513 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8515 t = (*child_cfun->local_decls)[srcidx];
8516 if (DECL_CONTEXT (t) == cfun->decl)
8517 continue;
8518 if (srcidx != dstidx)
8519 (*child_cfun->local_decls)[dstidx] = t;
8520 dstidx++;
8522 if (dstidx != num)
8523 vec_safe_truncate (child_cfun->local_decls, dstidx);
8525 /* Inform the callgraph about the new function. */
8526 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8527 cgraph_add_new_function (child_fn, true);
8529 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8530 fixed in a following pass. */
8531 push_cfun (child_cfun);
8532 rebuild_cgraph_edges ();
8534 /* Some EH regions might become dead, see PR34608. If
8535 pass_cleanup_cfg isn't the first pass to happen with the
8536 new child, these dead EH edges might cause problems.
8537 Clean them up now. */
8538 if (flag_exceptions)
8540 basic_block bb;
8541 bool changed = false;
8543 FOR_EACH_BB_FN (bb, cfun)
8544 changed |= gimple_purge_dead_eh_edges (bb);
8545 if (changed)
8546 cleanup_tree_cfg ();
8548 pop_cfun ();
8551 /* Emit a library call to launch the target region, or do data
8552 transfers. */
8553 tree t1, t2, t3, t4, device, cond, c, clauses;
8554 enum built_in_function start_ix;
8555 location_t clause_loc;
8557 clauses = gimple_omp_target_clauses (entry_stmt);
8559 switch (kind)
8561 case GF_OMP_TARGET_KIND_REGION:
8562 start_ix = BUILT_IN_GOMP_TARGET;
8563 break;
8564 case GF_OMP_TARGET_KIND_DATA:
8565 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8566 break;
8567 case GF_OMP_TARGET_KIND_UPDATE:
8568 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8569 break;
8570 case GF_OMP_TARGET_KIND_OACC_DATA:
8571 start_ix = BUILT_IN_GOACC_DATA_START;
8572 break;
8573 default:
8574 gcc_unreachable ();
8577 /* By default, the value of DEVICE is -1 (let runtime library choose)
8578 and there is no conditional. */
8579 cond = NULL_TREE;
8580 device = build_int_cst (integer_type_node, -1);
8582 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8583 gcc_assert (!c || kind != GF_OMP_TARGET_KIND_OACC_DATA);
8584 if (c)
8585 cond = OMP_CLAUSE_IF_EXPR (c);
8587 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8588 gcc_assert (!c || kind != GF_OMP_TARGET_KIND_OACC_DATA);
8589 if (c)
8591 device = OMP_CLAUSE_DEVICE_ID (c);
8592 clause_loc = OMP_CLAUSE_LOCATION (c);
8594 else
8595 clause_loc = gimple_location (entry_stmt);
8597 /* Ensure 'device' is of the correct type. */
8598 device = fold_convert_loc (clause_loc, integer_type_node, device);
8600 /* If we found the clause 'if (cond)', build
8601 (cond ? device : -2). */
8602 if (cond)
8604 gcc_assert (kind != GF_OMP_TARGET_KIND_OACC_DATA);
8605 cond = gimple_boolify (cond);
8607 basic_block cond_bb, then_bb, else_bb;
8608 edge e;
8609 tree tmp_var;
8611 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8612 if (kind != GF_OMP_TARGET_KIND_REGION)
8614 gsi = gsi_last_bb (new_bb);
8615 gsi_prev (&gsi);
8616 e = split_block (new_bb, gsi_stmt (gsi));
8618 else
8619 e = split_block (new_bb, NULL);
8620 cond_bb = e->src;
8621 new_bb = e->dest;
8622 remove_edge (e);
8624 then_bb = create_empty_bb (cond_bb);
8625 else_bb = create_empty_bb (then_bb);
8626 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8627 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8629 stmt = gimple_build_cond_empty (cond);
8630 gsi = gsi_last_bb (cond_bb);
8631 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8633 gsi = gsi_start_bb (then_bb);
8634 stmt = gimple_build_assign (tmp_var, device);
8635 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8637 gsi = gsi_start_bb (else_bb);
8638 stmt = gimple_build_assign (tmp_var,
8639 build_int_cst (integer_type_node, -2));
8640 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8642 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8643 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8644 if (current_loops)
8646 add_bb_to_loop (then_bb, cond_bb->loop_father);
8647 add_bb_to_loop (else_bb, cond_bb->loop_father);
8649 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8650 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8652 device = tmp_var;
8655 gsi = gsi_last_bb (new_bb);
8656 t = gimple_omp_target_data_arg (entry_stmt);
8657 if (t == NULL)
8659 t1 = size_zero_node;
8660 t2 = build_zero_cst (ptr_type_node);
8661 t3 = t2;
8662 t4 = t2;
8664 else
8666 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8667 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8668 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8669 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8670 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8673 gimple g;
8674 /* FIXME: This will be address of
8675 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8676 symbol, as soon as the linker plugin is able to create it for us. */
8677 tree openmp_target = build_zero_cst (ptr_type_node);
8678 if (kind == GF_OMP_TARGET_KIND_REGION)
8680 tree fnaddr = build_fold_addr_expr (child_fn);
8681 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8682 device, fnaddr, openmp_target, t1, t2, t3, t4);
8684 else
8685 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8686 device, openmp_target, t1, t2, t3, t4);
8687 gimple_set_location (g, gimple_location (entry_stmt));
8688 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8689 if (kind != GF_OMP_TARGET_KIND_REGION)
8691 g = gsi_stmt (gsi);
8692 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8693 gsi_remove (&gsi, true);
8695 if ((kind == GF_OMP_TARGET_KIND_DATA
8696 || kind == GF_OMP_TARGET_KIND_OACC_DATA)
8697 && region->exit)
8699 gsi = gsi_last_bb (region->exit);
8700 g = gsi_stmt (gsi);
8701 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8702 gsi_remove (&gsi, true);
8707 /* Expand the parallel region tree rooted at REGION. Expansion
8708 proceeds in depth-first order. Innermost regions are expanded
8709 first. This way, parallel regions that require a new function to
8710 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8711 internal dependencies in their body. */
8713 static void
8714 expand_omp (struct omp_region *region)
8716 while (region)
8718 location_t saved_location;
8719 gimple inner_stmt = NULL;
8721 /* First, determine whether this is a combined parallel+workshare
8722 region. */
8723 if (region->type == GIMPLE_OMP_PARALLEL)
8724 determine_parallel_type (region);
8726 if (region->type == GIMPLE_OMP_FOR
8727 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8728 inner_stmt = last_stmt (region->inner->entry);
8730 if (region->inner)
8731 expand_omp (region->inner);
8733 saved_location = input_location;
8734 if (gimple_has_location (last_stmt (region->entry)))
8735 input_location = gimple_location (last_stmt (region->entry));
8737 switch (region->type)
8739 case GIMPLE_OACC_KERNELS:
8740 case GIMPLE_OACC_PARALLEL:
8741 expand_oacc_offload (region);
8742 break;
8744 case GIMPLE_OMP_PARALLEL:
8745 case GIMPLE_OMP_TASK:
8746 expand_omp_taskreg (region);
8747 break;
8749 case GIMPLE_OMP_FOR:
8750 expand_omp_for (region, inner_stmt);
8751 break;
8753 case GIMPLE_OMP_SECTIONS:
8754 expand_omp_sections (region);
8755 break;
8757 case GIMPLE_OMP_SECTION:
8758 /* Individual omp sections are handled together with their
8759 parent GIMPLE_OMP_SECTIONS region. */
8760 break;
8762 case GIMPLE_OMP_SINGLE:
8763 expand_omp_single (region);
8764 break;
8766 case GIMPLE_OMP_MASTER:
8767 case GIMPLE_OMP_TASKGROUP:
8768 case GIMPLE_OMP_ORDERED:
8769 case GIMPLE_OMP_CRITICAL:
8770 case GIMPLE_OMP_TEAMS:
8771 expand_omp_synch (region);
8772 break;
8774 case GIMPLE_OMP_ATOMIC_LOAD:
8775 expand_omp_atomic (region);
8776 break;
8778 case GIMPLE_OMP_TARGET:
8779 expand_omp_target (region);
8780 break;
8782 default:
8783 gcc_unreachable ();
8786 input_location = saved_location;
8787 region = region->next;
8792 /* Helper for build_omp_regions. Scan the dominator tree starting at
8793 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8794 true, the function ends once a single tree is built (otherwise, whole
8795 forest of OMP constructs may be built). */
8797 static void
8798 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8799 bool single_tree)
8801 gimple_stmt_iterator gsi;
8802 gimple stmt;
8803 basic_block son;
8805 gsi = gsi_last_bb (bb);
8806 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8808 struct omp_region *region;
8809 enum gimple_code code;
8811 stmt = gsi_stmt (gsi);
8812 code = gimple_code (stmt);
8813 if (code == GIMPLE_OMP_RETURN)
8815 /* STMT is the return point out of region PARENT. Mark it
8816 as the exit point and make PARENT the immediately
8817 enclosing region. */
8818 gcc_assert (parent);
8819 region = parent;
8820 region->exit = bb;
8821 parent = parent->outer;
8823 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8825 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8826 GIMPLE_OMP_RETURN, but matches with
8827 GIMPLE_OMP_ATOMIC_LOAD. */
8828 gcc_assert (parent);
8829 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8830 region = parent;
8831 region->exit = bb;
8832 parent = parent->outer;
8835 else if (code == GIMPLE_OMP_CONTINUE)
8837 gcc_assert (parent);
8838 parent->cont = bb;
8840 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8842 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8843 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8846 else if (code == GIMPLE_OMP_TARGET
8847 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8848 new_omp_region (bb, code, parent);
8849 else
8851 /* Otherwise, this directive becomes the parent for a new
8852 region. */
8853 region = new_omp_region (bb, code, parent);
8854 parent = region;
8858 if (single_tree && !parent)
8859 return;
8861 for (son = first_dom_son (CDI_DOMINATORS, bb);
8862 son;
8863 son = next_dom_son (CDI_DOMINATORS, son))
8864 build_omp_regions_1 (son, parent, single_tree);
8867 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8868 root_omp_region. */
8870 static void
8871 build_omp_regions_root (basic_block root)
8873 gcc_assert (root_omp_region == NULL);
8874 build_omp_regions_1 (root, NULL, true);
8875 gcc_assert (root_omp_region != NULL);
8878 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8880 void
8881 omp_expand_local (basic_block head)
8883 build_omp_regions_root (head);
8884 if (dump_file && (dump_flags & TDF_DETAILS))
8886 fprintf (dump_file, "\nOMP region tree\n\n");
8887 dump_omp_region (dump_file, root_omp_region, 0);
8888 fprintf (dump_file, "\n");
8891 remove_exit_barriers (root_omp_region);
8892 expand_omp (root_omp_region);
8894 free_omp_regions ();
8897 /* Scan the CFG and build a tree of OMP regions. Return the root of
8898 the OMP region tree. */
8900 static void
8901 build_omp_regions (void)
8903 gcc_assert (root_omp_region == NULL);
8904 calculate_dominance_info (CDI_DOMINATORS);
8905 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8908 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8910 static unsigned int
8911 execute_expand_omp (void)
8913 build_omp_regions ();
8915 if (!root_omp_region)
8916 return 0;
8918 if (dump_file)
8920 fprintf (dump_file, "\nOMP region tree\n\n");
8921 dump_omp_region (dump_file, root_omp_region, 0);
8922 fprintf (dump_file, "\n");
8925 remove_exit_barriers (root_omp_region);
8927 expand_omp (root_omp_region);
8929 cleanup_tree_cfg ();
8931 free_omp_regions ();
8933 return 0;
8936 /* OMP expansion -- the default pass, run before creation of SSA form. */
8938 static bool
8939 gate_expand_omp (void)
8941 return ((flag_openacc != 0 || flag_openmp != 0 || flag_openmp_simd != 0
8942 || flag_cilkplus != 0) && !seen_error ());
8945 namespace {
8947 const pass_data pass_data_expand_omp =
8949 GIMPLE_PASS, /* type */
8950 "ompexp", /* name */
8951 OPTGROUP_NONE, /* optinfo_flags */
8952 true, /* has_gate */
8953 true, /* has_execute */
8954 TV_NONE, /* tv_id */
8955 PROP_gimple_any, /* properties_required */
8956 0, /* properties_provided */
8957 0, /* properties_destroyed */
8958 0, /* todo_flags_start */
8959 0, /* todo_flags_finish */
8962 class pass_expand_omp : public gimple_opt_pass
8964 public:
8965 pass_expand_omp (gcc::context *ctxt)
8966 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8969 /* opt_pass methods: */
8970 bool gate () { return gate_expand_omp (); }
8971 unsigned int execute () { return execute_expand_omp (); }
8973 }; // class pass_expand_omp
8975 } // anon namespace
8977 gimple_opt_pass *
8978 make_pass_expand_omp (gcc::context *ctxt)
8980 return new pass_expand_omp (ctxt);
8983 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8985 /* Lower the OpenACC offload directive in the current statement
8986 in GSI_P. CTX holds context information for the directive. */
8988 static void
8989 lower_oacc_offload (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8991 tree clauses;
8992 tree child_fn, t, c;
8993 gimple stmt = gsi_stmt (*gsi_p);
8994 gimple par_bind, bind;
8995 gimple_seq par_body, olist, ilist, new_body;
8996 location_t loc = gimple_location (stmt);
8997 unsigned int map_cnt = 0;
8998 tree (*gimple_omp_clauses) (const_gimple);
8999 void (*gimple_omp_set_data_arg) (gimple, tree);
9000 switch (gimple_code (stmt))
9002 case GIMPLE_OACC_KERNELS:
9003 gimple_omp_clauses = gimple_oacc_kernels_clauses;
9004 gimple_omp_set_data_arg = gimple_oacc_kernels_set_data_arg;
9005 break;
9006 case GIMPLE_OACC_PARALLEL:
9007 gimple_omp_clauses = gimple_oacc_parallel_clauses;
9008 gimple_omp_set_data_arg = gimple_oacc_parallel_set_data_arg;
9009 break;
9010 default:
9011 gcc_unreachable ();
9014 clauses = gimple_omp_clauses (stmt);
9015 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9016 par_body = gimple_bind_body (par_bind);
9017 child_fn = ctx->cb.dst_fn;
9019 push_gimplify_context ();
9021 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9022 switch (OMP_CLAUSE_CODE (c))
9024 tree var, x;
9026 default:
9027 break;
9028 case OMP_CLAUSE_MAP:
9029 var = OMP_CLAUSE_DECL (c);
9030 if (!DECL_P (var))
9032 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
9033 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9034 map_cnt++;
9035 continue;
9038 if (DECL_SIZE (var)
9039 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
9041 tree var2 = DECL_VALUE_EXPR (var);
9042 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
9043 var2 = TREE_OPERAND (var2, 0);
9044 gcc_assert (DECL_P (var2));
9045 var = var2;
9048 if (!maybe_lookup_field (var, ctx))
9049 continue;
9051 /* Preserve indentation of lower_omp_target. */
9052 if (1)
9054 x = build_receiver_ref (var, true, ctx);
9055 tree new_var = lookup_decl (var, ctx);
9056 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9057 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9058 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9059 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
9060 x = build_simple_mem_ref (x);
9061 SET_DECL_VALUE_EXPR (new_var, x);
9062 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
9064 map_cnt++;
9067 target_nesting_level++;
9068 lower_omp (&par_body, ctx);
9069 target_nesting_level--;
9071 /* Declare all the variables created by mapping and the variables
9072 declared in the scope of the body. */
9073 record_vars_into (ctx->block_vars, child_fn);
9074 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9076 olist = NULL;
9077 ilist = NULL;
9078 if (ctx->record_type)
9080 ctx->sender_decl
9081 = create_tmp_var (ctx->record_type, ".omp_data_arr");
9082 DECL_NAMELESS (ctx->sender_decl) = 1;
9083 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9084 t = make_tree_vec (3);
9085 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
9086 TREE_VEC_ELT (t, 1)
9087 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
9088 ".omp_data_sizes");
9089 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
9090 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
9091 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
9092 TREE_VEC_ELT (t, 2)
9093 = create_tmp_var (build_array_type_nelts (short_unsigned_type_node,
9094 map_cnt),
9095 ".omp_data_kinds");
9096 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
9097 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
9098 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
9099 gimple_omp_set_data_arg (stmt, t);
9101 vec<constructor_elt, va_gc> *vsize;
9102 vec<constructor_elt, va_gc> *vkind;
9103 vec_alloc (vsize, map_cnt);
9104 vec_alloc (vkind, map_cnt);
9105 unsigned int map_idx = 0;
9107 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9108 switch (OMP_CLAUSE_CODE (c))
9110 tree ovar, nc;
9112 default:
9113 break;
9114 case OMP_CLAUSE_MAP:
9115 nc = c;
9116 ovar = OMP_CLAUSE_DECL (c);
9117 if (!DECL_P (ovar))
9119 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9120 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9122 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
9123 == get_base_address (ovar));
9124 nc = OMP_CLAUSE_CHAIN (c);
9125 ovar = OMP_CLAUSE_DECL (nc);
9127 else
9129 tree x = build_sender_ref (ovar, ctx);
9130 tree v
9131 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
9132 gimplify_assign (x, v, &ilist);
9133 nc = NULL_TREE;
9136 else
9138 if (DECL_SIZE (ovar)
9139 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
9141 tree ovar2 = DECL_VALUE_EXPR (ovar);
9142 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
9143 ovar2 = TREE_OPERAND (ovar2, 0);
9144 gcc_assert (DECL_P (ovar2));
9145 ovar = ovar2;
9147 if (!maybe_lookup_field (ovar, ctx))
9148 continue;
9151 if (nc)
9153 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
9154 tree x = build_sender_ref (ovar, ctx);
9155 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9156 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9157 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9158 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
9160 tree avar
9161 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
9162 mark_addressable (avar);
9163 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
9164 avar = build_fold_addr_expr (avar);
9165 gimplify_assign (x, avar, &ilist);
9167 else if (is_gimple_reg (var))
9169 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
9170 mark_addressable (avar);
9171 enum omp_clause_map_kind map_kind
9172 = OMP_CLAUSE_MAP_KIND (c);
9173 if ((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
9174 && (map_kind & OMP_CLAUSE_MAP_TO))
9175 || map_kind == OMP_CLAUSE_MAP_POINTER)
9176 gimplify_assign (avar, var, &ilist);
9177 avar = build_fold_addr_expr (avar);
9178 gimplify_assign (x, avar, &ilist);
9179 if ((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
9180 && (map_kind & OMP_CLAUSE_MAP_FROM))
9181 && !TYPE_READONLY (TREE_TYPE (var)))
9183 x = build_sender_ref (ovar, ctx);
9184 x = build_simple_mem_ref (x);
9185 gimplify_assign (var, x, &olist);
9188 else
9190 var = build_fold_addr_expr (var);
9191 gimplify_assign (x, var, &ilist);
9194 tree s = OMP_CLAUSE_SIZE (c);
9195 if (s == NULL_TREE)
9196 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
9197 s = fold_convert (size_type_node, s);
9198 tree purpose = size_int (map_idx++);
9199 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
9200 if (TREE_CODE (s) != INTEGER_CST)
9201 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
9203 unsigned short tkind = 0;
9204 switch (OMP_CLAUSE_CODE (c))
9206 case OMP_CLAUSE_MAP:
9207 tkind = OMP_CLAUSE_MAP_KIND (c);
9208 break;
9209 default:
9210 gcc_unreachable ();
9212 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
9213 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
9214 talign = DECL_ALIGN_UNIT (ovar);
9215 talign = ceil_log2 (talign);
9216 tkind |= talign << 8;
9217 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
9218 build_int_cst (short_unsigned_type_node,
9219 tkind));
9220 if (nc && nc != c)
9221 c = nc;
9224 gcc_assert (map_idx == map_cnt);
9226 DECL_INITIAL (TREE_VEC_ELT (t, 1))
9227 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
9228 DECL_INITIAL (TREE_VEC_ELT (t, 2))
9229 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
9230 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
9232 gimple_seq initlist = NULL;
9233 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
9234 TREE_VEC_ELT (t, 1)),
9235 &initlist, true, NULL_TREE);
9236 gimple_seq_add_seq (&ilist, initlist);
9238 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
9239 NULL);
9240 TREE_THIS_VOLATILE (clobber) = 1;
9241 gimple_seq_add_stmt (&olist,
9242 gimple_build_assign (TREE_VEC_ELT (t, 1),
9243 clobber));
9246 tree clobber = build_constructor (ctx->record_type, NULL);
9247 TREE_THIS_VOLATILE (clobber) = 1;
9248 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9249 clobber));
9252 /* Once all the expansions are done, sequence all the different
9253 fragments inside gimple_omp_body. */
9255 new_body = NULL;
9257 if (ctx->record_type)
9259 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9260 /* fixup_child_record_type might have changed receiver_decl's type. */
9261 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9262 gimple_seq_add_stmt (&new_body,
9263 gimple_build_assign (ctx->receiver_decl, t));
9266 gimple_seq_add_seq (&new_body, par_body);
9267 gcc_assert (!ctx->cancellable);
9268 new_body = maybe_catch_exception (new_body);
9269 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9270 gimple_omp_set_body (stmt, new_body);
9272 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9273 gsi_replace (gsi_p, bind, true);
9274 gimple_bind_add_seq (bind, ilist);
9275 gimple_bind_add_stmt (bind, stmt);
9276 gimple_bind_add_seq (bind, olist);
9278 pop_gimplify_context (NULL);
9281 /* If ctx is a worksharing context inside of a cancellable parallel
9282 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9283 and conditional branch to parallel's cancel_label to handle
9284 cancellation in the implicit barrier. */
9286 static void
9287 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9289 gimple omp_return = gimple_seq_last_stmt (*body);
9290 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
9291 if (gimple_omp_return_nowait_p (omp_return))
9292 return;
9293 if (ctx->outer
9294 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
9295 && ctx->outer->cancellable)
9297 tree lhs = create_tmp_var (boolean_type_node, NULL);
9298 gimple_omp_return_set_lhs (omp_return, lhs);
9299 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
9300 gimple g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
9301 ctx->outer->cancel_label, fallthru_label);
9302 gimple_seq_add_stmt (body, g);
9303 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
9307 /* Lower the OpenMP sections directive in the current statement in GSI_P.
9308 CTX is the enclosing OMP context for the current statement. */
9310 static void
9311 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9313 tree block, control;
9314 gimple_stmt_iterator tgsi;
9315 gimple stmt, new_stmt, bind, t;
9316 gimple_seq ilist, dlist, olist, new_body;
9318 stmt = gsi_stmt (*gsi_p);
9320 push_gimplify_context ();
9322 dlist = NULL;
9323 ilist = NULL;
9324 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
9325 &ilist, &dlist, ctx, NULL);
9327 new_body = gimple_omp_body (stmt);
9328 gimple_omp_set_body (stmt, NULL);
9329 tgsi = gsi_start (new_body);
9330 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
9332 omp_context *sctx;
9333 gimple sec_start;
9335 sec_start = gsi_stmt (tgsi);
9336 sctx = maybe_lookup_ctx (sec_start);
9337 gcc_assert (sctx);
9339 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
9340 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
9341 GSI_CONTINUE_LINKING);
9342 gimple_omp_set_body (sec_start, NULL);
9344 if (gsi_one_before_end_p (tgsi))
9346 gimple_seq l = NULL;
9347 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
9348 &l, ctx);
9349 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
9350 gimple_omp_section_set_last (sec_start);
9353 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
9354 GSI_CONTINUE_LINKING);
9357 block = make_node (BLOCK);
9358 bind = gimple_build_bind (NULL, new_body, block);
9360 olist = NULL;
9361 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
9363 block = make_node (BLOCK);
9364 new_stmt = gimple_build_bind (NULL, NULL, block);
9365 gsi_replace (gsi_p, new_stmt, true);
9367 pop_gimplify_context (new_stmt);
9368 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9369 BLOCK_VARS (block) = gimple_bind_vars (bind);
9370 if (BLOCK_VARS (block))
9371 TREE_USED (block) = 1;
9373 new_body = NULL;
9374 gimple_seq_add_seq (&new_body, ilist);
9375 gimple_seq_add_stmt (&new_body, stmt);
9376 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
9377 gimple_seq_add_stmt (&new_body, bind);
9379 control = create_tmp_var (unsigned_type_node, ".section");
9380 t = gimple_build_omp_continue (control, control);
9381 gimple_omp_sections_set_control (stmt, control);
9382 gimple_seq_add_stmt (&new_body, t);
9384 gimple_seq_add_seq (&new_body, olist);
9385 if (ctx->cancellable)
9386 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9387 gimple_seq_add_seq (&new_body, dlist);
9389 new_body = maybe_catch_exception (new_body);
9391 t = gimple_build_omp_return
9392 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
9393 OMP_CLAUSE_NOWAIT));
9394 gimple_seq_add_stmt (&new_body, t);
9395 maybe_add_implicit_barrier_cancel (ctx, &new_body);
9397 gimple_bind_set_body (new_stmt, new_body);
9401 /* A subroutine of lower_omp_single. Expand the simple form of
9402 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
9404 if (GOMP_single_start ())
9405 BODY;
9406 [ GOMP_barrier (); ] -> unless 'nowait' is present.
9408 FIXME. It may be better to delay expanding the logic of this until
9409 pass_expand_omp. The expanded logic may make the job more difficult
9410 to a synchronization analysis pass. */
9412 static void
9413 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
9415 location_t loc = gimple_location (single_stmt);
9416 tree tlabel = create_artificial_label (loc);
9417 tree flabel = create_artificial_label (loc);
9418 gimple call, cond;
9419 tree lhs, decl;
9421 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
9422 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
9423 call = gimple_build_call (decl, 0);
9424 gimple_call_set_lhs (call, lhs);
9425 gimple_seq_add_stmt (pre_p, call);
9427 cond = gimple_build_cond (EQ_EXPR, lhs,
9428 fold_convert_loc (loc, TREE_TYPE (lhs),
9429 boolean_true_node),
9430 tlabel, flabel);
9431 gimple_seq_add_stmt (pre_p, cond);
9432 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
9433 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9434 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
9438 /* A subroutine of lower_omp_single. Expand the simple form of
9439 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
9441 #pragma omp single copyprivate (a, b, c)
9443 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
9446 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
9448 BODY;
9449 copyout.a = a;
9450 copyout.b = b;
9451 copyout.c = c;
9452 GOMP_single_copy_end (&copyout);
9454 else
9456 a = copyout_p->a;
9457 b = copyout_p->b;
9458 c = copyout_p->c;
9460 GOMP_barrier ();
9463 FIXME. It may be better to delay expanding the logic of this until
9464 pass_expand_omp. The expanded logic may make the job more difficult
9465 to a synchronization analysis pass. */
9467 static void
9468 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
9470 tree ptr_type, t, l0, l1, l2, bfn_decl;
9471 gimple_seq copyin_seq;
9472 location_t loc = gimple_location (single_stmt);
9474 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
9476 ptr_type = build_pointer_type (ctx->record_type);
9477 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
9479 l0 = create_artificial_label (loc);
9480 l1 = create_artificial_label (loc);
9481 l2 = create_artificial_label (loc);
9483 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
9484 t = build_call_expr_loc (loc, bfn_decl, 0);
9485 t = fold_convert_loc (loc, ptr_type, t);
9486 gimplify_assign (ctx->receiver_decl, t, pre_p);
9488 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
9489 build_int_cst (ptr_type, 0));
9490 t = build3 (COND_EXPR, void_type_node, t,
9491 build_and_jump (&l0), build_and_jump (&l1));
9492 gimplify_and_add (t, pre_p);
9494 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
9496 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9498 copyin_seq = NULL;
9499 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
9500 &copyin_seq, ctx);
9502 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9503 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
9504 t = build_call_expr_loc (loc, bfn_decl, 1, t);
9505 gimplify_and_add (t, pre_p);
9507 t = build_and_jump (&l2);
9508 gimplify_and_add (t, pre_p);
9510 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
9512 gimple_seq_add_seq (pre_p, copyin_seq);
9514 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
9518 /* Expand code for an OpenMP single directive. */
9520 static void
9521 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9523 tree block;
9524 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
9525 gimple_seq bind_body, bind_body_tail = NULL, dlist;
9527 push_gimplify_context ();
9529 block = make_node (BLOCK);
9530 bind = gimple_build_bind (NULL, NULL, block);
9531 gsi_replace (gsi_p, bind, true);
9532 bind_body = NULL;
9533 dlist = NULL;
9534 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
9535 &bind_body, &dlist, ctx, NULL);
9536 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
9538 gimple_seq_add_stmt (&bind_body, single_stmt);
9540 if (ctx->record_type)
9541 lower_omp_single_copy (single_stmt, &bind_body, ctx);
9542 else
9543 lower_omp_single_simple (single_stmt, &bind_body);
9545 gimple_omp_set_body (single_stmt, NULL);
9547 gimple_seq_add_seq (&bind_body, dlist);
9549 bind_body = maybe_catch_exception (bind_body);
9551 t = gimple_build_omp_return
9552 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
9553 OMP_CLAUSE_NOWAIT));
9554 gimple_seq_add_stmt (&bind_body_tail, t);
9555 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
9556 if (ctx->record_type)
9558 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9559 tree clobber = build_constructor (ctx->record_type, NULL);
9560 TREE_THIS_VOLATILE (clobber) = 1;
9561 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9562 clobber), GSI_SAME_STMT);
9564 gimple_seq_add_seq (&bind_body, bind_body_tail);
9565 gimple_bind_set_body (bind, bind_body);
9567 pop_gimplify_context (bind);
9569 gimple_bind_append_vars (bind, ctx->block_vars);
9570 BLOCK_VARS (block) = ctx->block_vars;
9571 if (BLOCK_VARS (block))
9572 TREE_USED (block) = 1;
9576 /* Expand code for an OpenMP master directive. */
9578 static void
9579 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9581 tree block, lab = NULL, x, bfn_decl;
9582 gimple stmt = gsi_stmt (*gsi_p), bind;
9583 location_t loc = gimple_location (stmt);
9584 gimple_seq tseq;
9586 push_gimplify_context ();
9588 block = make_node (BLOCK);
9589 bind = gimple_build_bind (NULL, NULL, block);
9590 gsi_replace (gsi_p, bind, true);
9591 gimple_bind_add_stmt (bind, stmt);
9593 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9594 x = build_call_expr_loc (loc, bfn_decl, 0);
9595 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
9596 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9597 tseq = NULL;
9598 gimplify_and_add (x, &tseq);
9599 gimple_bind_add_seq (bind, tseq);
9601 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9602 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9603 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9604 gimple_omp_set_body (stmt, NULL);
9606 gimple_bind_add_stmt (bind, gimple_build_label (lab));
9608 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9610 pop_gimplify_context (bind);
9612 gimple_bind_append_vars (bind, ctx->block_vars);
9613 BLOCK_VARS (block) = ctx->block_vars;
9617 /* Expand code for an OpenMP taskgroup directive. */
9619 static void
9620 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9622 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9623 tree block = make_node (BLOCK);
9625 bind = gimple_build_bind (NULL, NULL, block);
9626 gsi_replace (gsi_p, bind, true);
9627 gimple_bind_add_stmt (bind, stmt);
9629 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9631 gimple_bind_add_stmt (bind, x);
9633 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9634 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9635 gimple_omp_set_body (stmt, NULL);
9637 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9639 gimple_bind_append_vars (bind, ctx->block_vars);
9640 BLOCK_VARS (block) = ctx->block_vars;
9644 /* Expand code for an OpenMP ordered directive. */
9646 static void
9647 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9649 tree block;
9650 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9652 push_gimplify_context ();
9654 block = make_node (BLOCK);
9655 bind = gimple_build_bind (NULL, NULL, block);
9656 gsi_replace (gsi_p, bind, true);
9657 gimple_bind_add_stmt (bind, stmt);
9659 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
9661 gimple_bind_add_stmt (bind, x);
9663 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9664 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9665 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9666 gimple_omp_set_body (stmt, NULL);
9668 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
9669 gimple_bind_add_stmt (bind, x);
9671 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9673 pop_gimplify_context (bind);
9675 gimple_bind_append_vars (bind, ctx->block_vars);
9676 BLOCK_VARS (block) = gimple_bind_vars (bind);
9680 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9681 substitution of a couple of function calls. But in the NAMED case,
9682 requires that languages coordinate a symbol name. It is therefore
9683 best put here in common code. */
9685 static GTY((param1_is (tree), param2_is (tree)))
9686 splay_tree critical_name_mutexes;
9688 static void
9689 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9691 tree block;
9692 tree name, lock, unlock;
9693 gimple stmt = gsi_stmt (*gsi_p), bind;
9694 location_t loc = gimple_location (stmt);
9695 gimple_seq tbody;
9697 name = gimple_omp_critical_name (stmt);
9698 if (name)
9700 tree decl;
9701 splay_tree_node n;
9703 if (!critical_name_mutexes)
9704 critical_name_mutexes
9705 = splay_tree_new_ggc (splay_tree_compare_pointers,
9706 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
9707 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
9709 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
9710 if (n == NULL)
9712 char *new_str;
9714 decl = create_tmp_var_raw (ptr_type_node, NULL);
9716 new_str = ACONCAT ((".gomp_critical_user_",
9717 IDENTIFIER_POINTER (name), NULL));
9718 DECL_NAME (decl) = get_identifier (new_str);
9719 TREE_PUBLIC (decl) = 1;
9720 TREE_STATIC (decl) = 1;
9721 DECL_COMMON (decl) = 1;
9722 DECL_ARTIFICIAL (decl) = 1;
9723 DECL_IGNORED_P (decl) = 1;
9724 varpool_finalize_decl (decl);
9726 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
9727 (splay_tree_value) decl);
9729 else
9730 decl = (tree) n->value;
9732 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
9733 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
9735 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
9736 unlock = build_call_expr_loc (loc, unlock, 1,
9737 build_fold_addr_expr_loc (loc, decl));
9739 else
9741 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
9742 lock = build_call_expr_loc (loc, lock, 0);
9744 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
9745 unlock = build_call_expr_loc (loc, unlock, 0);
9748 push_gimplify_context ();
9750 block = make_node (BLOCK);
9751 bind = gimple_build_bind (NULL, NULL, block);
9752 gsi_replace (gsi_p, bind, true);
9753 gimple_bind_add_stmt (bind, stmt);
9755 tbody = gimple_bind_body (bind);
9756 gimplify_and_add (lock, &tbody);
9757 gimple_bind_set_body (bind, tbody);
9759 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9760 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9761 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9762 gimple_omp_set_body (stmt, NULL);
9764 tbody = gimple_bind_body (bind);
9765 gimplify_and_add (unlock, &tbody);
9766 gimple_bind_set_body (bind, tbody);
9768 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9770 pop_gimplify_context (bind);
9771 gimple_bind_append_vars (bind, ctx->block_vars);
9772 BLOCK_VARS (block) = gimple_bind_vars (bind);
9776 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9777 for a lastprivate clause. Given a loop control predicate of (V
9778 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9779 is appended to *DLIST, iterator initialization is appended to
9780 *BODY_P. */
9782 static void
9783 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
9784 gimple_seq *dlist, struct omp_context *ctx)
9786 tree clauses, cond, vinit;
9787 enum tree_code cond_code;
9788 gimple_seq stmts;
9790 cond_code = fd->loop.cond_code;
9791 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
9793 /* When possible, use a strict equality expression. This can let VRP
9794 type optimizations deduce the value and remove a copy. */
9795 if (tree_fits_shwi_p (fd->loop.step))
9797 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
9798 if (step == 1 || step == -1)
9799 cond_code = EQ_EXPR;
9802 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
9804 clauses = gimple_omp_for_clauses (fd->for_stmt);
9805 stmts = NULL;
9806 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
9807 if (!gimple_seq_empty_p (stmts))
9809 gimple_seq_add_seq (&stmts, *dlist);
9810 *dlist = stmts;
9812 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9813 vinit = fd->loop.n1;
9814 if (cond_code == EQ_EXPR
9815 && tree_fits_shwi_p (fd->loop.n2)
9816 && ! integer_zerop (fd->loop.n2))
9817 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
9818 else
9819 vinit = unshare_expr (vinit);
9821 /* Initialize the iterator variable, so that threads that don't execute
9822 any iterations don't execute the lastprivate clauses by accident. */
9823 gimplify_assign (fd->loop.v, vinit, body_p);
9828 /* Lower code for an OpenMP loop directive. */
9830 static void
9831 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9833 tree *rhs_p, block;
9834 struct omp_for_data fd, *fdp = NULL;
9835 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
9836 gimple_seq omp_for_body, body, dlist;
9837 size_t i;
9839 push_gimplify_context ();
9841 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
9843 block = make_node (BLOCK);
9844 new_stmt = gimple_build_bind (NULL, NULL, block);
9845 /* Replace at gsi right away, so that 'stmt' is no member
9846 of a sequence anymore as we're going to add to to a different
9847 one below. */
9848 gsi_replace (gsi_p, new_stmt, true);
9850 /* Move declaration of temporaries in the loop body before we make
9851 it go away. */
9852 omp_for_body = gimple_omp_body (stmt);
9853 if (!gimple_seq_empty_p (omp_for_body)
9854 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9856 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
9857 tree vars = gimple_bind_vars (inner_bind);
9858 gimple_bind_append_vars (new_stmt, vars);
9859 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9860 keep them on the inner_bind and it's block. */
9861 gimple_bind_set_vars (inner_bind, NULL_TREE);
9862 if (gimple_bind_block (inner_bind))
9863 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9866 if (gimple_omp_for_combined_into_p (stmt))
9868 gcc_assert (gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_OACC_LOOP);
9870 extract_omp_for_data (stmt, &fd, NULL);
9871 fdp = &fd;
9873 /* We need two temporaries with fd.loop.v type (istart/iend)
9874 and then (fd.collapse - 1) temporaries with the same
9875 type for count2 ... countN-1 vars if not constant. */
9876 size_t count = 2;
9877 tree type = fd.iter_type;
9878 if (fd.collapse > 1
9879 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9880 count += fd.collapse - 1;
9881 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9882 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9883 tree clauses = *pc;
9884 if (parallel_for)
9885 outerc
9886 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9887 OMP_CLAUSE__LOOPTEMP_);
9888 for (i = 0; i < count; i++)
9890 tree temp;
9891 if (parallel_for)
9893 gcc_assert (outerc);
9894 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9895 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9896 OMP_CLAUSE__LOOPTEMP_);
9898 else
9899 temp = create_tmp_var (type, NULL);
9900 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9901 OMP_CLAUSE_DECL (*pc) = temp;
9902 pc = &OMP_CLAUSE_CHAIN (*pc);
9904 *pc = clauses;
9907 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9908 dlist = NULL;
9909 body = NULL;
9910 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9911 fdp);
9912 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9914 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9916 /* Lower the header expressions. At this point, we can assume that
9917 the header is of the form:
9919 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9921 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9922 using the .omp_data_s mapping, if needed. */
9923 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9925 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9926 if (!is_gimple_min_invariant (*rhs_p))
9927 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9929 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9930 if (!is_gimple_min_invariant (*rhs_p))
9931 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9933 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9934 if (!is_gimple_min_invariant (*rhs_p))
9935 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9938 /* Once lowered, extract the bounds and clauses. */
9939 extract_omp_for_data (stmt, &fd, NULL);
9941 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9943 gimple_seq_add_stmt (&body, stmt);
9944 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9946 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9947 fd.loop.v));
9949 /* After the loop, add exit clauses. */
9950 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9952 if (ctx->cancellable)
9953 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9955 gimple_seq_add_seq (&body, dlist);
9957 body = maybe_catch_exception (body);
9959 /* Region exit marker goes at the end of the loop body. */
9960 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9961 maybe_add_implicit_barrier_cancel (ctx, &body);
9962 pop_gimplify_context (new_stmt);
9964 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9965 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9966 if (BLOCK_VARS (block))
9967 TREE_USED (block) = 1;
9969 gimple_bind_set_body (new_stmt, body);
9970 gimple_omp_set_body (stmt, NULL);
9971 gimple_omp_for_set_pre_body (stmt, NULL);
9974 /* Callback for walk_stmts. Check if the current statement only contains
9975 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9977 static tree
9978 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9979 bool *handled_ops_p,
9980 struct walk_stmt_info *wi)
9982 int *info = (int *) wi->info;
9983 gimple stmt = gsi_stmt (*gsi_p);
9985 *handled_ops_p = true;
9986 switch (gimple_code (stmt))
9988 WALK_SUBSTMTS;
9990 case GIMPLE_OMP_FOR:
9991 case GIMPLE_OMP_SECTIONS:
9992 *info = *info == 0 ? 1 : -1;
9993 break;
9994 default:
9995 *info = -1;
9996 break;
9998 return NULL;
10001 struct omp_taskcopy_context
10003 /* This field must be at the beginning, as we do "inheritance": Some
10004 callback functions for tree-inline.c (e.g., omp_copy_decl)
10005 receive a copy_body_data pointer that is up-casted to an
10006 omp_context pointer. */
10007 copy_body_data cb;
10008 omp_context *ctx;
10011 static tree
10012 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10014 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10016 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10017 return create_tmp_var (TREE_TYPE (var), NULL);
10019 return var;
10022 static tree
10023 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10025 tree name, new_fields = NULL, type, f;
10027 type = lang_hooks.types.make_type (RECORD_TYPE);
10028 name = DECL_NAME (TYPE_NAME (orig_type));
10029 name = build_decl (gimple_location (tcctx->ctx->stmt),
10030 TYPE_DECL, name, type);
10031 TYPE_NAME (type) = name;
10033 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10035 tree new_f = copy_node (f);
10036 DECL_CONTEXT (new_f) = type;
10037 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10038 TREE_CHAIN (new_f) = new_fields;
10039 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10040 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10041 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10042 &tcctx->cb, NULL);
10043 new_fields = new_f;
10044 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
10046 TYPE_FIELDS (type) = nreverse (new_fields);
10047 layout_type (type);
10048 return type;
10051 /* Create task copyfn. */
10053 static void
10054 create_task_copyfn (gimple task_stmt, omp_context *ctx)
10056 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
10058 struct function *child_cfun;
10059 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10060 tree record_type, srecord_type, bind, list;
10061 bool record_needs_remap = false, srecord_needs_remap = false;
10062 splay_tree_node n;
10063 struct omp_taskcopy_context tcctx;
10064 location_t loc = gimple_location (task_stmt);
10066 child_fn = gimple_omp_task_copy_fn (task_stmt);
10067 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10068 gcc_assert (child_cfun->cfg == NULL);
10069 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10071 /* Reset DECL_CONTEXT on function arguments. */
10072 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10073 DECL_CONTEXT (t) = child_fn;
10075 /* Populate the function. */
10076 push_gimplify_context ();
10077 push_cfun (child_cfun);
10079 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10080 TREE_SIDE_EFFECTS (bind) = 1;
10081 list = NULL;
10082 DECL_SAVED_TREE (child_fn) = bind;
10083 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10085 /* Remap src and dst argument types if needed. */
10086 record_type = ctx->record_type;
10087 srecord_type = ctx->srecord_type;
10088 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10089 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10091 record_needs_remap = true;
10092 break;
10094 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10095 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10097 srecord_needs_remap = true;
10098 break;
10101 if (record_needs_remap || srecord_needs_remap)
10103 memset (&tcctx, '\0', sizeof (tcctx));
10104 tcctx.cb.src_fn = ctx->cb.src_fn;
10105 tcctx.cb.dst_fn = child_fn;
10106 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
10107 gcc_checking_assert (tcctx.cb.src_node);
10108 tcctx.cb.dst_node = tcctx.cb.src_node;
10109 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10110 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10111 tcctx.cb.eh_lp_nr = 0;
10112 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10113 tcctx.cb.decl_map = pointer_map_create ();
10114 tcctx.ctx = ctx;
10116 if (record_needs_remap)
10117 record_type = task_copyfn_remap_type (&tcctx, record_type);
10118 if (srecord_needs_remap)
10119 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10121 else
10122 tcctx.cb.decl_map = NULL;
10124 arg = DECL_ARGUMENTS (child_fn);
10125 TREE_TYPE (arg) = build_pointer_type (record_type);
10126 sarg = DECL_CHAIN (arg);
10127 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10129 /* First pass: initialize temporaries used in record_type and srecord_type
10130 sizes and field offsets. */
10131 if (tcctx.cb.decl_map)
10132 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10133 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10135 tree *p;
10137 decl = OMP_CLAUSE_DECL (c);
10138 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
10139 if (p == NULL)
10140 continue;
10141 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10142 sf = (tree) n->value;
10143 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
10144 src = build_simple_mem_ref_loc (loc, sarg);
10145 src = omp_build_component_ref (src, sf);
10146 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10147 append_to_statement_list (t, &list);
10150 /* Second pass: copy shared var pointers and copy construct non-VLA
10151 firstprivate vars. */
10152 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10153 switch (OMP_CLAUSE_CODE (c))
10155 case OMP_CLAUSE_SHARED:
10156 decl = OMP_CLAUSE_DECL (c);
10157 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10158 if (n == NULL)
10159 break;
10160 f = (tree) n->value;
10161 if (tcctx.cb.decl_map)
10162 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
10163 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10164 sf = (tree) n->value;
10165 if (tcctx.cb.decl_map)
10166 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
10167 src = build_simple_mem_ref_loc (loc, sarg);
10168 src = omp_build_component_ref (src, sf);
10169 dst = build_simple_mem_ref_loc (loc, arg);
10170 dst = omp_build_component_ref (dst, f);
10171 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10172 append_to_statement_list (t, &list);
10173 break;
10174 case OMP_CLAUSE_FIRSTPRIVATE:
10175 decl = OMP_CLAUSE_DECL (c);
10176 if (is_variable_sized (decl))
10177 break;
10178 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10179 if (n == NULL)
10180 break;
10181 f = (tree) n->value;
10182 if (tcctx.cb.decl_map)
10183 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
10184 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10185 if (n != NULL)
10187 sf = (tree) n->value;
10188 if (tcctx.cb.decl_map)
10189 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
10190 src = build_simple_mem_ref_loc (loc, sarg);
10191 src = omp_build_component_ref (src, sf);
10192 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
10193 src = build_simple_mem_ref_loc (loc, src);
10195 else
10196 src = decl;
10197 dst = build_simple_mem_ref_loc (loc, arg);
10198 dst = omp_build_component_ref (dst, f);
10199 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10200 append_to_statement_list (t, &list);
10201 break;
10202 case OMP_CLAUSE_PRIVATE:
10203 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10204 break;
10205 decl = OMP_CLAUSE_DECL (c);
10206 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10207 f = (tree) n->value;
10208 if (tcctx.cb.decl_map)
10209 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
10210 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10211 if (n != NULL)
10213 sf = (tree) n->value;
10214 if (tcctx.cb.decl_map)
10215 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
10216 src = build_simple_mem_ref_loc (loc, sarg);
10217 src = omp_build_component_ref (src, sf);
10218 if (use_pointer_for_field (decl, NULL))
10219 src = build_simple_mem_ref_loc (loc, src);
10221 else
10222 src = decl;
10223 dst = build_simple_mem_ref_loc (loc, arg);
10224 dst = omp_build_component_ref (dst, f);
10225 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10226 append_to_statement_list (t, &list);
10227 break;
10228 default:
10229 break;
10232 /* Last pass: handle VLA firstprivates. */
10233 if (tcctx.cb.decl_map)
10234 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10235 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10237 tree ind, ptr, df;
10239 decl = OMP_CLAUSE_DECL (c);
10240 if (!is_variable_sized (decl))
10241 continue;
10242 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10243 if (n == NULL)
10244 continue;
10245 f = (tree) n->value;
10246 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
10247 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10248 ind = DECL_VALUE_EXPR (decl);
10249 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10250 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10251 n = splay_tree_lookup (ctx->sfield_map,
10252 (splay_tree_key) TREE_OPERAND (ind, 0));
10253 sf = (tree) n->value;
10254 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
10255 src = build_simple_mem_ref_loc (loc, sarg);
10256 src = omp_build_component_ref (src, sf);
10257 src = build_simple_mem_ref_loc (loc, src);
10258 dst = build_simple_mem_ref_loc (loc, arg);
10259 dst = omp_build_component_ref (dst, f);
10260 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10261 append_to_statement_list (t, &list);
10262 n = splay_tree_lookup (ctx->field_map,
10263 (splay_tree_key) TREE_OPERAND (ind, 0));
10264 df = (tree) n->value;
10265 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
10266 ptr = build_simple_mem_ref_loc (loc, arg);
10267 ptr = omp_build_component_ref (ptr, df);
10268 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
10269 build_fold_addr_expr_loc (loc, dst));
10270 append_to_statement_list (t, &list);
10273 t = build1 (RETURN_EXPR, void_type_node, NULL);
10274 append_to_statement_list (t, &list);
10276 if (tcctx.cb.decl_map)
10277 pointer_map_destroy (tcctx.cb.decl_map);
10278 pop_gimplify_context (NULL);
10279 BIND_EXPR_BODY (bind) = list;
10280 pop_cfun ();
10283 static void
10284 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
10286 tree c, clauses;
10287 gimple g;
10288 size_t n_in = 0, n_out = 0, idx = 2, i;
10290 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
10291 OMP_CLAUSE_DEPEND);
10292 gcc_assert (clauses);
10293 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10294 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10295 switch (OMP_CLAUSE_DEPEND_KIND (c))
10297 case OMP_CLAUSE_DEPEND_IN:
10298 n_in++;
10299 break;
10300 case OMP_CLAUSE_DEPEND_OUT:
10301 case OMP_CLAUSE_DEPEND_INOUT:
10302 n_out++;
10303 break;
10304 default:
10305 gcc_unreachable ();
10307 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
10308 tree array = create_tmp_var (type, NULL);
10309 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
10310 NULL_TREE);
10311 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
10312 gimple_seq_add_stmt (iseq, g);
10313 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
10314 NULL_TREE);
10315 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
10316 gimple_seq_add_stmt (iseq, g);
10317 for (i = 0; i < 2; i++)
10319 if ((i ? n_in : n_out) == 0)
10320 continue;
10321 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10322 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
10323 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
10325 tree t = OMP_CLAUSE_DECL (c);
10326 t = fold_convert (ptr_type_node, t);
10327 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
10328 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
10329 NULL_TREE, NULL_TREE);
10330 g = gimple_build_assign (r, t);
10331 gimple_seq_add_stmt (iseq, g);
10334 tree *p = gimple_omp_task_clauses_ptr (stmt);
10335 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
10336 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
10337 OMP_CLAUSE_CHAIN (c) = *p;
10338 *p = c;
10339 tree clobber = build_constructor (type, NULL);
10340 TREE_THIS_VOLATILE (clobber) = 1;
10341 g = gimple_build_assign (array, clobber);
10342 gimple_seq_add_stmt (oseq, g);
10345 /* Lower the OpenMP parallel or task directive in the current statement
10346 in GSI_P. CTX holds context information for the directive. */
10348 static void
10349 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10351 tree clauses;
10352 tree child_fn, t;
10353 gimple stmt = gsi_stmt (*gsi_p);
10354 gimple par_bind, bind, dep_bind = NULL;
10355 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
10356 location_t loc = gimple_location (stmt);
10358 clauses = gimple_omp_taskreg_clauses (stmt);
10359 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
10360 par_body = gimple_bind_body (par_bind);
10361 child_fn = ctx->cb.dst_fn;
10362 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
10363 && !gimple_omp_parallel_combined_p (stmt))
10365 struct walk_stmt_info wi;
10366 int ws_num = 0;
10368 memset (&wi, 0, sizeof (wi));
10369 wi.info = &ws_num;
10370 wi.val_only = true;
10371 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
10372 if (ws_num == 1)
10373 gimple_omp_parallel_set_combined_p (stmt, true);
10375 gimple_seq dep_ilist = NULL;
10376 gimple_seq dep_olist = NULL;
10377 if (gimple_code (stmt) == GIMPLE_OMP_TASK
10378 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
10380 push_gimplify_context ();
10381 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
10382 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
10385 if (ctx->srecord_type)
10386 create_task_copyfn (stmt, ctx);
10388 push_gimplify_context ();
10390 par_olist = NULL;
10391 par_ilist = NULL;
10392 par_rlist = NULL;
10393 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
10394 lower_omp (&par_body, ctx);
10395 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
10396 lower_reduction_clauses (clauses, &par_rlist, ctx);
10398 /* Declare all the variables created by mapping and the variables
10399 declared in the scope of the parallel body. */
10400 record_vars_into (ctx->block_vars, child_fn);
10401 record_vars_into (gimple_bind_vars (par_bind), child_fn);
10403 if (ctx->record_type)
10405 ctx->sender_decl
10406 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
10407 : ctx->record_type, ".omp_data_o");
10408 DECL_NAMELESS (ctx->sender_decl) = 1;
10409 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10410 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
10413 olist = NULL;
10414 ilist = NULL;
10415 lower_send_clauses (clauses, &ilist, &olist, ctx);
10416 lower_send_shared_vars (&ilist, &olist, ctx);
10418 if (ctx->record_type)
10420 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
10421 TREE_THIS_VOLATILE (clobber) = 1;
10422 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10423 clobber));
10426 /* Once all the expansions are done, sequence all the different
10427 fragments inside gimple_omp_body. */
10429 new_body = NULL;
10431 if (ctx->record_type)
10433 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10434 /* fixup_child_record_type might have changed receiver_decl's type. */
10435 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10436 gimple_seq_add_stmt (&new_body,
10437 gimple_build_assign (ctx->receiver_decl, t));
10440 gimple_seq_add_seq (&new_body, par_ilist);
10441 gimple_seq_add_seq (&new_body, par_body);
10442 gimple_seq_add_seq (&new_body, par_rlist);
10443 if (ctx->cancellable)
10444 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10445 gimple_seq_add_seq (&new_body, par_olist);
10446 new_body = maybe_catch_exception (new_body);
10447 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10448 gimple_omp_set_body (stmt, new_body);
10450 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
10451 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
10452 gimple_bind_add_seq (bind, ilist);
10453 gimple_bind_add_stmt (bind, stmt);
10454 gimple_bind_add_seq (bind, olist);
10456 pop_gimplify_context (NULL);
10458 if (dep_bind)
10460 gimple_bind_add_seq (dep_bind, dep_ilist);
10461 gimple_bind_add_stmt (dep_bind, bind);
10462 gimple_bind_add_seq (dep_bind, dep_olist);
10463 pop_gimplify_context (dep_bind);
10467 /* Lower the GIMPLE_OMP_TARGET in the current statement
10468 in GSI_P. CTX holds context information for the directive. */
10470 static void
10471 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10473 tree clauses;
10474 tree child_fn, t, c;
10475 gimple stmt = gsi_stmt (*gsi_p);
10476 gimple tgt_bind = NULL, bind;
10477 gimple_seq tgt_body = NULL, olist, ilist, new_body;
10478 location_t loc = gimple_location (stmt);
10479 int kind = gimple_omp_target_kind (stmt);
10480 unsigned int map_cnt = 0;
10482 clauses = gimple_omp_target_clauses (stmt);
10483 if (kind == GF_OMP_TARGET_KIND_REGION)
10485 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
10486 tgt_body = gimple_bind_body (tgt_bind);
10488 else if (kind == GF_OMP_TARGET_KIND_DATA
10489 || kind == GF_OMP_TARGET_KIND_OACC_DATA)
10490 tgt_body = gimple_omp_body (stmt);
10491 child_fn = ctx->cb.dst_fn;
10493 push_gimplify_context ();
10495 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10496 switch (OMP_CLAUSE_CODE (c))
10498 tree var, x;
10500 default:
10501 break;
10502 case OMP_CLAUSE_MAP:
10503 #ifdef ENABLE_CHECKING
10504 /* First check what we're prepared to handle in the following. */
10505 switch (OMP_CLAUSE_MAP_KIND (c))
10507 case OMP_CLAUSE_MAP_ALLOC:
10508 case OMP_CLAUSE_MAP_TO:
10509 case OMP_CLAUSE_MAP_FROM:
10510 case OMP_CLAUSE_MAP_TOFROM:
10511 case OMP_CLAUSE_MAP_POINTER:
10512 break;
10513 case OMP_CLAUSE_MAP_FORCE_ALLOC:
10514 case OMP_CLAUSE_MAP_FORCE_TO:
10515 case OMP_CLAUSE_MAP_FORCE_FROM:
10516 case OMP_CLAUSE_MAP_FORCE_TOFROM:
10517 case OMP_CLAUSE_MAP_FORCE_PRESENT:
10518 case OMP_CLAUSE_MAP_FORCE_DEALLOC:
10519 case OMP_CLAUSE_MAP_FORCE_DEVICEPTR:
10520 gcc_assert (kind == GF_OMP_TARGET_KIND_OACC_DATA);
10521 break;
10522 default:
10523 gcc_unreachable ();
10525 #endif
10526 /* FALLTHRU */
10528 case OMP_CLAUSE_TO:
10529 case OMP_CLAUSE_FROM:
10530 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
10531 gcc_assert (kind != GF_OMP_TARGET_KIND_OACC_DATA);
10532 var = OMP_CLAUSE_DECL (c);
10533 if (!DECL_P (var))
10535 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10536 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10537 map_cnt++;
10538 continue;
10541 if (DECL_SIZE (var)
10542 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
10544 tree var2 = DECL_VALUE_EXPR (var);
10545 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
10546 var2 = TREE_OPERAND (var2, 0);
10547 gcc_assert (DECL_P (var2));
10548 var = var2;
10551 if (!maybe_lookup_field (var, ctx))
10552 continue;
10554 if (kind == GF_OMP_TARGET_KIND_REGION)
10556 x = build_receiver_ref (var, true, ctx);
10557 tree new_var = lookup_decl (var, ctx);
10558 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10559 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10560 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10561 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
10562 x = build_simple_mem_ref (x);
10563 SET_DECL_VALUE_EXPR (new_var, x);
10564 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
10566 map_cnt++;
10569 if (kind == GF_OMP_TARGET_KIND_REGION)
10571 target_nesting_level++;
10572 lower_omp (&tgt_body, ctx);
10573 target_nesting_level--;
10575 else if (kind == GF_OMP_TARGET_KIND_DATA
10576 || kind == GF_OMP_TARGET_KIND_OACC_DATA)
10577 lower_omp (&tgt_body, ctx);
10579 if (kind == GF_OMP_TARGET_KIND_REGION)
10581 /* Declare all the variables created by mapping and the variables
10582 declared in the scope of the target body. */
10583 record_vars_into (ctx->block_vars, child_fn);
10584 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
10587 olist = NULL;
10588 ilist = NULL;
10589 if (ctx->record_type)
10591 ctx->sender_decl
10592 = create_tmp_var (ctx->record_type, ".omp_data_arr");
10593 DECL_NAMELESS (ctx->sender_decl) = 1;
10594 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10595 t = make_tree_vec (3);
10596 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
10597 TREE_VEC_ELT (t, 1)
10598 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
10599 ".omp_data_sizes");
10600 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
10601 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
10602 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
10603 tree tkind_type;
10604 int talign_shift;
10605 switch (kind)
10607 case GF_OMP_TARGET_KIND_REGION:
10608 case GF_OMP_TARGET_KIND_DATA:
10609 case GF_OMP_TARGET_KIND_UPDATE:
10610 tkind_type = unsigned_char_type_node;
10611 talign_shift = 3;
10612 break;
10613 case GF_OMP_TARGET_KIND_OACC_DATA:
10614 tkind_type = short_unsigned_type_node;
10615 talign_shift = 8;
10616 break;
10617 default:
10618 gcc_unreachable ();
10620 TREE_VEC_ELT (t, 2)
10621 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
10622 ".omp_data_kinds");
10623 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
10624 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
10625 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
10626 gimple_omp_target_set_data_arg (stmt, t);
10628 vec<constructor_elt, va_gc> *vsize;
10629 vec<constructor_elt, va_gc> *vkind;
10630 vec_alloc (vsize, map_cnt);
10631 vec_alloc (vkind, map_cnt);
10632 unsigned int map_idx = 0;
10634 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10635 switch (OMP_CLAUSE_CODE (c))
10637 tree ovar, nc;
10639 default:
10640 break;
10641 case OMP_CLAUSE_MAP:
10642 case OMP_CLAUSE_TO:
10643 case OMP_CLAUSE_FROM:
10644 nc = c;
10645 ovar = OMP_CLAUSE_DECL (c);
10646 if (!DECL_P (ovar))
10648 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10649 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10651 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
10652 == get_base_address (ovar));
10653 nc = OMP_CLAUSE_CHAIN (c);
10654 ovar = OMP_CLAUSE_DECL (nc);
10656 else
10658 tree x = build_sender_ref (ovar, ctx);
10659 tree v
10660 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
10661 gimplify_assign (x, v, &ilist);
10662 nc = NULL_TREE;
10665 else
10667 if (DECL_SIZE (ovar)
10668 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
10670 tree ovar2 = DECL_VALUE_EXPR (ovar);
10671 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
10672 ovar2 = TREE_OPERAND (ovar2, 0);
10673 gcc_assert (DECL_P (ovar2));
10674 ovar = ovar2;
10676 if (!maybe_lookup_field (ovar, ctx))
10677 continue;
10680 if (nc)
10682 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
10683 tree x = build_sender_ref (ovar, ctx);
10684 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10685 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10686 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10687 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
10689 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10690 tree avar
10691 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
10692 mark_addressable (avar);
10693 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
10694 avar = build_fold_addr_expr (avar);
10695 gimplify_assign (x, avar, &ilist);
10697 else if (is_gimple_reg (var))
10699 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10700 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
10701 mark_addressable (avar);
10702 enum omp_clause_map_kind map_kind
10703 = OMP_CLAUSE_MAP_KIND (c);
10704 if ((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
10705 && (map_kind & OMP_CLAUSE_MAP_TO))
10706 || map_kind == OMP_CLAUSE_MAP_POINTER)
10707 gimplify_assign (avar, var, &ilist);
10708 avar = build_fold_addr_expr (avar);
10709 gimplify_assign (x, avar, &ilist);
10710 if ((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
10711 && (map_kind & OMP_CLAUSE_MAP_FROM))
10712 && !TYPE_READONLY (TREE_TYPE (var)))
10714 x = build_sender_ref (ovar, ctx);
10715 x = build_simple_mem_ref (x);
10716 gimplify_assign (var, x, &olist);
10719 else
10721 var = build_fold_addr_expr (var);
10722 gimplify_assign (x, var, &ilist);
10725 tree s = OMP_CLAUSE_SIZE (c);
10726 if (s == NULL_TREE)
10727 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
10728 s = fold_convert (size_type_node, s);
10729 tree purpose = size_int (map_idx++);
10730 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
10731 if (TREE_CODE (s) != INTEGER_CST)
10732 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
10734 unsigned HOST_WIDE_INT tkind;
10735 switch (OMP_CLAUSE_CODE (c))
10737 case OMP_CLAUSE_MAP:
10738 tkind = OMP_CLAUSE_MAP_KIND (c);
10739 break;
10740 case OMP_CLAUSE_TO:
10741 tkind = OMP_CLAUSE_MAP_TO;
10742 break;
10743 case OMP_CLAUSE_FROM:
10744 tkind = OMP_CLAUSE_MAP_FROM;
10745 break;
10746 default:
10747 gcc_unreachable ();
10749 gcc_assert (tkind < (HOST_WIDE_INT_C (1U) << talign_shift));
10750 unsigned HOST_WIDE_INT talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
10751 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
10752 talign = DECL_ALIGN_UNIT (ovar);
10753 talign = ceil_log2 (talign);
10754 tkind |= talign << talign_shift;
10755 gcc_assert (tkind <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
10756 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
10757 build_int_cstu (tkind_type, tkind));
10758 if (nc && nc != c)
10759 c = nc;
10762 gcc_assert (map_idx == map_cnt);
10764 DECL_INITIAL (TREE_VEC_ELT (t, 1))
10765 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
10766 DECL_INITIAL (TREE_VEC_ELT (t, 2))
10767 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
10768 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
10770 gimple_seq initlist = NULL;
10771 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
10772 TREE_VEC_ELT (t, 1)),
10773 &initlist, true, NULL_TREE);
10774 gimple_seq_add_seq (&ilist, initlist);
10776 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
10777 NULL);
10778 TREE_THIS_VOLATILE (clobber) = 1;
10779 gimple_seq_add_stmt (&olist,
10780 gimple_build_assign (TREE_VEC_ELT (t, 1),
10781 clobber));
10784 tree clobber = build_constructor (ctx->record_type, NULL);
10785 TREE_THIS_VOLATILE (clobber) = 1;
10786 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10787 clobber));
10790 /* Once all the expansions are done, sequence all the different
10791 fragments inside gimple_omp_body. */
10793 new_body = NULL;
10795 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
10797 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10798 /* fixup_child_record_type might have changed receiver_decl's type. */
10799 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10800 gimple_seq_add_stmt (&new_body,
10801 gimple_build_assign (ctx->receiver_decl, t));
10804 if (kind == GF_OMP_TARGET_KIND_REGION)
10806 gimple_seq_add_seq (&new_body, tgt_body);
10807 new_body = maybe_catch_exception (new_body);
10809 else if (kind == GF_OMP_TARGET_KIND_DATA
10810 || kind == GF_OMP_TARGET_KIND_OACC_DATA)
10811 new_body = tgt_body;
10812 if (kind != GF_OMP_TARGET_KIND_UPDATE)
10814 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10815 gimple_omp_set_body (stmt, new_body);
10818 bind = gimple_build_bind (NULL, NULL,
10819 tgt_bind ? gimple_bind_block (tgt_bind)
10820 : NULL_TREE);
10821 gsi_replace (gsi_p, bind, true);
10822 gimple_bind_add_seq (bind, ilist);
10823 gimple_bind_add_stmt (bind, stmt);
10824 gimple_bind_add_seq (bind, olist);
10826 pop_gimplify_context (NULL);
10829 /* Expand code for an OpenMP teams directive. */
10831 static void
10832 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10834 gimple teams_stmt = gsi_stmt (*gsi_p);
10835 push_gimplify_context ();
10837 tree block = make_node (BLOCK);
10838 gimple bind = gimple_build_bind (NULL, NULL, block);
10839 gsi_replace (gsi_p, bind, true);
10840 gimple_seq bind_body = NULL;
10841 gimple_seq dlist = NULL;
10842 gimple_seq olist = NULL;
10844 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10845 OMP_CLAUSE_NUM_TEAMS);
10846 if (num_teams == NULL_TREE)
10847 num_teams = build_int_cst (unsigned_type_node, 0);
10848 else
10850 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
10851 num_teams = fold_convert (unsigned_type_node, num_teams);
10852 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
10854 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10855 OMP_CLAUSE_THREAD_LIMIT);
10856 if (thread_limit == NULL_TREE)
10857 thread_limit = build_int_cst (unsigned_type_node, 0);
10858 else
10860 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10861 thread_limit = fold_convert (unsigned_type_node, thread_limit);
10862 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
10863 fb_rvalue);
10866 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
10867 &bind_body, &dlist, ctx, NULL);
10868 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
10869 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
10870 gimple_seq_add_stmt (&bind_body, teams_stmt);
10872 location_t loc = gimple_location (teams_stmt);
10873 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
10874 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10875 gimple_set_location (call, loc);
10876 gimple_seq_add_stmt (&bind_body, call);
10878 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10879 gimple_omp_set_body (teams_stmt, NULL);
10880 gimple_seq_add_seq (&bind_body, olist);
10881 gimple_seq_add_seq (&bind_body, dlist);
10882 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10883 gimple_bind_set_body (bind, bind_body);
10885 pop_gimplify_context (bind);
10887 gimple_bind_append_vars (bind, ctx->block_vars);
10888 BLOCK_VARS (block) = ctx->block_vars;
10889 if (BLOCK_VARS (block))
10890 TREE_USED (block) = 1;
10894 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10895 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10896 of OpenMP context, but with task_shared_vars set. */
10898 static tree
10899 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10900 void *data)
10902 tree t = *tp;
10904 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10905 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
10906 return t;
10908 if (task_shared_vars
10909 && DECL_P (t)
10910 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10911 return t;
10913 /* If a global variable has been privatized, TREE_CONSTANT on
10914 ADDR_EXPR might be wrong. */
10915 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10916 recompute_tree_invariant_for_addr_expr (t);
10918 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10919 return NULL_TREE;
10922 static void
10923 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10925 gimple stmt = gsi_stmt (*gsi_p);
10926 struct walk_stmt_info wi;
10928 if (gimple_has_location (stmt))
10929 input_location = gimple_location (stmt);
10931 if (task_shared_vars)
10932 memset (&wi, '\0', sizeof (wi));
10934 /* If we have issued syntax errors, avoid doing any heavy lifting.
10935 Just replace the OpenMP directives with a NOP to avoid
10936 confusing RTL expansion. */
10937 if (seen_error () && is_gimple_omp (stmt))
10939 gsi_replace (gsi_p, gimple_build_nop (), true);
10940 return;
10943 switch (gimple_code (stmt))
10945 case GIMPLE_COND:
10946 if ((ctx || task_shared_vars)
10947 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
10948 ctx ? NULL : &wi, NULL)
10949 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
10950 ctx ? NULL : &wi, NULL)))
10951 gimple_regimplify_operands (stmt, gsi_p);
10952 break;
10953 case GIMPLE_CATCH:
10954 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
10955 break;
10956 case GIMPLE_EH_FILTER:
10957 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10958 break;
10959 case GIMPLE_TRY:
10960 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10961 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10962 break;
10963 case GIMPLE_TRANSACTION:
10964 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
10965 break;
10966 case GIMPLE_BIND:
10967 lower_omp (gimple_bind_body_ptr (stmt), ctx);
10968 break;
10969 case GIMPLE_OACC_KERNELS:
10970 case GIMPLE_OACC_PARALLEL:
10971 ctx = maybe_lookup_ctx (stmt);
10972 gcc_assert (ctx);
10973 gcc_assert (!ctx->cancellable);
10974 lower_oacc_offload (gsi_p, ctx);
10975 break;
10976 case GIMPLE_OMP_PARALLEL:
10977 case GIMPLE_OMP_TASK:
10978 ctx = maybe_lookup_ctx (stmt);
10979 gcc_assert (ctx);
10980 if (ctx->cancellable)
10981 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10982 lower_omp_taskreg (gsi_p, ctx);
10983 break;
10984 case GIMPLE_OMP_FOR:
10985 ctx = maybe_lookup_ctx (stmt);
10986 gcc_assert (ctx);
10987 if (ctx->cancellable)
10988 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10989 lower_omp_for (gsi_p, ctx);
10990 break;
10991 case GIMPLE_OMP_SECTIONS:
10992 ctx = maybe_lookup_ctx (stmt);
10993 gcc_assert (ctx);
10994 if (ctx->cancellable)
10995 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10996 lower_omp_sections (gsi_p, ctx);
10997 break;
10998 case GIMPLE_OMP_SINGLE:
10999 ctx = maybe_lookup_ctx (stmt);
11000 gcc_assert (ctx);
11001 lower_omp_single (gsi_p, ctx);
11002 break;
11003 case GIMPLE_OMP_MASTER:
11004 ctx = maybe_lookup_ctx (stmt);
11005 gcc_assert (ctx);
11006 lower_omp_master (gsi_p, ctx);
11007 break;
11008 case GIMPLE_OMP_TASKGROUP:
11009 ctx = maybe_lookup_ctx (stmt);
11010 gcc_assert (ctx);
11011 lower_omp_taskgroup (gsi_p, ctx);
11012 break;
11013 case GIMPLE_OMP_ORDERED:
11014 ctx = maybe_lookup_ctx (stmt);
11015 gcc_assert (ctx);
11016 lower_omp_ordered (gsi_p, ctx);
11017 break;
11018 case GIMPLE_OMP_CRITICAL:
11019 ctx = maybe_lookup_ctx (stmt);
11020 gcc_assert (ctx);
11021 lower_omp_critical (gsi_p, ctx);
11022 break;
11023 case GIMPLE_OMP_ATOMIC_LOAD:
11024 if ((ctx || task_shared_vars)
11025 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
11026 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11027 gimple_regimplify_operands (stmt, gsi_p);
11028 break;
11029 case GIMPLE_OMP_TARGET:
11030 ctx = maybe_lookup_ctx (stmt);
11031 gcc_assert (ctx);
11032 if (gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_DATA)
11033 gcc_assert (!ctx->cancellable);
11034 lower_omp_target (gsi_p, ctx);
11035 break;
11036 case GIMPLE_OMP_TEAMS:
11037 ctx = maybe_lookup_ctx (stmt);
11038 gcc_assert (ctx);
11039 lower_omp_teams (gsi_p, ctx);
11040 break;
11041 case GIMPLE_CALL:
11042 tree fndecl;
11043 fndecl = gimple_call_fndecl (stmt);
11044 if (fndecl
11045 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11046 switch (DECL_FUNCTION_CODE (fndecl))
11048 case BUILT_IN_GOMP_BARRIER:
11049 if (ctx == NULL)
11050 break;
11051 /* FALLTHRU */
11052 case BUILT_IN_GOMP_CANCEL:
11053 case BUILT_IN_GOMP_CANCELLATION_POINT:
11054 omp_context *cctx;
11055 cctx = ctx;
11056 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11057 cctx = cctx->outer;
11058 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
11059 if (!cctx->cancellable)
11061 if (DECL_FUNCTION_CODE (fndecl)
11062 == BUILT_IN_GOMP_CANCELLATION_POINT)
11064 stmt = gimple_build_nop ();
11065 gsi_replace (gsi_p, stmt, false);
11067 break;
11069 tree lhs;
11070 lhs = create_tmp_var (boolean_type_node, NULL);
11071 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11073 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11074 gimple_call_set_fndecl (stmt, fndecl);
11075 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
11077 gimple_call_set_lhs (stmt, lhs);
11078 tree fallthru_label;
11079 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11080 gimple g;
11081 g = gimple_build_label (fallthru_label);
11082 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11083 g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
11084 cctx->cancel_label, fallthru_label);
11085 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11086 break;
11087 default:
11088 break;
11090 /* FALLTHRU */
11091 default:
11092 if ((ctx || task_shared_vars)
11093 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11094 ctx ? NULL : &wi))
11095 gimple_regimplify_operands (stmt, gsi_p);
11096 break;
11100 static void
11101 lower_omp (gimple_seq *body, omp_context *ctx)
11103 location_t saved_location = input_location;
11104 gimple_stmt_iterator gsi;
11105 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11106 lower_omp_1 (&gsi, ctx);
11107 /* During gimplification, we haven't folded statments inside offloading
11108 regions (gimplify.c:maybe_fold_stmt); do that now. */
11109 if (target_nesting_level)
11110 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11111 fold_stmt (&gsi);
11112 input_location = saved_location;
11115 /* Main entry point. */
11117 static unsigned int
11118 execute_lower_omp (void)
11120 gimple_seq body;
11122 /* This pass always runs, to provide PROP_gimple_lomp.
11123 But often, there is nothing to do. */
11124 if (flag_openacc == 0 && flag_openmp == 0 && flag_openmp_simd == 0
11125 && flag_cilkplus == 0)
11126 return 0;
11128 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11129 delete_omp_context);
11131 body = gimple_body (current_function_decl);
11132 scan_omp (&body, NULL);
11133 gcc_assert (taskreg_nesting_level == 0);
11135 if (all_contexts->root)
11137 if (task_shared_vars)
11138 push_gimplify_context ();
11139 lower_omp (&body, NULL);
11140 if (task_shared_vars)
11141 pop_gimplify_context (NULL);
11144 if (all_contexts)
11146 splay_tree_delete (all_contexts);
11147 all_contexts = NULL;
11149 BITMAP_FREE (task_shared_vars);
11150 return 0;
11153 namespace {
11155 const pass_data pass_data_lower_omp =
11157 GIMPLE_PASS, /* type */
11158 "omplower", /* name */
11159 OPTGROUP_NONE, /* optinfo_flags */
11160 false, /* has_gate */
11161 true, /* has_execute */
11162 TV_NONE, /* tv_id */
11163 PROP_gimple_any, /* properties_required */
11164 PROP_gimple_lomp, /* properties_provided */
11165 0, /* properties_destroyed */
11166 0, /* todo_flags_start */
11167 0, /* todo_flags_finish */
11170 class pass_lower_omp : public gimple_opt_pass
11172 public:
11173 pass_lower_omp (gcc::context *ctxt)
11174 : gimple_opt_pass (pass_data_lower_omp, ctxt)
11177 /* opt_pass methods: */
11178 unsigned int execute () { return execute_lower_omp (); }
11180 }; // class pass_lower_omp
11182 } // anon namespace
11184 gimple_opt_pass *
11185 make_pass_lower_omp (gcc::context *ctxt)
11187 return new pass_lower_omp (ctxt);
11190 /* The following is a utility to diagnose structured block violations.
11191 It is not part of the "omplower" pass, as that's invoked too late. It
11192 should be invoked by the respective front ends after gimplification. */
11194 static splay_tree all_labels;
11196 /* Check for mismatched contexts and generate an error if needed. Return
11197 true if an error is detected. */
11199 static bool
11200 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
11201 gimple branch_ctx, gimple label_ctx)
11203 gcc_assert (!branch_ctx || is_gimple_omp (branch_ctx));
11204 gcc_assert (!label_ctx || is_gimple_omp (label_ctx));
11206 if (label_ctx == branch_ctx)
11207 return false;
11209 const char* kind = NULL;
11211 if (flag_cilkplus)
11213 if ((branch_ctx
11214 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
11215 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
11216 || (label_ctx
11217 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
11218 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
11219 kind = "Cilk Plus";
11221 if (flag_openacc)
11223 if ((branch_ctx && is_gimple_omp_oacc_specifically (branch_ctx))
11224 || (label_ctx && is_gimple_omp_oacc_specifically (label_ctx)))
11226 gcc_assert (kind == NULL);
11227 kind = "OpenACC";
11230 if (kind == NULL)
11232 gcc_assert (flag_openmp);
11233 kind = "OpenMP";
11237 Previously we kept track of the label's entire context in diagnose_sb_[12]
11238 so we could traverse it and issue a correct "exit" or "enter" error
11239 message upon a structured block violation.
11241 We built the context by building a list with tree_cons'ing, but there is
11242 no easy counterpart in gimple tuples. It seems like far too much work
11243 for issuing exit/enter error messages. If someone really misses the
11244 distinct error message... patches welcome.
11247 #if 0
11248 /* Try to avoid confusing the user by producing and error message
11249 with correct "exit" or "enter" verbiage. We prefer "exit"
11250 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
11251 if (branch_ctx == NULL)
11252 exit_p = false;
11253 else
11255 while (label_ctx)
11257 if (TREE_VALUE (label_ctx) == branch_ctx)
11259 exit_p = false;
11260 break;
11262 label_ctx = TREE_CHAIN (label_ctx);
11266 if (exit_p)
11267 error ("invalid exit from %s structured block", kind);
11268 else
11269 error ("invalid entry to %s structured block", kind);
11270 #endif
11272 /* If it's obvious we have an invalid entry, be specific about the error. */
11273 if (branch_ctx == NULL)
11274 error ("invalid entry to %s structured block", kind);
11275 else
11277 /* Otherwise, be vague and lazy, but efficient. */
11278 error ("invalid branch to/from %s structured block", kind);
11281 gsi_replace (gsi_p, gimple_build_nop (), false);
11282 return true;
11285 /* Pass 1: Create a minimal tree of structured blocks, and record
11286 where each label is found. */
11288 static tree
11289 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
11290 struct walk_stmt_info *wi)
11292 gimple context = (gimple) wi->info;
11293 gimple inner_context;
11294 gimple stmt = gsi_stmt (*gsi_p);
11296 *handled_ops_p = true;
11298 switch (gimple_code (stmt))
11300 WALK_SUBSTMTS;
11302 case GIMPLE_OACC_KERNELS:
11303 case GIMPLE_OACC_PARALLEL:
11304 case GIMPLE_OMP_PARALLEL:
11305 case GIMPLE_OMP_TASK:
11306 case GIMPLE_OMP_SECTIONS:
11307 case GIMPLE_OMP_SINGLE:
11308 case GIMPLE_OMP_SECTION:
11309 case GIMPLE_OMP_MASTER:
11310 case GIMPLE_OMP_ORDERED:
11311 case GIMPLE_OMP_CRITICAL:
11312 case GIMPLE_OMP_TARGET:
11313 case GIMPLE_OMP_TEAMS:
11314 case GIMPLE_OMP_TASKGROUP:
11315 /* The minimal context here is just the current construct. */
11316 inner_context = stmt;
11317 wi->info = inner_context;
11318 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
11319 wi->info = context;
11320 break;
11322 case GIMPLE_OMP_FOR:
11323 inner_context = stmt;
11324 wi->info = inner_context;
11325 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
11326 walk them. */
11327 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
11328 diagnose_sb_1, NULL, wi);
11329 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
11330 wi->info = context;
11331 break;
11333 case GIMPLE_LABEL:
11334 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
11335 (splay_tree_value) context);
11336 break;
11338 default:
11339 break;
11342 return NULL_TREE;
11345 /* Pass 2: Check each branch and see if its context differs from that of
11346 the destination label's context. */
11348 static tree
11349 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
11350 struct walk_stmt_info *wi)
11352 gimple context = (gimple) wi->info;
11353 splay_tree_node n;
11354 gimple stmt = gsi_stmt (*gsi_p);
11356 *handled_ops_p = true;
11358 switch (gimple_code (stmt))
11360 WALK_SUBSTMTS;
11362 case GIMPLE_OACC_KERNELS:
11363 case GIMPLE_OACC_PARALLEL:
11364 case GIMPLE_OMP_PARALLEL:
11365 case GIMPLE_OMP_TASK:
11366 case GIMPLE_OMP_SECTIONS:
11367 case GIMPLE_OMP_SINGLE:
11368 case GIMPLE_OMP_SECTION:
11369 case GIMPLE_OMP_MASTER:
11370 case GIMPLE_OMP_ORDERED:
11371 case GIMPLE_OMP_CRITICAL:
11372 case GIMPLE_OMP_TARGET:
11373 case GIMPLE_OMP_TEAMS:
11374 case GIMPLE_OMP_TASKGROUP:
11375 wi->info = stmt;
11376 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
11377 wi->info = context;
11378 break;
11380 case GIMPLE_OMP_FOR:
11381 wi->info = stmt;
11382 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
11383 walk them. */
11384 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
11385 diagnose_sb_2, NULL, wi);
11386 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
11387 wi->info = context;
11388 break;
11390 case GIMPLE_COND:
11392 tree lab = gimple_cond_true_label (stmt);
11393 if (lab)
11395 n = splay_tree_lookup (all_labels,
11396 (splay_tree_key) lab);
11397 diagnose_sb_0 (gsi_p, context,
11398 n ? (gimple) n->value : NULL);
11400 lab = gimple_cond_false_label (stmt);
11401 if (lab)
11403 n = splay_tree_lookup (all_labels,
11404 (splay_tree_key) lab);
11405 diagnose_sb_0 (gsi_p, context,
11406 n ? (gimple) n->value : NULL);
11409 break;
11411 case GIMPLE_GOTO:
11413 tree lab = gimple_goto_dest (stmt);
11414 if (TREE_CODE (lab) != LABEL_DECL)
11415 break;
11417 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
11418 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
11420 break;
11422 case GIMPLE_SWITCH:
11424 unsigned int i;
11425 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
11427 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
11428 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
11429 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
11430 break;
11433 break;
11435 case GIMPLE_RETURN:
11436 diagnose_sb_0 (gsi_p, context, NULL);
11437 break;
11439 default:
11440 break;
11443 return NULL_TREE;
11446 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
11447 GIMPLE codes. */
11448 bool
11449 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
11450 int *region_idx)
11452 gimple last = last_stmt (bb);
11453 enum gimple_code code = gimple_code (last);
11454 struct omp_region *cur_region = *region;
11455 bool fallthru = false;
11457 switch (code)
11459 case GIMPLE_OACC_KERNELS:
11460 case GIMPLE_OACC_PARALLEL:
11461 case GIMPLE_OMP_PARALLEL:
11462 case GIMPLE_OMP_TASK:
11463 case GIMPLE_OMP_FOR:
11464 case GIMPLE_OMP_SINGLE:
11465 case GIMPLE_OMP_TEAMS:
11466 case GIMPLE_OMP_MASTER:
11467 case GIMPLE_OMP_TASKGROUP:
11468 case GIMPLE_OMP_ORDERED:
11469 case GIMPLE_OMP_CRITICAL:
11470 case GIMPLE_OMP_SECTION:
11471 cur_region = new_omp_region (bb, code, cur_region);
11472 fallthru = true;
11473 break;
11475 case GIMPLE_OMP_TARGET:
11476 cur_region = new_omp_region (bb, code, cur_region);
11477 fallthru = true;
11478 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
11479 cur_region = cur_region->outer;
11480 break;
11482 case GIMPLE_OMP_SECTIONS:
11483 cur_region = new_omp_region (bb, code, cur_region);
11484 fallthru = true;
11485 break;
11487 case GIMPLE_OMP_SECTIONS_SWITCH:
11488 fallthru = false;
11489 break;
11491 case GIMPLE_OMP_ATOMIC_LOAD:
11492 case GIMPLE_OMP_ATOMIC_STORE:
11493 fallthru = true;
11494 break;
11496 case GIMPLE_OMP_RETURN:
11497 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
11498 somewhere other than the next block. This will be
11499 created later. */
11500 cur_region->exit = bb;
11501 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
11502 cur_region = cur_region->outer;
11503 break;
11505 case GIMPLE_OMP_CONTINUE:
11506 cur_region->cont = bb;
11507 switch (cur_region->type)
11509 case GIMPLE_OMP_FOR:
11510 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11511 succs edges as abnormal to prevent splitting
11512 them. */
11513 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
11514 /* Make the loopback edge. */
11515 make_edge (bb, single_succ (cur_region->entry),
11516 EDGE_ABNORMAL);
11518 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11519 corresponds to the case that the body of the loop
11520 is not executed at all. */
11521 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
11522 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
11523 fallthru = false;
11524 break;
11526 case GIMPLE_OMP_SECTIONS:
11527 /* Wire up the edges into and out of the nested sections. */
11529 basic_block switch_bb = single_succ (cur_region->entry);
11531 struct omp_region *i;
11532 for (i = cur_region->inner; i ; i = i->next)
11534 gcc_assert (i->type == GIMPLE_OMP_SECTION);
11535 make_edge (switch_bb, i->entry, 0);
11536 make_edge (i->exit, bb, EDGE_FALLTHRU);
11539 /* Make the loopback edge to the block with
11540 GIMPLE_OMP_SECTIONS_SWITCH. */
11541 make_edge (bb, switch_bb, 0);
11543 /* Make the edge from the switch to exit. */
11544 make_edge (switch_bb, bb->next_bb, 0);
11545 fallthru = false;
11547 break;
11549 default:
11550 gcc_unreachable ();
11552 break;
11554 default:
11555 gcc_unreachable ();
11558 if (*region != cur_region)
11560 *region = cur_region;
11561 if (cur_region)
11562 *region_idx = cur_region->entry->index;
11563 else
11564 *region_idx = 0;
11567 return fallthru;
11570 static unsigned int
11571 diagnose_omp_structured_block_errors (void)
11573 struct walk_stmt_info wi;
11574 gimple_seq body = gimple_body (current_function_decl);
11576 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
11578 memset (&wi, 0, sizeof (wi));
11579 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
11581 memset (&wi, 0, sizeof (wi));
11582 wi.want_locations = true;
11583 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
11585 gimple_set_body (current_function_decl, body);
11587 splay_tree_delete (all_labels);
11588 all_labels = NULL;
11590 return 0;
11593 static bool
11594 gate_diagnose_omp_blocks (void)
11596 return flag_openacc || flag_openmp || flag_cilkplus;
11599 namespace {
11601 const pass_data pass_data_diagnose_omp_blocks =
11603 GIMPLE_PASS, /* type */
11604 "*diagnose_omp_blocks", /* name */
11605 OPTGROUP_NONE, /* optinfo_flags */
11606 true, /* has_gate */
11607 true, /* has_execute */
11608 TV_NONE, /* tv_id */
11609 PROP_gimple_any, /* properties_required */
11610 0, /* properties_provided */
11611 0, /* properties_destroyed */
11612 0, /* todo_flags_start */
11613 0, /* todo_flags_finish */
11616 class pass_diagnose_omp_blocks : public gimple_opt_pass
11618 public:
11619 pass_diagnose_omp_blocks (gcc::context *ctxt)
11620 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
11623 /* opt_pass methods: */
11624 bool gate () { return gate_diagnose_omp_blocks (); }
11625 unsigned int execute () {
11626 return diagnose_omp_structured_block_errors ();
11629 }; // class pass_diagnose_omp_blocks
11631 } // anon namespace
11633 gimple_opt_pass *
11634 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
11636 return new pass_diagnose_omp_blocks (ctxt);
11639 /* SIMD clone supporting code. */
11641 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11642 of arguments to reserve space for. */
11644 static struct cgraph_simd_clone *
11645 simd_clone_struct_alloc (int nargs)
11647 struct cgraph_simd_clone *clone_info;
11648 size_t len = (sizeof (struct cgraph_simd_clone)
11649 + nargs * sizeof (struct cgraph_simd_clone_arg));
11650 clone_info = (struct cgraph_simd_clone *)
11651 ggc_internal_cleared_alloc (len);
11652 return clone_info;
11655 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11657 static inline void
11658 simd_clone_struct_copy (struct cgraph_simd_clone *to,
11659 struct cgraph_simd_clone *from)
11661 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
11662 + ((from->nargs - from->inbranch)
11663 * sizeof (struct cgraph_simd_clone_arg))));
11666 /* Return vector of parameter types of function FNDECL. This uses
11667 TYPE_ARG_TYPES if available, otherwise falls back to types of
11668 DECL_ARGUMENTS types. */
11670 vec<tree>
11671 simd_clone_vector_of_formal_parm_types (tree fndecl)
11673 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
11674 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
11675 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
11676 unsigned int i;
11677 tree arg;
11678 FOR_EACH_VEC_ELT (args, i, arg)
11679 args[i] = TREE_TYPE (args[i]);
11680 return args;
11683 /* Given a simd function in NODE, extract the simd specific
11684 information from the OMP clauses passed in CLAUSES, and return
11685 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11686 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11687 otherwise set to FALSE. */
11689 static struct cgraph_simd_clone *
11690 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
11691 bool *inbranch_specified)
11693 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
11694 tree t;
11695 int n;
11696 *inbranch_specified = false;
11698 n = args.length ();
11699 if (n > 0 && args.last () == void_type_node)
11700 n--;
11702 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11703 be cloned have a distinctive artificial label in addition to "omp
11704 declare simd". */
11705 bool cilk_clone
11706 = (flag_cilkplus
11707 && lookup_attribute ("cilk simd function",
11708 DECL_ATTRIBUTES (node->decl)));
11710 /* Allocate one more than needed just in case this is an in-branch
11711 clone which will require a mask argument. */
11712 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
11713 clone_info->nargs = n;
11714 clone_info->cilk_elemental = cilk_clone;
11716 if (!clauses)
11718 args.release ();
11719 return clone_info;
11721 clauses = TREE_VALUE (clauses);
11722 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
11723 return clone_info;
11725 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
11727 switch (OMP_CLAUSE_CODE (t))
11729 case OMP_CLAUSE_INBRANCH:
11730 clone_info->inbranch = 1;
11731 *inbranch_specified = true;
11732 break;
11733 case OMP_CLAUSE_NOTINBRANCH:
11734 clone_info->inbranch = 0;
11735 *inbranch_specified = true;
11736 break;
11737 case OMP_CLAUSE_SIMDLEN:
11738 clone_info->simdlen
11739 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
11740 break;
11741 case OMP_CLAUSE_LINEAR:
11743 tree decl = OMP_CLAUSE_DECL (t);
11744 tree step = OMP_CLAUSE_LINEAR_STEP (t);
11745 int argno = TREE_INT_CST_LOW (decl);
11746 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
11748 clone_info->args[argno].arg_type
11749 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
11750 clone_info->args[argno].linear_step = tree_to_shwi (step);
11751 gcc_assert (clone_info->args[argno].linear_step >= 0
11752 && clone_info->args[argno].linear_step < n);
11754 else
11756 if (POINTER_TYPE_P (args[argno]))
11757 step = fold_convert (ssizetype, step);
11758 if (!tree_fits_shwi_p (step))
11760 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11761 "ignoring large linear step");
11762 args.release ();
11763 return NULL;
11765 else if (integer_zerop (step))
11767 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11768 "ignoring zero linear step");
11769 args.release ();
11770 return NULL;
11772 else
11774 clone_info->args[argno].arg_type
11775 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
11776 clone_info->args[argno].linear_step = tree_to_shwi (step);
11779 break;
11781 case OMP_CLAUSE_UNIFORM:
11783 tree decl = OMP_CLAUSE_DECL (t);
11784 int argno = tree_to_uhwi (decl);
11785 clone_info->args[argno].arg_type
11786 = SIMD_CLONE_ARG_TYPE_UNIFORM;
11787 break;
11789 case OMP_CLAUSE_ALIGNED:
11791 tree decl = OMP_CLAUSE_DECL (t);
11792 int argno = tree_to_uhwi (decl);
11793 clone_info->args[argno].alignment
11794 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
11795 break;
11797 default:
11798 break;
11801 args.release ();
11802 return clone_info;
11805 /* Given a SIMD clone in NODE, calculate the characteristic data
11806 type and return the coresponding type. The characteristic data
11807 type is computed as described in the Intel Vector ABI. */
11809 static tree
11810 simd_clone_compute_base_data_type (struct cgraph_node *node,
11811 struct cgraph_simd_clone *clone_info)
11813 tree type = integer_type_node;
11814 tree fndecl = node->decl;
11816 /* a) For non-void function, the characteristic data type is the
11817 return type. */
11818 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
11819 type = TREE_TYPE (TREE_TYPE (fndecl));
11821 /* b) If the function has any non-uniform, non-linear parameters,
11822 then the characteristic data type is the type of the first
11823 such parameter. */
11824 else
11826 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
11827 for (unsigned int i = 0; i < clone_info->nargs; ++i)
11828 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
11830 type = map[i];
11831 break;
11833 map.release ();
11836 /* c) If the characteristic data type determined by a) or b) above
11837 is struct, union, or class type which is pass-by-value (except
11838 for the type that maps to the built-in complex data type), the
11839 characteristic data type is int. */
11840 if (RECORD_OR_UNION_TYPE_P (type)
11841 && !aggregate_value_p (type, NULL)
11842 && TREE_CODE (type) != COMPLEX_TYPE)
11843 return integer_type_node;
11845 /* d) If none of the above three classes is applicable, the
11846 characteristic data type is int. */
11848 return type;
11850 /* e) For Intel Xeon Phi native and offload compilation, if the
11851 resulting characteristic data type is 8-bit or 16-bit integer
11852 data type, the characteristic data type is int. */
11853 /* Well, we don't handle Xeon Phi yet. */
11856 static tree
11857 simd_clone_mangle (struct cgraph_node *node,
11858 struct cgraph_simd_clone *clone_info)
11860 char vecsize_mangle = clone_info->vecsize_mangle;
11861 char mask = clone_info->inbranch ? 'M' : 'N';
11862 unsigned int simdlen = clone_info->simdlen;
11863 unsigned int n;
11864 pretty_printer pp;
11866 gcc_assert (vecsize_mangle && simdlen);
11868 pp_string (&pp, "_ZGV");
11869 pp_character (&pp, vecsize_mangle);
11870 pp_character (&pp, mask);
11871 pp_decimal_int (&pp, simdlen);
11873 for (n = 0; n < clone_info->nargs; ++n)
11875 struct cgraph_simd_clone_arg arg = clone_info->args[n];
11877 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
11878 pp_character (&pp, 'u');
11879 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11881 gcc_assert (arg.linear_step != 0);
11882 pp_character (&pp, 'l');
11883 if (arg.linear_step > 1)
11884 pp_unsigned_wide_integer (&pp, arg.linear_step);
11885 else if (arg.linear_step < 0)
11887 pp_character (&pp, 'n');
11888 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
11889 arg.linear_step));
11892 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11894 pp_character (&pp, 's');
11895 pp_unsigned_wide_integer (&pp, arg.linear_step);
11897 else
11898 pp_character (&pp, 'v');
11899 if (arg.alignment)
11901 pp_character (&pp, 'a');
11902 pp_decimal_int (&pp, arg.alignment);
11906 pp_underscore (&pp);
11907 pp_string (&pp,
11908 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11909 const char *str = pp_formatted_text (&pp);
11911 /* If there already is a SIMD clone with the same mangled name, don't
11912 add another one. This can happen e.g. for
11913 #pragma omp declare simd
11914 #pragma omp declare simd simdlen(8)
11915 int foo (int, int);
11916 if the simdlen is assumed to be 8 for the first one, etc. */
11917 for (struct cgraph_node *clone = node->simd_clones; clone;
11918 clone = clone->simdclone->next_clone)
11919 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11920 str) == 0)
11921 return NULL_TREE;
11923 return get_identifier (str);
11926 /* Create a simd clone of OLD_NODE and return it. */
11928 static struct cgraph_node *
11929 simd_clone_create (struct cgraph_node *old_node)
11931 struct cgraph_node *new_node;
11932 if (old_node->definition)
11934 if (!cgraph_function_with_gimple_body_p (old_node))
11935 return NULL;
11936 cgraph_get_body (old_node);
11937 new_node = cgraph_function_versioning (old_node, vNULL, NULL, NULL,
11938 false, NULL, NULL, "simdclone");
11940 else
11942 tree old_decl = old_node->decl;
11943 tree new_decl = copy_node (old_node->decl);
11944 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11945 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11946 SET_DECL_RTL (new_decl, NULL);
11947 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11948 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11949 new_node
11950 = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL);
11951 cgraph_call_function_insertion_hooks (new_node);
11953 if (new_node == NULL)
11954 return new_node;
11956 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11958 /* The function cgraph_function_versioning () will force the new
11959 symbol local. Undo this, and inherit external visability from
11960 the old node. */
11961 new_node->local.local = old_node->local.local;
11962 new_node->externally_visible = old_node->externally_visible;
11964 return new_node;
11967 /* Adjust the return type of the given function to its appropriate
11968 vector counterpart. Returns a simd array to be used throughout the
11969 function as a return value. */
11971 static tree
11972 simd_clone_adjust_return_type (struct cgraph_node *node)
11974 tree fndecl = node->decl;
11975 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11976 unsigned int veclen;
11977 tree t;
11979 /* Adjust the function return type. */
11980 if (orig_rettype == void_type_node)
11981 return NULL_TREE;
11982 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11983 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11984 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11985 veclen = node->simdclone->vecsize_int;
11986 else
11987 veclen = node->simdclone->vecsize_float;
11988 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11989 if (veclen > node->simdclone->simdlen)
11990 veclen = node->simdclone->simdlen;
11991 if (veclen == node->simdclone->simdlen)
11992 TREE_TYPE (TREE_TYPE (fndecl))
11993 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11994 node->simdclone->simdlen);
11995 else
11997 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11998 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11999 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12001 if (!node->definition)
12002 return NULL_TREE;
12004 t = DECL_RESULT (fndecl);
12005 /* Adjust the DECL_RESULT. */
12006 gcc_assert (TREE_TYPE (t) != void_type_node);
12007 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12008 relayout_decl (t);
12010 tree atype = build_array_type_nelts (orig_rettype,
12011 node->simdclone->simdlen);
12012 if (veclen != node->simdclone->simdlen)
12013 return build1 (VIEW_CONVERT_EXPR, atype, t);
12015 /* Set up a SIMD array to use as the return value. */
12016 tree retval = create_tmp_var_raw (atype, "retval");
12017 gimple_add_tmp_var (retval);
12018 return retval;
12021 /* Each vector argument has a corresponding array to be used locally
12022 as part of the eventual loop. Create such temporary array and
12023 return it.
12025 PREFIX is the prefix to be used for the temporary.
12027 TYPE is the inner element type.
12029 SIMDLEN is the number of elements. */
12031 static tree
12032 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12034 tree atype = build_array_type_nelts (type, simdlen);
12035 tree avar = create_tmp_var_raw (atype, prefix);
12036 gimple_add_tmp_var (avar);
12037 return avar;
12040 /* Modify the function argument types to their corresponding vector
12041 counterparts if appropriate. Also, create one array for each simd
12042 argument to be used locally when using the function arguments as
12043 part of the loop.
12045 NODE is the function whose arguments are to be adjusted.
12047 Returns an adjustment vector that will be filled describing how the
12048 argument types will be adjusted. */
12050 static ipa_parm_adjustment_vec
12051 simd_clone_adjust_argument_types (struct cgraph_node *node)
12053 vec<tree> args;
12054 ipa_parm_adjustment_vec adjustments;
12056 if (node->definition)
12057 args = ipa_get_vector_of_formal_parms (node->decl);
12058 else
12059 args = simd_clone_vector_of_formal_parm_types (node->decl);
12060 adjustments.create (args.length ());
12061 unsigned i, j, veclen;
12062 struct ipa_parm_adjustment adj;
12063 for (i = 0; i < node->simdclone->nargs; ++i)
12065 memset (&adj, 0, sizeof (adj));
12066 tree parm = args[i];
12067 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12068 adj.base_index = i;
12069 adj.base = parm;
12071 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12072 node->simdclone->args[i].orig_type = parm_type;
12074 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12076 /* No adjustment necessary for scalar arguments. */
12077 adj.op = IPA_PARM_OP_COPY;
12079 else
12081 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12082 veclen = node->simdclone->vecsize_int;
12083 else
12084 veclen = node->simdclone->vecsize_float;
12085 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12086 if (veclen > node->simdclone->simdlen)
12087 veclen = node->simdclone->simdlen;
12088 adj.arg_prefix = "simd";
12089 adj.type = build_vector_type (parm_type, veclen);
12090 node->simdclone->args[i].vector_type = adj.type;
12091 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12093 adjustments.safe_push (adj);
12094 if (j == veclen)
12096 memset (&adj, 0, sizeof (adj));
12097 adj.op = IPA_PARM_OP_NEW;
12098 adj.arg_prefix = "simd";
12099 adj.base_index = i;
12100 adj.type = node->simdclone->args[i].vector_type;
12104 if (node->definition)
12105 node->simdclone->args[i].simd_array
12106 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12107 parm_type, node->simdclone->simdlen);
12109 adjustments.safe_push (adj);
12112 if (node->simdclone->inbranch)
12114 tree base_type
12115 = simd_clone_compute_base_data_type (node->simdclone->origin,
12116 node->simdclone);
12118 memset (&adj, 0, sizeof (adj));
12119 adj.op = IPA_PARM_OP_NEW;
12120 adj.arg_prefix = "mask";
12122 adj.base_index = i;
12123 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12124 veclen = node->simdclone->vecsize_int;
12125 else
12126 veclen = node->simdclone->vecsize_float;
12127 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12128 if (veclen > node->simdclone->simdlen)
12129 veclen = node->simdclone->simdlen;
12130 adj.type = build_vector_type (base_type, veclen);
12131 adjustments.safe_push (adj);
12133 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12134 adjustments.safe_push (adj);
12136 /* We have previously allocated one extra entry for the mask. Use
12137 it and fill it. */
12138 struct cgraph_simd_clone *sc = node->simdclone;
12139 sc->nargs++;
12140 if (node->definition)
12142 sc->args[i].orig_arg
12143 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12144 sc->args[i].simd_array
12145 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12147 sc->args[i].orig_type = base_type;
12148 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12151 if (node->definition)
12152 ipa_modify_formal_parameters (node->decl, adjustments);
12153 else
12155 tree new_arg_types = NULL_TREE, new_reversed;
12156 bool last_parm_void = false;
12157 if (args.length () > 0 && args.last () == void_type_node)
12158 last_parm_void = true;
12160 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12161 j = adjustments.length ();
12162 for (i = 0; i < j; i++)
12164 struct ipa_parm_adjustment *adj = &adjustments[i];
12165 tree ptype;
12166 if (adj->op == IPA_PARM_OP_COPY)
12167 ptype = args[adj->base_index];
12168 else
12169 ptype = adj->type;
12170 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12172 new_reversed = nreverse (new_arg_types);
12173 if (last_parm_void)
12175 if (new_reversed)
12176 TREE_CHAIN (new_arg_types) = void_list_node;
12177 else
12178 new_reversed = void_list_node;
12181 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
12182 TYPE_ARG_TYPES (new_type) = new_reversed;
12183 TREE_TYPE (node->decl) = new_type;
12185 adjustments.release ();
12187 args.release ();
12188 return adjustments;
12191 /* Initialize and copy the function arguments in NODE to their
12192 corresponding local simd arrays. Returns a fresh gimple_seq with
12193 the instruction sequence generated. */
12195 static gimple_seq
12196 simd_clone_init_simd_arrays (struct cgraph_node *node,
12197 ipa_parm_adjustment_vec adjustments)
12199 gimple_seq seq = NULL;
12200 unsigned i = 0, j = 0, k;
12202 for (tree arg = DECL_ARGUMENTS (node->decl);
12203 arg;
12204 arg = DECL_CHAIN (arg), i++, j++)
12206 if (adjustments[j].op == IPA_PARM_OP_COPY)
12207 continue;
12209 node->simdclone->args[i].vector_arg = arg;
12211 tree array = node->simdclone->args[i].simd_array;
12212 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
12214 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12215 tree ptr = build_fold_addr_expr (array);
12216 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
12217 build_int_cst (ptype, 0));
12218 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
12219 gimplify_and_add (t, &seq);
12221 else
12223 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
12224 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12225 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
12227 tree ptr = build_fold_addr_expr (array);
12228 int elemsize;
12229 if (k)
12231 arg = DECL_CHAIN (arg);
12232 j++;
12234 elemsize
12235 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
12236 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
12237 build_int_cst (ptype, k * elemsize));
12238 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
12239 gimplify_and_add (t, &seq);
12243 return seq;
12246 /* Callback info for ipa_simd_modify_stmt_ops below. */
12248 struct modify_stmt_info {
12249 ipa_parm_adjustment_vec adjustments;
12250 gimple stmt;
12251 /* True if the parent statement was modified by
12252 ipa_simd_modify_stmt_ops. */
12253 bool modified;
12256 /* Callback for walk_gimple_op.
12258 Adjust operands from a given statement as specified in the
12259 adjustments vector in the callback data. */
12261 static tree
12262 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
12264 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
12265 if (!SSA_VAR_P (*tp))
12267 /* Make sure we treat subtrees as a RHS. This makes sure that
12268 when examining the `*foo' in *foo=x, the `foo' get treated as
12269 a use properly. */
12270 wi->is_lhs = false;
12271 wi->val_only = true;
12272 if (TYPE_P (*tp))
12273 *walk_subtrees = 0;
12274 return NULL_TREE;
12276 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
12277 struct ipa_parm_adjustment *cand
12278 = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
12279 if (!cand)
12280 return NULL_TREE;
12282 tree t = *tp;
12283 tree repl = make_ssa_name (TREE_TYPE (t), NULL);
12285 gimple stmt;
12286 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
12287 if (wi->is_lhs)
12289 stmt = gimple_build_assign (unshare_expr (cand->new_decl), repl);
12290 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
12291 SSA_NAME_DEF_STMT (repl) = info->stmt;
12293 else
12295 /* You'd think we could skip the extra SSA variable when
12296 wi->val_only=true, but we may have `*var' which will get
12297 replaced into `*var_array[iter]' and will likely be something
12298 not gimple. */
12299 stmt = gimple_build_assign (repl, unshare_expr (cand->new_decl));
12300 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
12303 if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
12305 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
12306 *tp = vce;
12308 else
12309 *tp = repl;
12311 info->modified = true;
12312 wi->is_lhs = false;
12313 wi->val_only = true;
12314 return NULL_TREE;
12317 /* Traverse the function body and perform all modifications as
12318 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
12319 modified such that the replacement/reduction value will now be an
12320 offset into the corresponding simd_array.
12322 This function will replace all function argument uses with their
12323 corresponding simd array elements, and ajust the return values
12324 accordingly. */
12326 static void
12327 ipa_simd_modify_function_body (struct cgraph_node *node,
12328 ipa_parm_adjustment_vec adjustments,
12329 tree retval_array, tree iter)
12331 basic_block bb;
12332 unsigned int i, j;
12334 /* Re-use the adjustments array, but this time use it to replace
12335 every function argument use to an offset into the corresponding
12336 simd_array. */
12337 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
12339 if (!node->simdclone->args[i].vector_arg)
12340 continue;
12342 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
12343 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
12344 adjustments[j].new_decl
12345 = build4 (ARRAY_REF,
12346 basetype,
12347 node->simdclone->args[i].simd_array,
12348 iter,
12349 NULL_TREE, NULL_TREE);
12350 if (adjustments[j].op == IPA_PARM_OP_NONE
12351 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
12352 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
12355 struct modify_stmt_info info;
12356 info.adjustments = adjustments;
12358 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
12360 gimple_stmt_iterator gsi;
12362 gsi = gsi_start_bb (bb);
12363 while (!gsi_end_p (gsi))
12365 gimple stmt = gsi_stmt (gsi);
12366 info.stmt = stmt;
12367 struct walk_stmt_info wi;
12369 memset (&wi, 0, sizeof (wi));
12370 info.modified = false;
12371 wi.info = &info;
12372 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
12374 if (gimple_code (stmt) == GIMPLE_RETURN)
12376 tree retval = gimple_return_retval (stmt);
12377 if (!retval)
12379 gsi_remove (&gsi, true);
12380 continue;
12383 /* Replace `return foo' with `retval_array[iter] = foo'. */
12384 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
12385 retval_array, iter, NULL, NULL);
12386 stmt = gimple_build_assign (ref, retval);
12387 gsi_replace (&gsi, stmt, true);
12388 info.modified = true;
12391 if (info.modified)
12393 update_stmt (stmt);
12394 if (maybe_clean_eh_stmt (stmt))
12395 gimple_purge_dead_eh_edges (gimple_bb (stmt));
12397 gsi_next (&gsi);
12402 /* Adjust the argument types in NODE to their appropriate vector
12403 counterparts. */
12405 static void
12406 simd_clone_adjust (struct cgraph_node *node)
12408 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
12410 targetm.simd_clone.adjust (node);
12412 tree retval = simd_clone_adjust_return_type (node);
12413 ipa_parm_adjustment_vec adjustments
12414 = simd_clone_adjust_argument_types (node);
12416 push_gimplify_context ();
12418 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
12420 /* Adjust all uses of vector arguments accordingly. Adjust all
12421 return values accordingly. */
12422 tree iter = create_tmp_var (unsigned_type_node, "iter");
12423 tree iter1 = make_ssa_name (iter, NULL);
12424 tree iter2 = make_ssa_name (iter, NULL);
12425 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
12427 /* Initialize the iteration variable. */
12428 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12429 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
12430 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
12431 /* Insert the SIMD array and iv initialization at function
12432 entry. */
12433 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
12435 pop_gimplify_context (NULL);
12437 /* Create a new BB right before the original exit BB, to hold the
12438 iteration increment and the condition/branch. */
12439 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
12440 basic_block incr_bb = create_empty_bb (orig_exit);
12441 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
12442 flag. Set it now to be a FALLTHRU_EDGE. */
12443 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
12444 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
12445 for (unsigned i = 0;
12446 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
12448 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
12449 redirect_edge_succ (e, incr_bb);
12451 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
12452 e->probability = REG_BR_PROB_BASE;
12453 gsi = gsi_last_bb (incr_bb);
12454 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
12455 build_int_cst (unsigned_type_node,
12456 1));
12457 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12459 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12460 struct loop *loop = alloc_loop ();
12461 cfun->has_force_vect_loops = true;
12462 loop->safelen = node->simdclone->simdlen;
12463 loop->force_vect = true;
12464 loop->header = body_bb;
12465 add_bb_to_loop (incr_bb, loop);
12467 /* Branch around the body if the mask applies. */
12468 if (node->simdclone->inbranch)
12470 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
12471 tree mask_array
12472 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
12473 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
12474 tree aref = build4 (ARRAY_REF,
12475 TREE_TYPE (TREE_TYPE (mask_array)),
12476 mask_array, iter1,
12477 NULL, NULL);
12478 g = gimple_build_assign (mask, aref);
12479 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12480 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
12481 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
12483 aref = build1 (VIEW_CONVERT_EXPR,
12484 build_nonstandard_integer_type (bitsize, 0), mask);
12485 mask = make_ssa_name (TREE_TYPE (aref), NULL);
12486 g = gimple_build_assign (mask, aref);
12487 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12490 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
12491 NULL, NULL);
12492 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12493 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
12494 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
12497 /* Generate the condition. */
12498 g = gimple_build_cond (LT_EXPR,
12499 iter2,
12500 build_int_cst (unsigned_type_node,
12501 node->simdclone->simdlen),
12502 NULL, NULL);
12503 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12504 e = split_block (incr_bb, gsi_stmt (gsi));
12505 basic_block latch_bb = e->dest;
12506 basic_block new_exit_bb = e->dest;
12507 new_exit_bb = split_block (latch_bb, NULL)->dest;
12508 loop->latch = latch_bb;
12510 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
12512 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
12513 /* The successor of incr_bb is already pointing to latch_bb; just
12514 change the flags.
12515 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12516 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
12518 gimple phi = create_phi_node (iter1, body_bb);
12519 edge preheader_edge = find_edge (entry_bb, body_bb);
12520 edge latch_edge = single_succ_edge (latch_bb);
12521 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
12522 UNKNOWN_LOCATION);
12523 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12525 /* Generate the new return. */
12526 gsi = gsi_last_bb (new_exit_bb);
12527 if (retval
12528 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
12529 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
12530 retval = TREE_OPERAND (retval, 0);
12531 else if (retval)
12533 retval = build1 (VIEW_CONVERT_EXPR,
12534 TREE_TYPE (TREE_TYPE (node->decl)),
12535 retval);
12536 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
12537 false, GSI_CONTINUE_LINKING);
12539 g = gimple_build_return (retval);
12540 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12542 /* Handle aligned clauses by replacing default defs of the aligned
12543 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12544 lhs. Handle linear by adding PHIs. */
12545 for (unsigned i = 0; i < node->simdclone->nargs; i++)
12546 if (node->simdclone->args[i].alignment
12547 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
12548 && (node->simdclone->args[i].alignment
12549 & (node->simdclone->args[i].alignment - 1)) == 0
12550 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
12551 == POINTER_TYPE)
12553 unsigned int alignment = node->simdclone->args[i].alignment;
12554 tree orig_arg = node->simdclone->args[i].orig_arg;
12555 tree def = ssa_default_def (cfun, orig_arg);
12556 if (def && !has_zero_uses (def))
12558 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
12559 gimple_seq seq = NULL;
12560 bool need_cvt = false;
12561 gimple call
12562 = gimple_build_call (fn, 2, def, size_int (alignment));
12563 g = call;
12564 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
12565 ptr_type_node))
12566 need_cvt = true;
12567 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
12568 gimple_call_set_lhs (g, t);
12569 gimple_seq_add_stmt_without_update (&seq, g);
12570 if (need_cvt)
12572 t = make_ssa_name (orig_arg, NULL);
12573 g = gimple_build_assign_with_ops (NOP_EXPR, t,
12574 gimple_call_lhs (g),
12575 NULL_TREE);
12576 gimple_seq_add_stmt_without_update (&seq, g);
12578 gsi_insert_seq_on_edge_immediate
12579 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
12581 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12582 int freq = compute_call_stmt_bb_frequency (current_function_decl,
12583 entry_bb);
12584 cgraph_create_edge (node, cgraph_get_create_node (fn),
12585 call, entry_bb->count, freq);
12587 imm_use_iterator iter;
12588 use_operand_p use_p;
12589 gimple use_stmt;
12590 tree repl = gimple_get_lhs (g);
12591 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12592 if (is_gimple_debug (use_stmt) || use_stmt == call)
12593 continue;
12594 else
12595 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12596 SET_USE (use_p, repl);
12599 else if (node->simdclone->args[i].arg_type
12600 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12602 tree orig_arg = node->simdclone->args[i].orig_arg;
12603 tree def = ssa_default_def (cfun, orig_arg);
12604 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12605 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
12606 if (def && !has_zero_uses (def))
12608 iter1 = make_ssa_name (orig_arg, NULL);
12609 iter2 = make_ssa_name (orig_arg, NULL);
12610 phi = create_phi_node (iter1, body_bb);
12611 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
12612 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12613 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12614 ? PLUS_EXPR : POINTER_PLUS_EXPR;
12615 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12616 ? TREE_TYPE (orig_arg) : sizetype;
12617 tree addcst
12618 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
12619 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
12620 gsi = gsi_last_bb (incr_bb);
12621 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12623 imm_use_iterator iter;
12624 use_operand_p use_p;
12625 gimple use_stmt;
12626 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12627 if (use_stmt == phi)
12628 continue;
12629 else
12630 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12631 SET_USE (use_p, iter1);
12635 calculate_dominance_info (CDI_DOMINATORS);
12636 add_loop (loop, loop->header->loop_father);
12637 update_ssa (TODO_update_ssa);
12639 pop_cfun ();
12642 /* If the function in NODE is tagged as an elemental SIMD function,
12643 create the appropriate SIMD clones. */
12645 static void
12646 expand_simd_clones (struct cgraph_node *node)
12648 tree attr = lookup_attribute ("omp declare simd",
12649 DECL_ATTRIBUTES (node->decl));
12650 if (attr == NULL_TREE
12651 || node->global.inlined_to
12652 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
12653 return;
12655 /* Ignore
12656 #pragma omp declare simd
12657 extern int foo ();
12658 in C, there we don't know the argument types at all. */
12659 if (!node->definition
12660 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
12661 return;
12665 /* Start with parsing the "omp declare simd" attribute(s). */
12666 bool inbranch_clause_specified;
12667 struct cgraph_simd_clone *clone_info
12668 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
12669 &inbranch_clause_specified);
12670 if (clone_info == NULL)
12671 continue;
12673 int orig_simdlen = clone_info->simdlen;
12674 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
12675 /* The target can return 0 (no simd clones should be created),
12676 1 (just one ISA of simd clones should be created) or higher
12677 count of ISA variants. In that case, clone_info is initialized
12678 for the first ISA variant. */
12679 int count
12680 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
12681 base_type, 0);
12682 if (count == 0)
12683 continue;
12685 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12686 also create one inbranch and one !inbranch clone of it. */
12687 for (int i = 0; i < count * 2; i++)
12689 struct cgraph_simd_clone *clone = clone_info;
12690 if (inbranch_clause_specified && (i & 1) != 0)
12691 continue;
12693 if (i != 0)
12695 clone = simd_clone_struct_alloc (clone_info->nargs
12696 + ((i & 1) != 0));
12697 simd_clone_struct_copy (clone, clone_info);
12698 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12699 and simd_clone_adjust_argument_types did to the first
12700 clone's info. */
12701 clone->nargs -= clone_info->inbranch;
12702 clone->simdlen = orig_simdlen;
12703 /* And call the target hook again to get the right ISA. */
12704 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
12705 base_type,
12706 i / 2);
12707 if ((i & 1) != 0)
12708 clone->inbranch = 1;
12711 /* simd_clone_mangle might fail if such a clone has been created
12712 already. */
12713 tree id = simd_clone_mangle (node, clone);
12714 if (id == NULL_TREE)
12715 continue;
12717 /* Only when we are sure we want to create the clone actually
12718 clone the function (or definitions) or create another
12719 extern FUNCTION_DECL (for prototypes without definitions). */
12720 struct cgraph_node *n = simd_clone_create (node);
12721 if (n == NULL)
12722 continue;
12724 n->simdclone = clone;
12725 clone->origin = node;
12726 clone->next_clone = NULL;
12727 if (node->simd_clones == NULL)
12729 clone->prev_clone = n;
12730 node->simd_clones = n;
12732 else
12734 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
12735 clone->prev_clone->simdclone->next_clone = n;
12736 node->simd_clones->simdclone->prev_clone = n;
12738 change_decl_assembler_name (n->decl, id);
12739 /* And finally adjust the return type, parameters and for
12740 definitions also function body. */
12741 if (node->definition)
12742 simd_clone_adjust (n);
12743 else
12745 simd_clone_adjust_return_type (n);
12746 simd_clone_adjust_argument_types (n);
12750 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
12753 /* Entry point for IPA simd clone creation pass. */
12755 static unsigned int
12756 ipa_omp_simd_clone (void)
12758 struct cgraph_node *node;
12759 FOR_EACH_FUNCTION (node)
12760 expand_simd_clones (node);
12761 return 0;
12764 namespace {
12766 const pass_data pass_data_omp_simd_clone =
12768 SIMPLE_IPA_PASS, /* type */
12769 "simdclone", /* name */
12770 OPTGROUP_NONE, /* optinfo_flags */
12771 true, /* has_gate */
12772 true, /* has_execute */
12773 TV_NONE, /* tv_id */
12774 ( PROP_ssa | PROP_cfg ), /* properties_required */
12775 0, /* properties_provided */
12776 0, /* properties_destroyed */
12777 0, /* todo_flags_start */
12778 0, /* todo_flags_finish */
12781 class pass_omp_simd_clone : public simple_ipa_opt_pass
12783 public:
12784 pass_omp_simd_clone(gcc::context *ctxt)
12785 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
12788 /* opt_pass methods: */
12789 bool gate () { return ((flag_openmp || flag_openmp_simd
12790 || flag_cilkplus || (in_lto_p && !flag_wpa))
12791 && (targetm.simd_clone.compute_vecsize_and_simdlen
12792 != NULL)); }
12793 unsigned int execute () { return ipa_omp_simd_clone (); }
12796 } // anon namespace
12798 simple_ipa_opt_pass *
12799 make_pass_omp_simd_clone (gcc::context *ctxt)
12801 return new pass_omp_simd_clone (ctxt);
12804 #include "gt-omp-low.h"