Nesting of OpenACC constructs inside of OpenACC data constructs.
[official-gcc.git] / gcc / omp-low.c
blob23a0dda64817986b9ca56f80d338a17c131076bf
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005-2014 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "stringpool.h"
30 #include "stor-layout.h"
31 #include "rtl.h"
32 #include "pointer-set.h"
33 #include "basic-block.h"
34 #include "tree-ssa-alias.h"
35 #include "internal-fn.h"
36 #include "gimple-fold.h"
37 #include "gimple-expr.h"
38 #include "is-a.h"
39 #include "gimple.h"
40 #include "gimplify.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "gimple-walk.h"
44 #include "tree-iterator.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47 #include "diagnostic-core.h"
48 #include "gimple-ssa.h"
49 #include "cgraph.h"
50 #include "tree-cfg.h"
51 #include "tree-phinodes.h"
52 #include "ssa-iterators.h"
53 #include "tree-ssanames.h"
54 #include "tree-into-ssa.h"
55 #include "expr.h"
56 #include "tree-dfa.h"
57 #include "tree-ssa.h"
58 #include "flags.h"
59 #include "function.h"
60 #include "expr.h"
61 #include "tree-pass.h"
62 #include "except.h"
63 #include "splay-tree.h"
64 #include "optabs.h"
65 #include "cfgloop.h"
66 #include "target.h"
67 #include "omp-low.h"
68 #include "gimple-low.h"
69 #include "tree-cfgcleanup.h"
70 #include "pretty-print.h"
71 #include "ipa-prop.h"
72 #include "tree-nested.h"
73 #include "tree-eh.h"
76 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
77 phases. The first phase scans the function looking for OMP statements
78 and then for variables that must be replaced to satisfy data sharing
79 clauses. The second phase expands code for the constructs, as well as
80 re-gimplifying things when variables have been replaced with complex
81 expressions.
83 Final code generation is done by pass_expand_omp. The flowgraph is
84 scanned for parallel regions which are then moved to a new
85 function, to be invoked by the thread library. */
87 /* Parallel region information. Every parallel and workshare
88 directive is enclosed between two markers, the OMP_* directive
89 and a corresponding OMP_RETURN statement. */
91 struct omp_region
93 /* The enclosing region. */
94 struct omp_region *outer;
96 /* First child region. */
97 struct omp_region *inner;
99 /* Next peer region. */
100 struct omp_region *next;
102 /* Block containing the omp directive as its last stmt. */
103 basic_block entry;
105 /* Block containing the OMP_RETURN as its last stmt. */
106 basic_block exit;
108 /* Block containing the OMP_CONTINUE as its last stmt. */
109 basic_block cont;
111 /* If this is a combined parallel+workshare region, this is a list
112 of additional arguments needed by the combined parallel+workshare
113 library call. */
114 vec<tree, va_gc> *ws_args;
116 /* The code for the omp directive of this region. */
117 enum gimple_code type;
119 /* Schedule kind, only used for OMP_FOR type regions. */
120 enum omp_clause_schedule_kind sched_kind;
122 /* True if this is a combined parallel+workshare region. */
123 bool is_combined_parallel;
126 /* Context structure. Used to store information about each parallel
127 directive in the code. */
129 typedef struct omp_context
131 /* This field must be at the beginning, as we do "inheritance": Some
132 callback functions for tree-inline.c (e.g., omp_copy_decl)
133 receive a copy_body_data pointer that is up-casted to an
134 omp_context pointer. */
135 copy_body_data cb;
137 /* The tree of contexts corresponding to the encountered constructs. */
138 struct omp_context *outer;
139 gimple stmt;
141 /* Map variables to fields in a structure that allows communication
142 between sending and receiving threads. */
143 splay_tree field_map;
144 tree record_type;
145 tree sender_decl;
146 tree receiver_decl;
148 /* These are used just by task contexts, if task firstprivate fn is
149 needed. srecord_type is used to communicate from the thread
150 that encountered the task construct to task firstprivate fn,
151 record_type is allocated by GOMP_task, initialized by task firstprivate
152 fn and passed to the task body fn. */
153 splay_tree sfield_map;
154 tree srecord_type;
156 /* A chain of variables to add to the top-level block surrounding the
157 construct. In the case of a parallel, this is in the child function. */
158 tree block_vars;
160 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
161 barriers should jump to during omplower pass. */
162 tree cancel_label;
164 /* What to do with variables with implicitly determined sharing
165 attributes. */
166 enum omp_clause_default_kind default_kind;
168 /* Nesting depth of this context. Used to beautify error messages re
169 invalid gotos. The outermost ctx is depth 1, with depth 0 being
170 reserved for the main body of the function. */
171 int depth;
173 /* True if this parallel directive is nested within another. */
174 bool is_nested;
176 /* True if this construct can be cancelled. */
177 bool cancellable;
178 } omp_context;
181 struct omp_for_data_loop
183 tree v, n1, n2, step;
184 enum tree_code cond_code;
187 /* A structure describing the main elements of a parallel loop. */
189 struct omp_for_data
191 struct omp_for_data_loop loop;
192 tree chunk_size;
193 gimple for_stmt;
194 tree pre, iter_type;
195 int collapse;
196 bool have_nowait, have_ordered;
197 enum omp_clause_schedule_kind sched_kind;
198 struct omp_for_data_loop *loops;
202 static splay_tree all_contexts;
203 static int taskreg_nesting_level;
204 static int target_nesting_level;
205 static struct omp_region *root_omp_region;
206 static bitmap task_shared_vars;
208 static void scan_omp (gimple_seq *, omp_context *);
209 static tree scan_omp_1_op (tree *, int *, void *);
211 #define WALK_SUBSTMTS \
212 case GIMPLE_BIND: \
213 case GIMPLE_TRY: \
214 case GIMPLE_CATCH: \
215 case GIMPLE_EH_FILTER: \
216 case GIMPLE_TRANSACTION: \
217 /* The sub-statements for these should be walked. */ \
218 *handled_ops_p = false; \
219 break;
221 /* Convenience function for calling scan_omp_1_op on tree operands. */
223 static inline tree
224 scan_omp_op (tree *tp, omp_context *ctx)
226 struct walk_stmt_info wi;
228 memset (&wi, 0, sizeof (wi));
229 wi.info = ctx;
230 wi.want_locations = true;
232 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
235 static void lower_omp (gimple_seq *, omp_context *);
236 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
237 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
239 /* Find an OpenMP clause of type KIND within CLAUSES. */
241 tree
242 find_omp_clause (tree clauses, enum omp_clause_code kind)
244 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
245 if (OMP_CLAUSE_CODE (clauses) == kind)
246 return clauses;
248 return NULL_TREE;
251 /* Return true if CTX is for an omp parallel. */
253 static inline bool
254 is_parallel_ctx (omp_context *ctx)
256 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
260 /* Return true if CTX is for an omp task. */
262 static inline bool
263 is_task_ctx (omp_context *ctx)
265 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
269 /* Return true if CTX is for an omp parallel or omp task. */
271 static inline bool
272 is_taskreg_ctx (omp_context *ctx)
274 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
275 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
279 /* Return true if REGION is a combined parallel+workshare region. */
281 static inline bool
282 is_combined_parallel (struct omp_region *region)
284 return region->is_combined_parallel;
288 /* Extract the header elements of parallel loop FOR_STMT and store
289 them into *FD. */
291 static void
292 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
293 struct omp_for_data_loop *loops)
295 tree t, var, *collapse_iter, *collapse_count;
296 tree count = NULL_TREE, iter_type = long_integer_type_node;
297 struct omp_for_data_loop *loop;
298 int i;
299 struct omp_for_data_loop dummy_loop;
300 location_t loc = gimple_location (for_stmt);
301 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_KIND_SIMD;
302 bool distribute = gimple_omp_for_kind (for_stmt)
303 == GF_OMP_FOR_KIND_DISTRIBUTE;
305 fd->for_stmt = for_stmt;
306 fd->pre = NULL;
307 fd->collapse = gimple_omp_for_collapse (for_stmt);
308 if (fd->collapse > 1)
309 fd->loops = loops;
310 else
311 fd->loops = &fd->loop;
313 fd->have_nowait = distribute || simd;
314 fd->have_ordered = false;
315 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
316 fd->chunk_size = NULL_TREE;
317 collapse_iter = NULL;
318 collapse_count = NULL;
320 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
321 switch (OMP_CLAUSE_CODE (t))
323 case OMP_CLAUSE_NOWAIT:
324 fd->have_nowait = true;
325 break;
326 case OMP_CLAUSE_ORDERED:
327 fd->have_ordered = true;
328 break;
329 case OMP_CLAUSE_SCHEDULE:
330 gcc_assert (!distribute);
331 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
332 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
333 break;
334 case OMP_CLAUSE_DIST_SCHEDULE:
335 gcc_assert (distribute);
336 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
337 break;
338 case OMP_CLAUSE_COLLAPSE:
339 if (fd->collapse > 1)
341 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
342 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
344 default:
345 break;
348 /* FIXME: for now map schedule(auto) to schedule(static).
349 There should be analysis to determine whether all iterations
350 are approximately the same amount of work (then schedule(static)
351 is best) or if it varies (then schedule(dynamic,N) is better). */
352 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
354 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
355 gcc_assert (fd->chunk_size == NULL);
357 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
358 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
359 gcc_assert (fd->chunk_size == NULL);
360 else if (fd->chunk_size == NULL)
362 /* We only need to compute a default chunk size for ordered
363 static loops and dynamic loops. */
364 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
365 || fd->have_ordered)
366 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
367 ? integer_zero_node : integer_one_node;
370 for (i = 0; i < fd->collapse; i++)
372 if (fd->collapse == 1)
373 loop = &fd->loop;
374 else if (loops != NULL)
375 loop = loops + i;
376 else
377 loop = &dummy_loop;
379 loop->v = gimple_omp_for_index (for_stmt, i);
380 gcc_assert (SSA_VAR_P (loop->v));
381 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
382 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
383 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
384 loop->n1 = gimple_omp_for_initial (for_stmt, i);
386 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
387 loop->n2 = gimple_omp_for_final (for_stmt, i);
388 switch (loop->cond_code)
390 case LT_EXPR:
391 case GT_EXPR:
392 break;
393 case NE_EXPR:
394 gcc_assert (gimple_omp_for_kind (for_stmt)
395 == GF_OMP_FOR_KIND_CILKSIMD);
396 break;
397 case LE_EXPR:
398 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
399 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
400 else
401 loop->n2 = fold_build2_loc (loc,
402 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
403 build_int_cst (TREE_TYPE (loop->n2), 1));
404 loop->cond_code = LT_EXPR;
405 break;
406 case GE_EXPR:
407 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
408 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
409 else
410 loop->n2 = fold_build2_loc (loc,
411 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
412 build_int_cst (TREE_TYPE (loop->n2), 1));
413 loop->cond_code = GT_EXPR;
414 break;
415 default:
416 gcc_unreachable ();
419 t = gimple_omp_for_incr (for_stmt, i);
420 gcc_assert (TREE_OPERAND (t, 0) == var);
421 switch (TREE_CODE (t))
423 case PLUS_EXPR:
424 loop->step = TREE_OPERAND (t, 1);
425 break;
426 case POINTER_PLUS_EXPR:
427 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
428 break;
429 case MINUS_EXPR:
430 loop->step = TREE_OPERAND (t, 1);
431 loop->step = fold_build1_loc (loc,
432 NEGATE_EXPR, TREE_TYPE (loop->step),
433 loop->step);
434 break;
435 default:
436 gcc_unreachable ();
439 if (simd
440 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
441 && !fd->have_ordered))
443 if (fd->collapse == 1)
444 iter_type = TREE_TYPE (loop->v);
445 else if (i == 0
446 || TYPE_PRECISION (iter_type)
447 < TYPE_PRECISION (TREE_TYPE (loop->v)))
448 iter_type
449 = build_nonstandard_integer_type
450 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
452 else if (iter_type != long_long_unsigned_type_node)
454 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
455 iter_type = long_long_unsigned_type_node;
456 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
457 && TYPE_PRECISION (TREE_TYPE (loop->v))
458 >= TYPE_PRECISION (iter_type))
460 tree n;
462 if (loop->cond_code == LT_EXPR)
463 n = fold_build2_loc (loc,
464 PLUS_EXPR, TREE_TYPE (loop->v),
465 loop->n2, loop->step);
466 else
467 n = loop->n1;
468 if (TREE_CODE (n) != INTEGER_CST
469 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
470 iter_type = long_long_unsigned_type_node;
472 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
473 > TYPE_PRECISION (iter_type))
475 tree n1, n2;
477 if (loop->cond_code == LT_EXPR)
479 n1 = loop->n1;
480 n2 = fold_build2_loc (loc,
481 PLUS_EXPR, TREE_TYPE (loop->v),
482 loop->n2, loop->step);
484 else
486 n1 = fold_build2_loc (loc,
487 MINUS_EXPR, TREE_TYPE (loop->v),
488 loop->n2, loop->step);
489 n2 = loop->n1;
491 if (TREE_CODE (n1) != INTEGER_CST
492 || TREE_CODE (n2) != INTEGER_CST
493 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
494 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
495 iter_type = long_long_unsigned_type_node;
499 if (collapse_count && *collapse_count == NULL)
501 t = fold_binary (loop->cond_code, boolean_type_node,
502 fold_convert (TREE_TYPE (loop->v), loop->n1),
503 fold_convert (TREE_TYPE (loop->v), loop->n2));
504 if (t && integer_zerop (t))
505 count = build_zero_cst (long_long_unsigned_type_node);
506 else if ((i == 0 || count != NULL_TREE)
507 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
508 && TREE_CONSTANT (loop->n1)
509 && TREE_CONSTANT (loop->n2)
510 && TREE_CODE (loop->step) == INTEGER_CST)
512 tree itype = TREE_TYPE (loop->v);
514 if (POINTER_TYPE_P (itype))
515 itype = signed_type_for (itype);
516 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
517 t = fold_build2_loc (loc,
518 PLUS_EXPR, itype,
519 fold_convert_loc (loc, itype, loop->step), t);
520 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
521 fold_convert_loc (loc, itype, loop->n2));
522 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
523 fold_convert_loc (loc, itype, loop->n1));
524 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
525 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
526 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
527 fold_build1_loc (loc, NEGATE_EXPR, itype,
528 fold_convert_loc (loc, itype,
529 loop->step)));
530 else
531 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
532 fold_convert_loc (loc, itype, loop->step));
533 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
534 if (count != NULL_TREE)
535 count = fold_build2_loc (loc,
536 MULT_EXPR, long_long_unsigned_type_node,
537 count, t);
538 else
539 count = t;
540 if (TREE_CODE (count) != INTEGER_CST)
541 count = NULL_TREE;
543 else if (count && !integer_zerop (count))
544 count = NULL_TREE;
548 if (count
549 && !simd
550 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
551 || fd->have_ordered))
553 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
554 iter_type = long_long_unsigned_type_node;
555 else
556 iter_type = long_integer_type_node;
558 else if (collapse_iter && *collapse_iter != NULL)
559 iter_type = TREE_TYPE (*collapse_iter);
560 fd->iter_type = iter_type;
561 if (collapse_iter && *collapse_iter == NULL)
562 *collapse_iter = create_tmp_var (iter_type, ".iter");
563 if (collapse_count && *collapse_count == NULL)
565 if (count)
566 *collapse_count = fold_convert_loc (loc, iter_type, count);
567 else
568 *collapse_count = create_tmp_var (iter_type, ".count");
571 if (fd->collapse > 1)
573 fd->loop.v = *collapse_iter;
574 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
575 fd->loop.n2 = *collapse_count;
576 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
577 fd->loop.cond_code = LT_EXPR;
582 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
583 is the immediate dominator of PAR_ENTRY_BB, return true if there
584 are no data dependencies that would prevent expanding the parallel
585 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
587 When expanding a combined parallel+workshare region, the call to
588 the child function may need additional arguments in the case of
589 GIMPLE_OMP_FOR regions. In some cases, these arguments are
590 computed out of variables passed in from the parent to the child
591 via 'struct .omp_data_s'. For instance:
593 #pragma omp parallel for schedule (guided, i * 4)
594 for (j ...)
596 Is lowered into:
598 # BLOCK 2 (PAR_ENTRY_BB)
599 .omp_data_o.i = i;
600 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
602 # BLOCK 3 (WS_ENTRY_BB)
603 .omp_data_i = &.omp_data_o;
604 D.1667 = .omp_data_i->i;
605 D.1598 = D.1667 * 4;
606 #pragma omp for schedule (guided, D.1598)
608 When we outline the parallel region, the call to the child function
609 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
610 that value is computed *after* the call site. So, in principle we
611 cannot do the transformation.
613 To see whether the code in WS_ENTRY_BB blocks the combined
614 parallel+workshare call, we collect all the variables used in the
615 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
616 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
617 call.
619 FIXME. If we had the SSA form built at this point, we could merely
620 hoist the code in block 3 into block 2 and be done with it. But at
621 this point we don't have dataflow information and though we could
622 hack something up here, it is really not worth the aggravation. */
624 static bool
625 workshare_safe_to_combine_p (basic_block ws_entry_bb)
627 struct omp_for_data fd;
628 gimple ws_stmt = last_stmt (ws_entry_bb);
630 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
631 return true;
633 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
635 extract_omp_for_data (ws_stmt, &fd, NULL);
637 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
638 return false;
639 if (fd.iter_type != long_integer_type_node)
640 return false;
642 /* FIXME. We give up too easily here. If any of these arguments
643 are not constants, they will likely involve variables that have
644 been mapped into fields of .omp_data_s for sharing with the child
645 function. With appropriate data flow, it would be possible to
646 see through this. */
647 if (!is_gimple_min_invariant (fd.loop.n1)
648 || !is_gimple_min_invariant (fd.loop.n2)
649 || !is_gimple_min_invariant (fd.loop.step)
650 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
651 return false;
653 return true;
657 /* Collect additional arguments needed to emit a combined
658 parallel+workshare call. WS_STMT is the workshare directive being
659 expanded. */
661 static vec<tree, va_gc> *
662 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
664 tree t;
665 location_t loc = gimple_location (ws_stmt);
666 vec<tree, va_gc> *ws_args;
668 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
670 struct omp_for_data fd;
671 tree n1, n2;
673 extract_omp_for_data (ws_stmt, &fd, NULL);
674 n1 = fd.loop.n1;
675 n2 = fd.loop.n2;
677 if (gimple_omp_for_combined_into_p (ws_stmt))
679 tree innerc
680 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
681 OMP_CLAUSE__LOOPTEMP_);
682 gcc_assert (innerc);
683 n1 = OMP_CLAUSE_DECL (innerc);
684 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
685 OMP_CLAUSE__LOOPTEMP_);
686 gcc_assert (innerc);
687 n2 = OMP_CLAUSE_DECL (innerc);
690 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
692 t = fold_convert_loc (loc, long_integer_type_node, n1);
693 ws_args->quick_push (t);
695 t = fold_convert_loc (loc, long_integer_type_node, n2);
696 ws_args->quick_push (t);
698 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
699 ws_args->quick_push (t);
701 if (fd.chunk_size)
703 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
704 ws_args->quick_push (t);
707 return ws_args;
709 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
711 /* Number of sections is equal to the number of edges from the
712 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
713 the exit of the sections region. */
714 basic_block bb = single_succ (gimple_bb (ws_stmt));
715 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
716 vec_alloc (ws_args, 1);
717 ws_args->quick_push (t);
718 return ws_args;
721 gcc_unreachable ();
725 /* Discover whether REGION is a combined parallel+workshare region. */
727 static void
728 determine_parallel_type (struct omp_region *region)
730 basic_block par_entry_bb, par_exit_bb;
731 basic_block ws_entry_bb, ws_exit_bb;
733 if (region == NULL || region->inner == NULL
734 || region->exit == NULL || region->inner->exit == NULL
735 || region->inner->cont == NULL)
736 return;
738 /* We only support parallel+for and parallel+sections. */
739 if (region->type != GIMPLE_OMP_PARALLEL
740 || (region->inner->type != GIMPLE_OMP_FOR
741 && region->inner->type != GIMPLE_OMP_SECTIONS))
742 return;
744 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
745 WS_EXIT_BB -> PAR_EXIT_BB. */
746 par_entry_bb = region->entry;
747 par_exit_bb = region->exit;
748 ws_entry_bb = region->inner->entry;
749 ws_exit_bb = region->inner->exit;
751 if (single_succ (par_entry_bb) == ws_entry_bb
752 && single_succ (ws_exit_bb) == par_exit_bb
753 && workshare_safe_to_combine_p (ws_entry_bb)
754 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
755 || (last_and_only_stmt (ws_entry_bb)
756 && last_and_only_stmt (par_exit_bb))))
758 gimple par_stmt = last_stmt (par_entry_bb);
759 gimple ws_stmt = last_stmt (ws_entry_bb);
761 if (region->inner->type == GIMPLE_OMP_FOR)
763 /* If this is a combined parallel loop, we need to determine
764 whether or not to use the combined library calls. There
765 are two cases where we do not apply the transformation:
766 static loops and any kind of ordered loop. In the first
767 case, we already open code the loop so there is no need
768 to do anything else. In the latter case, the combined
769 parallel loop call would still need extra synchronization
770 to implement ordered semantics, so there would not be any
771 gain in using the combined call. */
772 tree clauses = gimple_omp_for_clauses (ws_stmt);
773 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
774 if (c == NULL
775 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
776 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
778 region->is_combined_parallel = false;
779 region->inner->is_combined_parallel = false;
780 return;
784 region->is_combined_parallel = true;
785 region->inner->is_combined_parallel = true;
786 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
791 /* Return true if EXPR is variable sized. */
793 static inline bool
794 is_variable_sized (const_tree expr)
796 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
799 /* Return true if DECL is a reference type. */
801 static inline bool
802 is_reference (tree decl)
804 return lang_hooks.decls.omp_privatize_by_reference (decl);
807 /* Lookup variables in the decl or field splay trees. The "maybe" form
808 allows for the variable form to not have been entered, otherwise we
809 assert that the variable must have been entered. */
811 static inline tree
812 lookup_decl (tree var, omp_context *ctx)
814 tree *n;
815 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
816 return *n;
819 static inline tree
820 maybe_lookup_decl (const_tree var, omp_context *ctx)
822 tree *n;
823 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
824 return n ? *n : NULL_TREE;
827 static inline tree
828 lookup_field (tree var, omp_context *ctx)
830 splay_tree_node n;
831 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
832 return (tree) n->value;
835 static inline tree
836 lookup_sfield (tree var, omp_context *ctx)
838 splay_tree_node n;
839 n = splay_tree_lookup (ctx->sfield_map
840 ? ctx->sfield_map : ctx->field_map,
841 (splay_tree_key) var);
842 return (tree) n->value;
845 static inline tree
846 maybe_lookup_field (tree var, omp_context *ctx)
848 splay_tree_node n;
849 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
850 return n ? (tree) n->value : NULL_TREE;
853 /* Return true if DECL should be copied by pointer. SHARED_CTX is
854 the parallel context if DECL is to be shared. */
856 static bool
857 use_pointer_for_field (tree decl, omp_context *shared_ctx)
859 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
860 return true;
862 /* We can only use copy-in/copy-out semantics for shared variables
863 when we know the value is not accessible from an outer scope. */
864 if (shared_ctx)
866 gcc_assert (!is_gimple_omp_oacc_specifically (shared_ctx->stmt));
868 /* ??? Trivially accessible from anywhere. But why would we even
869 be passing an address in this case? Should we simply assert
870 this to be false, or should we have a cleanup pass that removes
871 these from the list of mappings? */
872 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
873 return true;
875 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
876 without analyzing the expression whether or not its location
877 is accessible to anyone else. In the case of nested parallel
878 regions it certainly may be. */
879 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
880 return true;
882 /* Do not use copy-in/copy-out for variables that have their
883 address taken. */
884 if (TREE_ADDRESSABLE (decl))
885 return true;
887 /* lower_send_shared_vars only uses copy-in, but not copy-out
888 for these. */
889 if (TREE_READONLY (decl)
890 || ((TREE_CODE (decl) == RESULT_DECL
891 || TREE_CODE (decl) == PARM_DECL)
892 && DECL_BY_REFERENCE (decl)))
893 return false;
895 /* Disallow copy-in/out in nested parallel if
896 decl is shared in outer parallel, otherwise
897 each thread could store the shared variable
898 in its own copy-in location, making the
899 variable no longer really shared. */
900 if (shared_ctx->is_nested)
902 omp_context *up;
904 for (up = shared_ctx->outer; up; up = up->outer)
905 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
906 break;
908 if (up)
910 tree c;
912 for (c = gimple_omp_taskreg_clauses (up->stmt);
913 c; c = OMP_CLAUSE_CHAIN (c))
914 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
915 && OMP_CLAUSE_DECL (c) == decl)
916 break;
918 if (c)
919 goto maybe_mark_addressable_and_ret;
923 /* For tasks avoid using copy-in/out. As tasks can be
924 deferred or executed in different thread, when GOMP_task
925 returns, the task hasn't necessarily terminated. */
926 if (is_task_ctx (shared_ctx))
928 tree outer;
929 maybe_mark_addressable_and_ret:
930 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
931 if (is_gimple_reg (outer))
933 /* Taking address of OUTER in lower_send_shared_vars
934 might need regimplification of everything that uses the
935 variable. */
936 if (!task_shared_vars)
937 task_shared_vars = BITMAP_ALLOC (NULL);
938 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
939 TREE_ADDRESSABLE (outer) = 1;
941 return true;
945 return false;
948 /* Construct a new automatic decl similar to VAR. */
950 static tree
951 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
953 tree copy = copy_var_decl (var, name, type);
955 DECL_CONTEXT (copy) = current_function_decl;
956 DECL_CHAIN (copy) = ctx->block_vars;
957 ctx->block_vars = copy;
959 return copy;
962 static tree
963 omp_copy_decl_1 (tree var, omp_context *ctx)
965 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
968 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
969 as appropriate. */
970 static tree
971 omp_build_component_ref (tree obj, tree field)
973 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
974 if (TREE_THIS_VOLATILE (field))
975 TREE_THIS_VOLATILE (ret) |= 1;
976 if (TREE_READONLY (field))
977 TREE_READONLY (ret) |= 1;
978 return ret;
981 /* Build tree nodes to access the field for VAR on the receiver side. */
983 static tree
984 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
986 tree x, field = lookup_field (var, ctx);
988 /* If the receiver record type was remapped in the child function,
989 remap the field into the new record type. */
990 x = maybe_lookup_field (field, ctx);
991 if (x != NULL)
992 field = x;
994 x = build_simple_mem_ref (ctx->receiver_decl);
995 x = omp_build_component_ref (x, field);
996 if (by_ref)
997 x = build_simple_mem_ref (x);
999 return x;
1002 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1003 of a parallel, this is a component reference; for workshare constructs
1004 this is some variable. */
1006 static tree
1007 build_outer_var_ref (tree var, omp_context *ctx)
1009 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1011 tree x;
1013 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1014 x = var;
1015 else if (is_variable_sized (var))
1017 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1018 x = build_outer_var_ref (x, ctx);
1019 x = build_simple_mem_ref (x);
1021 else if (is_taskreg_ctx (ctx))
1023 bool by_ref = use_pointer_for_field (var, NULL);
1024 x = build_receiver_ref (var, by_ref, ctx);
1026 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1027 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
1029 /* #pragma omp simd isn't a worksharing construct, and can reference even
1030 private vars in its linear etc. clauses. */
1031 x = NULL_TREE;
1032 if (ctx->outer && is_taskreg_ctx (ctx))
1033 x = lookup_decl (var, ctx->outer);
1034 else if (ctx->outer)
1035 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1036 if (x == NULL_TREE)
1037 x = var;
1039 else if (ctx->outer)
1040 x = lookup_decl (var, ctx->outer);
1041 else if (is_reference (var))
1042 /* This can happen with orphaned constructs. If var is reference, it is
1043 possible it is shared and as such valid. */
1044 x = var;
1045 else
1046 gcc_unreachable ();
1048 if (is_reference (var))
1049 x = build_simple_mem_ref (x);
1051 return x;
1054 /* Build tree nodes to access the field for VAR on the sender side. */
1056 static tree
1057 build_sender_ref (tree var, omp_context *ctx)
1059 tree field = lookup_sfield (var, ctx);
1060 return omp_build_component_ref (ctx->sender_decl, field);
1063 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1065 static void
1066 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1068 tree field, type, sfield = NULL_TREE;
1070 gcc_assert ((mask & 1) == 0
1071 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1072 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1073 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1074 gcc_assert ((mask & 3) == 3
1075 || !is_gimple_omp_oacc_specifically (ctx->stmt));
1077 type = TREE_TYPE (var);
1078 if (mask & 4)
1080 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1081 type = build_pointer_type (build_pointer_type (type));
1083 else if (by_ref)
1084 type = build_pointer_type (type);
1085 else if ((mask & 3) == 1 && is_reference (var))
1086 type = TREE_TYPE (type);
1088 field = build_decl (DECL_SOURCE_LOCATION (var),
1089 FIELD_DECL, DECL_NAME (var), type);
1091 /* Remember what variable this field was created for. This does have a
1092 side effect of making dwarf2out ignore this member, so for helpful
1093 debugging we clear it later in delete_omp_context. */
1094 DECL_ABSTRACT_ORIGIN (field) = var;
1095 if (type == TREE_TYPE (var))
1097 DECL_ALIGN (field) = DECL_ALIGN (var);
1098 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1099 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1101 else
1102 DECL_ALIGN (field) = TYPE_ALIGN (type);
1104 if ((mask & 3) == 3)
1106 insert_field_into_struct (ctx->record_type, field);
1107 if (ctx->srecord_type)
1109 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1110 FIELD_DECL, DECL_NAME (var), type);
1111 DECL_ABSTRACT_ORIGIN (sfield) = var;
1112 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1113 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1114 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1115 insert_field_into_struct (ctx->srecord_type, sfield);
1118 else
1120 if (ctx->srecord_type == NULL_TREE)
1122 tree t;
1124 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1125 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1126 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1128 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1129 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1130 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1131 insert_field_into_struct (ctx->srecord_type, sfield);
1132 splay_tree_insert (ctx->sfield_map,
1133 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1134 (splay_tree_value) sfield);
1137 sfield = field;
1138 insert_field_into_struct ((mask & 1) ? ctx->record_type
1139 : ctx->srecord_type, field);
1142 if (mask & 1)
1143 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1144 (splay_tree_value) field);
1145 if ((mask & 2) && ctx->sfield_map)
1146 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1147 (splay_tree_value) sfield);
1150 static tree
1151 install_var_local (tree var, omp_context *ctx)
1153 tree new_var = omp_copy_decl_1 (var, ctx);
1154 insert_decl_map (&ctx->cb, var, new_var);
1155 return new_var;
1158 /* Adjust the replacement for DECL in CTX for the new context. This means
1159 copying the DECL_VALUE_EXPR, and fixing up the type. */
1161 static void
1162 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1164 tree new_decl, size;
1166 new_decl = lookup_decl (decl, ctx);
1168 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1170 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1171 && DECL_HAS_VALUE_EXPR_P (decl))
1173 tree ve = DECL_VALUE_EXPR (decl);
1174 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1175 SET_DECL_VALUE_EXPR (new_decl, ve);
1176 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1179 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1181 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1182 if (size == error_mark_node)
1183 size = TYPE_SIZE (TREE_TYPE (new_decl));
1184 DECL_SIZE (new_decl) = size;
1186 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1187 if (size == error_mark_node)
1188 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1189 DECL_SIZE_UNIT (new_decl) = size;
1193 /* The callback for remap_decl. Search all containing contexts for a
1194 mapping of the variable; this avoids having to duplicate the splay
1195 tree ahead of time. We know a mapping doesn't already exist in the
1196 given context. Create new mappings to implement default semantics. */
1198 static tree
1199 omp_copy_decl (tree var, copy_body_data *cb)
1201 omp_context *ctx = (omp_context *) cb;
1202 tree new_var;
1204 if (TREE_CODE (var) == LABEL_DECL)
1206 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1207 DECL_CONTEXT (new_var) = current_function_decl;
1208 insert_decl_map (&ctx->cb, var, new_var);
1209 return new_var;
1212 while (!is_taskreg_ctx (ctx))
1214 ctx = ctx->outer;
1215 if (ctx == NULL)
1216 return var;
1217 new_var = maybe_lookup_decl (var, ctx);
1218 if (new_var)
1219 return new_var;
1222 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1223 return var;
1225 return error_mark_node;
1229 /* Debugging dumps for parallel regions. */
1230 void dump_omp_region (FILE *, struct omp_region *, int);
1231 void debug_omp_region (struct omp_region *);
1232 void debug_all_omp_regions (void);
1234 /* Dump the parallel region tree rooted at REGION. */
1236 void
1237 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1239 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1240 gimple_code_name[region->type]);
1242 if (region->inner)
1243 dump_omp_region (file, region->inner, indent + 4);
1245 if (region->cont)
1247 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1248 region->cont->index);
1251 if (region->exit)
1252 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1253 region->exit->index);
1254 else
1255 fprintf (file, "%*s[no exit marker]\n", indent, "");
1257 if (region->next)
1258 dump_omp_region (file, region->next, indent);
1261 DEBUG_FUNCTION void
1262 debug_omp_region (struct omp_region *region)
1264 dump_omp_region (stderr, region, 0);
1267 DEBUG_FUNCTION void
1268 debug_all_omp_regions (void)
1270 dump_omp_region (stderr, root_omp_region, 0);
1274 /* Create a new parallel region starting at STMT inside region PARENT. */
1276 static struct omp_region *
1277 new_omp_region (basic_block bb, enum gimple_code type,
1278 struct omp_region *parent)
1280 struct omp_region *region = XCNEW (struct omp_region);
1282 region->outer = parent;
1283 region->entry = bb;
1284 region->type = type;
1286 if (parent)
1288 /* This is a nested region. Add it to the list of inner
1289 regions in PARENT. */
1290 region->next = parent->inner;
1291 parent->inner = region;
1293 else
1295 /* This is a toplevel region. Add it to the list of toplevel
1296 regions in ROOT_OMP_REGION. */
1297 region->next = root_omp_region;
1298 root_omp_region = region;
1301 return region;
1304 /* Release the memory associated with the region tree rooted at REGION. */
1306 static void
1307 free_omp_region_1 (struct omp_region *region)
1309 struct omp_region *i, *n;
1311 for (i = region->inner; i ; i = n)
1313 n = i->next;
1314 free_omp_region_1 (i);
1317 free (region);
1320 /* Release the memory for the entire omp region tree. */
1322 void
1323 free_omp_regions (void)
1325 struct omp_region *r, *n;
1326 for (r = root_omp_region; r ; r = n)
1328 n = r->next;
1329 free_omp_region_1 (r);
1331 root_omp_region = NULL;
1335 /* Create a new context, with OUTER_CTX being the surrounding context. */
1337 static omp_context *
1338 new_omp_context (gimple stmt, omp_context *outer_ctx)
1340 omp_context *ctx = XCNEW (omp_context);
1342 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1343 (splay_tree_value) ctx);
1344 ctx->stmt = stmt;
1346 if (outer_ctx)
1348 ctx->outer = outer_ctx;
1349 ctx->cb = outer_ctx->cb;
1350 ctx->cb.block = NULL;
1351 ctx->depth = outer_ctx->depth + 1;
1353 else
1355 ctx->cb.src_fn = current_function_decl;
1356 ctx->cb.dst_fn = current_function_decl;
1357 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1358 gcc_checking_assert (ctx->cb.src_node);
1359 ctx->cb.dst_node = ctx->cb.src_node;
1360 ctx->cb.src_cfun = cfun;
1361 ctx->cb.copy_decl = omp_copy_decl;
1362 ctx->cb.eh_lp_nr = 0;
1363 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1364 ctx->depth = 1;
1367 ctx->cb.decl_map = pointer_map_create ();
1369 return ctx;
1372 static gimple_seq maybe_catch_exception (gimple_seq);
1374 /* Finalize task copyfn. */
1376 static void
1377 finalize_task_copyfn (gimple task_stmt)
1379 struct function *child_cfun;
1380 tree child_fn;
1381 gimple_seq seq = NULL, new_seq;
1382 gimple bind;
1384 child_fn = gimple_omp_task_copy_fn (task_stmt);
1385 if (child_fn == NULL_TREE)
1386 return;
1388 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1389 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1391 push_cfun (child_cfun);
1392 bind = gimplify_body (child_fn, false);
1393 gimple_seq_add_stmt (&seq, bind);
1394 new_seq = maybe_catch_exception (seq);
1395 if (new_seq != seq)
1397 bind = gimple_build_bind (NULL, new_seq, NULL);
1398 seq = NULL;
1399 gimple_seq_add_stmt (&seq, bind);
1401 gimple_set_body (child_fn, seq);
1402 pop_cfun ();
1404 /* Inform the callgraph about the new function. */
1405 cgraph_add_new_function (child_fn, false);
1408 /* Destroy a omp_context data structures. Called through the splay tree
1409 value delete callback. */
1411 static void
1412 delete_omp_context (splay_tree_value value)
1414 omp_context *ctx = (omp_context *) value;
1416 pointer_map_destroy (ctx->cb.decl_map);
1418 if (ctx->field_map)
1419 splay_tree_delete (ctx->field_map);
1420 if (ctx->sfield_map)
1421 splay_tree_delete (ctx->sfield_map);
1423 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1424 it produces corrupt debug information. */
1425 if (ctx->record_type)
1427 tree t;
1428 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1429 DECL_ABSTRACT_ORIGIN (t) = NULL;
1431 if (ctx->srecord_type)
1433 tree t;
1434 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1435 DECL_ABSTRACT_ORIGIN (t) = NULL;
1438 if (is_task_ctx (ctx))
1439 finalize_task_copyfn (ctx->stmt);
1441 XDELETE (ctx);
1444 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1445 context. */
1447 static void
1448 fixup_child_record_type (omp_context *ctx)
1450 tree f, type = ctx->record_type;
1452 /* ??? It isn't sufficient to just call remap_type here, because
1453 variably_modified_type_p doesn't work the way we expect for
1454 record types. Testing each field for whether it needs remapping
1455 and creating a new record by hand works, however. */
1456 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1457 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1458 break;
1459 if (f)
1461 tree name, new_fields = NULL;
1463 type = lang_hooks.types.make_type (RECORD_TYPE);
1464 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1465 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1466 TYPE_DECL, name, type);
1467 TYPE_NAME (type) = name;
1469 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1471 tree new_f = copy_node (f);
1472 DECL_CONTEXT (new_f) = type;
1473 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1474 DECL_CHAIN (new_f) = new_fields;
1475 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1476 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1477 &ctx->cb, NULL);
1478 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1479 &ctx->cb, NULL);
1480 new_fields = new_f;
1482 /* Arrange to be able to look up the receiver field
1483 given the sender field. */
1484 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1485 (splay_tree_value) new_f);
1487 TYPE_FIELDS (type) = nreverse (new_fields);
1488 layout_type (type);
1491 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1494 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1495 specified by CLAUSES. */
1497 static void
1498 scan_sharing_clauses (tree clauses, omp_context *ctx)
1500 tree c, decl;
1501 bool scan_array_reductions = false;
1503 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1505 bool by_ref;
1507 switch (OMP_CLAUSE_CODE (c))
1509 case OMP_CLAUSE_PRIVATE:
1510 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1511 decl = OMP_CLAUSE_DECL (c);
1512 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1513 goto do_private;
1514 else if (!is_variable_sized (decl))
1515 install_var_local (decl, ctx);
1516 break;
1518 case OMP_CLAUSE_SHARED:
1519 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1520 /* Ignore shared directives in teams construct. */
1521 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1522 break;
1523 gcc_assert (is_taskreg_ctx (ctx));
1524 decl = OMP_CLAUSE_DECL (c);
1525 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1526 || !is_variable_sized (decl));
1527 /* Global variables don't need to be copied,
1528 the receiver side will use them directly. */
1529 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1530 break;
1531 by_ref = use_pointer_for_field (decl, ctx);
1532 if (! TREE_READONLY (decl)
1533 || TREE_ADDRESSABLE (decl)
1534 || by_ref
1535 || is_reference (decl))
1537 install_var_field (decl, by_ref, 3, ctx);
1538 install_var_local (decl, ctx);
1539 break;
1541 /* We don't need to copy const scalar vars back. */
1542 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1543 goto do_private;
1545 case OMP_CLAUSE_LASTPRIVATE:
1546 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1547 /* Let the corresponding firstprivate clause create
1548 the variable. */
1549 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1550 break;
1551 /* FALLTHRU */
1553 case OMP_CLAUSE_FIRSTPRIVATE:
1554 case OMP_CLAUSE_REDUCTION:
1555 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1557 sorry ("clause not supported yet");
1558 break;
1560 case OMP_CLAUSE_LINEAR:
1561 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1562 decl = OMP_CLAUSE_DECL (c);
1563 do_private:
1564 if (is_variable_sized (decl))
1566 if (is_task_ctx (ctx))
1567 install_var_field (decl, false, 1, ctx);
1568 break;
1570 else if (is_taskreg_ctx (ctx))
1572 bool global
1573 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1574 by_ref = use_pointer_for_field (decl, NULL);
1576 if (is_task_ctx (ctx)
1577 && (global || by_ref || is_reference (decl)))
1579 install_var_field (decl, false, 1, ctx);
1580 if (!global)
1581 install_var_field (decl, by_ref, 2, ctx);
1583 else if (!global)
1584 install_var_field (decl, by_ref, 3, ctx);
1586 install_var_local (decl, ctx);
1587 break;
1589 case OMP_CLAUSE__LOOPTEMP_:
1590 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1591 gcc_assert (is_parallel_ctx (ctx));
1592 decl = OMP_CLAUSE_DECL (c);
1593 install_var_field (decl, false, 3, ctx);
1594 install_var_local (decl, ctx);
1595 break;
1597 case OMP_CLAUSE_COPYPRIVATE:
1598 case OMP_CLAUSE_COPYIN:
1599 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1600 decl = OMP_CLAUSE_DECL (c);
1601 by_ref = use_pointer_for_field (decl, NULL);
1602 install_var_field (decl, by_ref, 3, ctx);
1603 break;
1605 case OMP_CLAUSE_DEFAULT:
1606 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1607 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1608 break;
1610 case OMP_CLAUSE_IF:
1611 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1613 sorry ("clause not supported yet");
1614 break;
1616 case OMP_CLAUSE_FINAL:
1617 case OMP_CLAUSE_NUM_THREADS:
1618 case OMP_CLAUSE_NUM_TEAMS:
1619 case OMP_CLAUSE_THREAD_LIMIT:
1620 case OMP_CLAUSE_DEVICE:
1621 case OMP_CLAUSE_SCHEDULE:
1622 case OMP_CLAUSE_DIST_SCHEDULE:
1623 case OMP_CLAUSE_DEPEND:
1624 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1625 case OMP_CLAUSE_NUM_GANGS:
1626 case OMP_CLAUSE_NUM_WORKERS:
1627 case OMP_CLAUSE_VECTOR_LENGTH:
1628 if (ctx->outer)
1629 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1630 break;
1632 case OMP_CLAUSE_TO:
1633 case OMP_CLAUSE_FROM:
1634 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1635 case OMP_CLAUSE_MAP:
1636 switch (OMP_CLAUSE_CODE (c))
1638 case OMP_CLAUSE_TO:
1639 case OMP_CLAUSE_FROM:
1640 /* The to and from clauses are only ever seen with OpenMP target
1641 update constructs. */
1642 gcc_assert (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1643 && (gimple_omp_target_kind (ctx->stmt)
1644 == GF_OMP_TARGET_KIND_UPDATE));
1645 break;
1646 case OMP_CLAUSE_MAP:
1647 /* The map clause is never seen with OpenMP target update
1648 constructs. */
1649 gcc_assert (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
1650 || (gimple_omp_target_kind (ctx->stmt)
1651 != GF_OMP_TARGET_KIND_UPDATE));
1652 break;
1653 default:
1654 gcc_unreachable ();
1656 if (ctx->outer)
1657 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1658 decl = OMP_CLAUSE_DECL (c);
1659 /* Global variables with "omp declare target" attribute
1660 don't need to be copied, the receiver side will use them
1661 directly. */
1662 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1663 && DECL_P (decl)
1664 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1665 && lookup_attribute ("omp declare target",
1666 DECL_ATTRIBUTES (decl)))
1668 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1669 break;
1671 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1672 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1674 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1675 target regions that are not offloaded; there is nothing to map for
1676 those. */
1677 if (!is_gimple_omp_offloaded (ctx->stmt)
1678 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1679 break;
1681 if (DECL_P (decl))
1683 if (DECL_SIZE (decl)
1684 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1686 tree decl2 = DECL_VALUE_EXPR (decl);
1687 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1688 decl2 = TREE_OPERAND (decl2, 0);
1689 gcc_assert (DECL_P (decl2));
1690 install_var_field (decl2, true, 3, ctx);
1691 install_var_local (decl2, ctx);
1692 install_var_local (decl, ctx);
1694 else
1696 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1697 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1698 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1699 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1700 install_var_field (decl, true, 7, ctx);
1701 else
1702 install_var_field (decl, true, 3, ctx);
1703 if (is_gimple_omp_offloaded (ctx->stmt))
1704 install_var_local (decl, ctx);
1707 else
1709 tree base = get_base_address (decl);
1710 tree nc = OMP_CLAUSE_CHAIN (c);
1711 if (DECL_P (base)
1712 && nc != NULL_TREE
1713 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1714 && OMP_CLAUSE_DECL (nc) == base
1715 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1716 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1718 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1719 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1721 else
1723 gcc_assert (!splay_tree_lookup (ctx->field_map,
1724 (splay_tree_key) decl));
1725 tree field
1726 = build_decl (OMP_CLAUSE_LOCATION (c),
1727 FIELD_DECL, NULL_TREE, ptr_type_node);
1728 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1729 insert_field_into_struct (ctx->record_type, field);
1730 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1731 (splay_tree_value) field);
1734 break;
1736 case OMP_CLAUSE_NOWAIT:
1737 case OMP_CLAUSE_ORDERED:
1738 case OMP_CLAUSE_COLLAPSE:
1739 case OMP_CLAUSE_UNTIED:
1740 case OMP_CLAUSE_MERGEABLE:
1741 case OMP_CLAUSE_PROC_BIND:
1742 case OMP_CLAUSE_SAFELEN:
1743 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1744 break;
1746 case OMP_CLAUSE_ALIGNED:
1747 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1748 decl = OMP_CLAUSE_DECL (c);
1749 if (is_global_var (decl)
1750 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1751 install_var_local (decl, ctx);
1752 break;
1754 case OMP_CLAUSE_HOST:
1755 case OMP_CLAUSE_OACC_DEVICE:
1756 case OMP_CLAUSE_DEVICE_RESIDENT:
1757 case OMP_CLAUSE_USE_DEVICE:
1758 case OMP_CLAUSE_GANG:
1759 case OMP_CLAUSE_ASYNC:
1760 case OMP_CLAUSE_WAIT:
1761 case OMP_NO_CLAUSE_CACHE:
1762 case OMP_CLAUSE_INDEPENDENT:
1763 case OMP_CLAUSE_WORKER:
1764 case OMP_CLAUSE_VECTOR:
1765 sorry ("Clause not supported yet");
1766 break;
1768 default:
1769 gcc_unreachable ();
1773 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1775 switch (OMP_CLAUSE_CODE (c))
1777 case OMP_CLAUSE_LASTPRIVATE:
1778 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1779 /* Let the corresponding firstprivate clause create
1780 the variable. */
1781 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1782 scan_array_reductions = true;
1783 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1784 break;
1785 /* FALLTHRU */
1787 case OMP_CLAUSE_PRIVATE:
1788 case OMP_CLAUSE_FIRSTPRIVATE:
1789 case OMP_CLAUSE_REDUCTION:
1790 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1792 sorry ("clause not supported yet");
1793 break;
1795 case OMP_CLAUSE_LINEAR:
1796 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1797 decl = OMP_CLAUSE_DECL (c);
1798 if (is_variable_sized (decl))
1799 install_var_local (decl, ctx);
1800 fixup_remapped_decl (decl, ctx,
1801 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1802 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1803 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1804 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1805 scan_array_reductions = true;
1806 break;
1808 case OMP_CLAUSE_SHARED:
1809 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1810 /* Ignore shared directives in teams construct. */
1811 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1812 break;
1813 decl = OMP_CLAUSE_DECL (c);
1814 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1815 fixup_remapped_decl (decl, ctx, false);
1816 break;
1818 case OMP_CLAUSE_MAP:
1819 /* The map clause is never seen with OpenMP target update
1820 constructs. */
1821 gcc_assert (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
1822 || (gimple_omp_target_kind (ctx->stmt)
1823 != GF_OMP_TARGET_KIND_UPDATE));
1824 if (!is_gimple_omp_offloaded (ctx->stmt))
1825 break;
1826 decl = OMP_CLAUSE_DECL (c);
1827 if (DECL_P (decl)
1828 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1829 && lookup_attribute ("omp declare target",
1830 DECL_ATTRIBUTES (decl)))
1832 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1833 break;
1835 if (DECL_P (decl))
1837 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1838 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1839 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1841 tree new_decl = lookup_decl (decl, ctx);
1842 TREE_TYPE (new_decl)
1843 = remap_type (TREE_TYPE (decl), &ctx->cb);
1845 else if (DECL_SIZE (decl)
1846 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1848 tree decl2 = DECL_VALUE_EXPR (decl);
1849 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1850 decl2 = TREE_OPERAND (decl2, 0);
1851 gcc_assert (DECL_P (decl2));
1852 fixup_remapped_decl (decl2, ctx, false);
1853 fixup_remapped_decl (decl, ctx, true);
1855 else
1856 fixup_remapped_decl (decl, ctx, false);
1858 break;
1860 case OMP_CLAUSE_IF:
1861 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1863 sorry ("clause not supported yet");
1864 break;
1866 case OMP_CLAUSE_COPYPRIVATE:
1867 case OMP_CLAUSE_COPYIN:
1868 case OMP_CLAUSE_DEFAULT:
1869 case OMP_CLAUSE_NUM_THREADS:
1870 case OMP_CLAUSE_NUM_TEAMS:
1871 case OMP_CLAUSE_THREAD_LIMIT:
1872 case OMP_CLAUSE_DEVICE:
1873 case OMP_CLAUSE_SCHEDULE:
1874 case OMP_CLAUSE_DIST_SCHEDULE:
1875 case OMP_CLAUSE_NOWAIT:
1876 case OMP_CLAUSE_ORDERED:
1877 case OMP_CLAUSE_COLLAPSE:
1878 case OMP_CLAUSE_UNTIED:
1879 case OMP_CLAUSE_FINAL:
1880 case OMP_CLAUSE_MERGEABLE:
1881 case OMP_CLAUSE_PROC_BIND:
1882 case OMP_CLAUSE_SAFELEN:
1883 case OMP_CLAUSE_ALIGNED:
1884 case OMP_CLAUSE_DEPEND:
1885 case OMP_CLAUSE__LOOPTEMP_:
1886 case OMP_CLAUSE_TO:
1887 case OMP_CLAUSE_FROM:
1888 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1889 case OMP_CLAUSE_NUM_GANGS:
1890 case OMP_CLAUSE_NUM_WORKERS:
1891 case OMP_CLAUSE_VECTOR_LENGTH:
1892 break;
1894 case OMP_CLAUSE_HOST:
1895 case OMP_CLAUSE_OACC_DEVICE:
1896 case OMP_CLAUSE_DEVICE_RESIDENT:
1897 case OMP_CLAUSE_USE_DEVICE:
1898 case OMP_CLAUSE_GANG:
1899 case OMP_CLAUSE_ASYNC:
1900 case OMP_CLAUSE_WAIT:
1901 case OMP_NO_CLAUSE_CACHE:
1902 case OMP_CLAUSE_INDEPENDENT:
1903 case OMP_CLAUSE_WORKER:
1904 case OMP_CLAUSE_VECTOR:
1905 sorry ("Clause not supported yet");
1906 break;
1908 default:
1909 gcc_unreachable ();
1913 if (scan_array_reductions)
1915 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1916 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1917 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1918 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1920 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1921 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1923 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1924 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1925 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1929 /* Create a new name for omp child function. Returns an identifier. */
1931 static tree
1932 create_omp_child_function_name (bool task_copy)
1934 return (clone_function_name (current_function_decl,
1935 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1938 /* Build a decl for the omp child function. It'll not contain a body
1939 yet, just the bare decl. */
1941 static void
1942 create_omp_child_function (omp_context *ctx, bool task_copy)
1944 tree decl, type, name, t;
1946 name = create_omp_child_function_name (task_copy);
1947 if (task_copy)
1948 type = build_function_type_list (void_type_node, ptr_type_node,
1949 ptr_type_node, NULL_TREE);
1950 else
1951 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1953 decl = build_decl (gimple_location (ctx->stmt),
1954 FUNCTION_DECL, name, type);
1956 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt)
1957 || !task_copy);
1958 if (!task_copy)
1959 ctx->cb.dst_fn = decl;
1960 else
1961 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1963 TREE_STATIC (decl) = 1;
1964 TREE_USED (decl) = 1;
1965 DECL_ARTIFICIAL (decl) = 1;
1966 DECL_NAMELESS (decl) = 1;
1967 DECL_IGNORED_P (decl) = 0;
1968 TREE_PUBLIC (decl) = 0;
1969 DECL_UNINLINABLE (decl) = 1;
1970 DECL_EXTERNAL (decl) = 0;
1971 DECL_CONTEXT (decl) = NULL_TREE;
1972 DECL_INITIAL (decl) = make_node (BLOCK);
1973 bool target_p = false;
1974 if (lookup_attribute ("omp declare target",
1975 DECL_ATTRIBUTES (current_function_decl)))
1976 target_p = true;
1977 else
1979 omp_context *octx;
1980 for (octx = ctx; octx; octx = octx->outer)
1981 if (is_gimple_omp_offloaded (octx->stmt))
1983 target_p = true;
1984 break;
1987 if (target_p)
1988 DECL_ATTRIBUTES (decl)
1989 = tree_cons (get_identifier ("omp declare target"),
1990 NULL_TREE, DECL_ATTRIBUTES (decl));
1992 t = build_decl (DECL_SOURCE_LOCATION (decl),
1993 RESULT_DECL, NULL_TREE, void_type_node);
1994 DECL_ARTIFICIAL (t) = 1;
1995 DECL_IGNORED_P (t) = 1;
1996 DECL_CONTEXT (t) = decl;
1997 DECL_RESULT (decl) = t;
1999 t = build_decl (DECL_SOURCE_LOCATION (decl),
2000 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
2001 DECL_ARTIFICIAL (t) = 1;
2002 DECL_NAMELESS (t) = 1;
2003 DECL_ARG_TYPE (t) = ptr_type_node;
2004 DECL_CONTEXT (t) = current_function_decl;
2005 TREE_USED (t) = 1;
2006 DECL_ARGUMENTS (decl) = t;
2007 if (!task_copy)
2008 ctx->receiver_decl = t;
2009 else
2011 t = build_decl (DECL_SOURCE_LOCATION (decl),
2012 PARM_DECL, get_identifier (".omp_data_o"),
2013 ptr_type_node);
2014 DECL_ARTIFICIAL (t) = 1;
2015 DECL_NAMELESS (t) = 1;
2016 DECL_ARG_TYPE (t) = ptr_type_node;
2017 DECL_CONTEXT (t) = current_function_decl;
2018 TREE_USED (t) = 1;
2019 TREE_ADDRESSABLE (t) = 1;
2020 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2021 DECL_ARGUMENTS (decl) = t;
2024 /* Allocate memory for the function structure. The call to
2025 allocate_struct_function clobbers CFUN, so we need to restore
2026 it afterward. */
2027 push_struct_function (decl);
2028 cfun->function_end_locus = gimple_location (ctx->stmt);
2029 pop_cfun ();
2032 /* Callback for walk_gimple_seq. Check if combined parallel
2033 contains gimple_omp_for_combined_into_p OMP_FOR. */
2035 static tree
2036 find_combined_for (gimple_stmt_iterator *gsi_p,
2037 bool *handled_ops_p,
2038 struct walk_stmt_info *wi)
2040 gimple stmt = gsi_stmt (*gsi_p);
2042 *handled_ops_p = true;
2043 switch (gimple_code (stmt))
2045 WALK_SUBSTMTS;
2047 case GIMPLE_OMP_FOR:
2048 if (gimple_omp_for_combined_into_p (stmt)
2049 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2051 wi->info = stmt;
2052 return integer_zero_node;
2054 break;
2055 default:
2056 break;
2058 return NULL;
2061 /* Scan an OpenACC offload directive. */
2063 static void
2064 scan_oacc_offload (gimple stmt, omp_context *outer_ctx)
2066 omp_context *ctx;
2067 tree name;
2068 void (*gimple_omp_set_child_fn) (gimple, tree);
2069 tree (*gimple_omp_clauses) (const_gimple);
2070 switch (gimple_code (stmt))
2072 case GIMPLE_OACC_KERNELS:
2073 gimple_omp_set_child_fn = gimple_oacc_kernels_set_child_fn;
2074 gimple_omp_clauses = gimple_oacc_kernels_clauses;
2075 break;
2076 case GIMPLE_OACC_PARALLEL:
2077 gimple_omp_set_child_fn = gimple_oacc_parallel_set_child_fn;
2078 gimple_omp_clauses = gimple_oacc_parallel_clauses;
2079 break;
2080 default:
2081 gcc_unreachable ();
2084 gcc_assert (taskreg_nesting_level == 0);
2085 gcc_assert (target_nesting_level == 0);
2087 ctx = new_omp_context (stmt, outer_ctx);
2088 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2089 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2090 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2091 name = create_tmp_var_name (".omp_data_t");
2092 name = build_decl (gimple_location (stmt),
2093 TYPE_DECL, name, ctx->record_type);
2094 DECL_ARTIFICIAL (name) = 1;
2095 DECL_NAMELESS (name) = 1;
2096 TYPE_NAME (ctx->record_type) = name;
2097 create_omp_child_function (ctx, false);
2099 gimple_omp_set_child_fn (stmt, ctx->cb.dst_fn);
2101 scan_sharing_clauses (gimple_omp_clauses (stmt), ctx);
2102 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2104 if (TYPE_FIELDS (ctx->record_type) == NULL)
2105 ctx->record_type = ctx->receiver_decl = NULL;
2106 else
2108 TYPE_FIELDS (ctx->record_type)
2109 = nreverse (TYPE_FIELDS (ctx->record_type));
2110 #ifdef ENABLE_CHECKING
2111 tree field;
2112 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2113 for (field = TYPE_FIELDS (ctx->record_type);
2114 field;
2115 field = DECL_CHAIN (field))
2116 gcc_assert (DECL_ALIGN (field) == align);
2117 #endif
2118 layout_type (ctx->record_type);
2119 fixup_child_record_type (ctx);
2123 /* Scan an OpenMP parallel directive. */
2125 static void
2126 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2128 omp_context *ctx;
2129 tree name;
2130 gimple stmt = gsi_stmt (*gsi);
2132 /* Ignore parallel directives with empty bodies, unless there
2133 are copyin clauses. */
2134 if (optimize > 0
2135 && empty_body_p (gimple_omp_body (stmt))
2136 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2137 OMP_CLAUSE_COPYIN) == NULL)
2139 gsi_replace (gsi, gimple_build_nop (), false);
2140 return;
2143 if (gimple_omp_parallel_combined_p (stmt))
2145 gimple for_stmt;
2146 struct walk_stmt_info wi;
2148 memset (&wi, 0, sizeof (wi));
2149 wi.val_only = true;
2150 walk_gimple_seq (gimple_omp_body (stmt),
2151 find_combined_for, NULL, &wi);
2152 for_stmt = (gimple) wi.info;
2153 if (for_stmt)
2155 struct omp_for_data fd;
2156 extract_omp_for_data (for_stmt, &fd, NULL);
2157 /* We need two temporaries with fd.loop.v type (istart/iend)
2158 and then (fd.collapse - 1) temporaries with the same
2159 type for count2 ... countN-1 vars if not constant. */
2160 size_t count = 2, i;
2161 tree type = fd.iter_type;
2162 if (fd.collapse > 1
2163 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2164 count += fd.collapse - 1;
2165 for (i = 0; i < count; i++)
2167 tree temp = create_tmp_var (type, NULL);
2168 tree c = build_omp_clause (UNKNOWN_LOCATION,
2169 OMP_CLAUSE__LOOPTEMP_);
2170 OMP_CLAUSE_DECL (c) = temp;
2171 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2172 gimple_omp_parallel_set_clauses (stmt, c);
2177 ctx = new_omp_context (stmt, outer_ctx);
2178 if (taskreg_nesting_level > 1)
2179 ctx->is_nested = true;
2180 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2181 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2182 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2183 name = create_tmp_var_name (".omp_data_s");
2184 name = build_decl (gimple_location (stmt),
2185 TYPE_DECL, name, ctx->record_type);
2186 DECL_ARTIFICIAL (name) = 1;
2187 DECL_NAMELESS (name) = 1;
2188 TYPE_NAME (ctx->record_type) = name;
2189 create_omp_child_function (ctx, false);
2190 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2192 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2193 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2195 if (TYPE_FIELDS (ctx->record_type) == NULL)
2196 ctx->record_type = ctx->receiver_decl = NULL;
2197 else
2199 layout_type (ctx->record_type);
2200 fixup_child_record_type (ctx);
2204 /* Scan an OpenMP task directive. */
2206 static void
2207 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2209 omp_context *ctx;
2210 tree name, t;
2211 gimple stmt = gsi_stmt (*gsi);
2212 location_t loc = gimple_location (stmt);
2214 /* Ignore task directives with empty bodies. */
2215 if (optimize > 0
2216 && empty_body_p (gimple_omp_body (stmt)))
2218 gsi_replace (gsi, gimple_build_nop (), false);
2219 return;
2222 ctx = new_omp_context (stmt, outer_ctx);
2223 if (taskreg_nesting_level > 1)
2224 ctx->is_nested = true;
2225 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2226 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2227 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2228 name = create_tmp_var_name (".omp_data_s");
2229 name = build_decl (gimple_location (stmt),
2230 TYPE_DECL, name, ctx->record_type);
2231 DECL_ARTIFICIAL (name) = 1;
2232 DECL_NAMELESS (name) = 1;
2233 TYPE_NAME (ctx->record_type) = name;
2234 create_omp_child_function (ctx, false);
2235 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2237 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2239 if (ctx->srecord_type)
2241 name = create_tmp_var_name (".omp_data_a");
2242 name = build_decl (gimple_location (stmt),
2243 TYPE_DECL, name, ctx->srecord_type);
2244 DECL_ARTIFICIAL (name) = 1;
2245 DECL_NAMELESS (name) = 1;
2246 TYPE_NAME (ctx->srecord_type) = name;
2247 create_omp_child_function (ctx, true);
2250 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2252 if (TYPE_FIELDS (ctx->record_type) == NULL)
2254 ctx->record_type = ctx->receiver_decl = NULL;
2255 t = build_int_cst (long_integer_type_node, 0);
2256 gimple_omp_task_set_arg_size (stmt, t);
2257 t = build_int_cst (long_integer_type_node, 1);
2258 gimple_omp_task_set_arg_align (stmt, t);
2260 else
2262 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2263 /* Move VLA fields to the end. */
2264 p = &TYPE_FIELDS (ctx->record_type);
2265 while (*p)
2266 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2267 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2269 *q = *p;
2270 *p = TREE_CHAIN (*p);
2271 TREE_CHAIN (*q) = NULL_TREE;
2272 q = &TREE_CHAIN (*q);
2274 else
2275 p = &DECL_CHAIN (*p);
2276 *p = vla_fields;
2277 layout_type (ctx->record_type);
2278 fixup_child_record_type (ctx);
2279 if (ctx->srecord_type)
2280 layout_type (ctx->srecord_type);
2281 t = fold_convert_loc (loc, long_integer_type_node,
2282 TYPE_SIZE_UNIT (ctx->record_type));
2283 gimple_omp_task_set_arg_size (stmt, t);
2284 t = build_int_cst (long_integer_type_node,
2285 TYPE_ALIGN_UNIT (ctx->record_type));
2286 gimple_omp_task_set_arg_align (stmt, t);
2291 /* Scan an OpenMP loop directive. */
2293 static void
2294 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2296 omp_context *ctx;
2297 size_t i;
2299 ctx = new_omp_context (stmt, outer_ctx);
2301 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2303 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2304 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2306 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2307 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2308 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2309 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2311 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2314 /* Scan an OpenMP sections directive. */
2316 static void
2317 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2319 omp_context *ctx;
2321 ctx = new_omp_context (stmt, outer_ctx);
2322 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2323 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2326 /* Scan an OpenMP single directive. */
2328 static void
2329 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2331 omp_context *ctx;
2332 tree name;
2334 ctx = new_omp_context (stmt, outer_ctx);
2335 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2336 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2337 name = create_tmp_var_name (".omp_copy_s");
2338 name = build_decl (gimple_location (stmt),
2339 TYPE_DECL, name, ctx->record_type);
2340 TYPE_NAME (ctx->record_type) = name;
2342 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2343 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2345 if (TYPE_FIELDS (ctx->record_type) == NULL)
2346 ctx->record_type = NULL;
2347 else
2348 layout_type (ctx->record_type);
2351 /* Scan a GIMPLE_OMP_TARGET. */
2353 static void
2354 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2356 omp_context *ctx;
2357 tree name;
2358 int kind = gimple_omp_target_kind (stmt);
2360 if (kind == GF_OMP_TARGET_KIND_OACC_DATA)
2362 gcc_assert (taskreg_nesting_level == 0);
2363 gcc_assert (target_nesting_level == 0);
2366 ctx = new_omp_context (stmt, outer_ctx);
2367 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2368 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2369 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2370 name = create_tmp_var_name (".omp_data_t");
2371 name = build_decl (gimple_location (stmt),
2372 TYPE_DECL, name, ctx->record_type);
2373 DECL_ARTIFICIAL (name) = 1;
2374 DECL_NAMELESS (name) = 1;
2375 TYPE_NAME (ctx->record_type) = name;
2376 if (kind == GF_OMP_TARGET_KIND_REGION)
2378 create_omp_child_function (ctx, false);
2379 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2382 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2383 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2385 if (TYPE_FIELDS (ctx->record_type) == NULL)
2386 ctx->record_type = ctx->receiver_decl = NULL;
2387 else
2389 TYPE_FIELDS (ctx->record_type)
2390 = nreverse (TYPE_FIELDS (ctx->record_type));
2391 #ifdef ENABLE_CHECKING
2392 tree field;
2393 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2394 for (field = TYPE_FIELDS (ctx->record_type);
2395 field;
2396 field = DECL_CHAIN (field))
2397 gcc_assert (DECL_ALIGN (field) == align);
2398 #endif
2399 layout_type (ctx->record_type);
2400 if (kind == GF_OMP_TARGET_KIND_REGION)
2401 fixup_child_record_type (ctx);
2405 /* Scan an OpenMP teams directive. */
2407 static void
2408 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2410 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2411 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2412 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2415 /* Check OpenMP nesting restrictions. */
2416 static bool
2417 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2419 /* TODO: While the OpenACC specification does allow for certain kinds of
2420 nesting, we don't support many of these yet. */
2421 if (is_gimple_omp (stmt)
2422 && is_gimple_omp_oacc_specifically (stmt))
2424 /* No nesting of OpenACC STMT inside any OpenACC or OpenMP CTX different
2425 from an OpenACC data construct. */
2426 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2427 if (is_gimple_omp (ctx_->stmt)
2428 && !(gimple_code (ctx_->stmt) == GIMPLE_OMP_TARGET
2429 && (gimple_omp_target_kind (ctx_->stmt)
2430 == GF_OMP_TARGET_KIND_OACC_DATA)))
2432 error_at (gimple_location (stmt),
2433 "may not be nested");
2434 return false;
2437 else
2439 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP
2440 builtin) inside any OpenACC CTX. */
2441 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2442 if (is_gimple_omp (ctx_->stmt)
2443 && is_gimple_omp_oacc_specifically (ctx_->stmt))
2445 error_at (gimple_location (stmt),
2446 "may not be nested");
2447 return false;
2451 if (ctx != NULL)
2453 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2454 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2456 error_at (gimple_location (stmt),
2457 "OpenMP constructs may not be nested inside simd region");
2458 return false;
2460 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2462 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2463 || (gimple_omp_for_kind (stmt)
2464 != GF_OMP_FOR_KIND_DISTRIBUTE))
2465 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2467 error_at (gimple_location (stmt),
2468 "only distribute or parallel constructs are allowed to "
2469 "be closely nested inside teams construct");
2470 return false;
2474 switch (gimple_code (stmt))
2476 case GIMPLE_OMP_FOR:
2477 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_KIND_SIMD)
2478 return true;
2479 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2481 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2483 error_at (gimple_location (stmt),
2484 "distribute construct must be closely nested inside "
2485 "teams construct");
2486 return false;
2488 return true;
2490 /* FALLTHRU */
2491 case GIMPLE_CALL:
2492 if (is_gimple_call (stmt)
2493 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2494 == BUILT_IN_GOMP_CANCEL
2495 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2496 == BUILT_IN_GOMP_CANCELLATION_POINT))
2498 const char *bad = NULL;
2499 const char *kind = NULL;
2500 if (ctx == NULL)
2502 error_at (gimple_location (stmt), "orphaned %qs construct",
2503 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2504 == BUILT_IN_GOMP_CANCEL
2505 ? "#pragma omp cancel"
2506 : "#pragma omp cancellation point");
2507 return false;
2509 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2510 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2511 : 0)
2513 case 1:
2514 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2515 bad = "#pragma omp parallel";
2516 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2517 == BUILT_IN_GOMP_CANCEL
2518 && !integer_zerop (gimple_call_arg (stmt, 1)))
2519 ctx->cancellable = true;
2520 kind = "parallel";
2521 break;
2522 case 2:
2523 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2524 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2525 bad = "#pragma omp for";
2526 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2527 == BUILT_IN_GOMP_CANCEL
2528 && !integer_zerop (gimple_call_arg (stmt, 1)))
2530 ctx->cancellable = true;
2531 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2532 OMP_CLAUSE_NOWAIT))
2533 warning_at (gimple_location (stmt), 0,
2534 "%<#pragma omp cancel for%> inside "
2535 "%<nowait%> for construct");
2536 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2537 OMP_CLAUSE_ORDERED))
2538 warning_at (gimple_location (stmt), 0,
2539 "%<#pragma omp cancel for%> inside "
2540 "%<ordered%> for construct");
2542 kind = "for";
2543 break;
2544 case 4:
2545 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2546 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2547 bad = "#pragma omp sections";
2548 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2549 == BUILT_IN_GOMP_CANCEL
2550 && !integer_zerop (gimple_call_arg (stmt, 1)))
2552 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2554 ctx->cancellable = true;
2555 if (find_omp_clause (gimple_omp_sections_clauses
2556 (ctx->stmt),
2557 OMP_CLAUSE_NOWAIT))
2558 warning_at (gimple_location (stmt), 0,
2559 "%<#pragma omp cancel sections%> inside "
2560 "%<nowait%> sections construct");
2562 else
2564 gcc_assert (ctx->outer
2565 && gimple_code (ctx->outer->stmt)
2566 == GIMPLE_OMP_SECTIONS);
2567 ctx->outer->cancellable = true;
2568 if (find_omp_clause (gimple_omp_sections_clauses
2569 (ctx->outer->stmt),
2570 OMP_CLAUSE_NOWAIT))
2571 warning_at (gimple_location (stmt), 0,
2572 "%<#pragma omp cancel sections%> inside "
2573 "%<nowait%> sections construct");
2576 kind = "sections";
2577 break;
2578 case 8:
2579 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2580 bad = "#pragma omp task";
2581 else
2582 ctx->cancellable = true;
2583 kind = "taskgroup";
2584 break;
2585 default:
2586 error_at (gimple_location (stmt), "invalid arguments");
2587 return false;
2589 if (bad)
2591 error_at (gimple_location (stmt),
2592 "%<%s %s%> construct not closely nested inside of %qs",
2593 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2594 == BUILT_IN_GOMP_CANCEL
2595 ? "#pragma omp cancel"
2596 : "#pragma omp cancellation point", kind, bad);
2597 return false;
2600 /* FALLTHRU */
2601 case GIMPLE_OMP_SECTIONS:
2602 case GIMPLE_OMP_SINGLE:
2603 for (; ctx != NULL; ctx = ctx->outer)
2604 switch (gimple_code (ctx->stmt))
2606 case GIMPLE_OMP_FOR:
2607 case GIMPLE_OMP_SECTIONS:
2608 case GIMPLE_OMP_SINGLE:
2609 case GIMPLE_OMP_ORDERED:
2610 case GIMPLE_OMP_MASTER:
2611 case GIMPLE_OMP_TASK:
2612 case GIMPLE_OMP_CRITICAL:
2613 if (is_gimple_call (stmt))
2615 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2616 != BUILT_IN_GOMP_BARRIER)
2617 return true;
2618 error_at (gimple_location (stmt),
2619 "barrier region may not be closely nested inside "
2620 "of work-sharing, critical, ordered, master or "
2621 "explicit task region");
2622 return false;
2624 error_at (gimple_location (stmt),
2625 "work-sharing region may not be closely nested inside "
2626 "of work-sharing, critical, ordered, master or explicit "
2627 "task region");
2628 return false;
2629 case GIMPLE_OMP_PARALLEL:
2630 return true;
2631 default:
2632 break;
2634 break;
2635 case GIMPLE_OMP_MASTER:
2636 for (; ctx != NULL; ctx = ctx->outer)
2637 switch (gimple_code (ctx->stmt))
2639 case GIMPLE_OMP_FOR:
2640 case GIMPLE_OMP_SECTIONS:
2641 case GIMPLE_OMP_SINGLE:
2642 case GIMPLE_OMP_TASK:
2643 error_at (gimple_location (stmt),
2644 "master region may not be closely nested inside "
2645 "of work-sharing or explicit task region");
2646 return false;
2647 case GIMPLE_OMP_PARALLEL:
2648 return true;
2649 default:
2650 break;
2652 break;
2653 case GIMPLE_OMP_ORDERED:
2654 for (; ctx != NULL; ctx = ctx->outer)
2655 switch (gimple_code (ctx->stmt))
2657 case GIMPLE_OMP_CRITICAL:
2658 case GIMPLE_OMP_TASK:
2659 error_at (gimple_location (stmt),
2660 "ordered region may not be closely nested inside "
2661 "of critical or explicit task region");
2662 return false;
2663 case GIMPLE_OMP_FOR:
2664 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2665 OMP_CLAUSE_ORDERED) == NULL)
2667 error_at (gimple_location (stmt),
2668 "ordered region must be closely nested inside "
2669 "a loop region with an ordered clause");
2670 return false;
2672 return true;
2673 case GIMPLE_OMP_PARALLEL:
2674 error_at (gimple_location (stmt),
2675 "ordered region must be closely nested inside "
2676 "a loop region with an ordered clause");
2677 return false;
2678 default:
2679 break;
2681 break;
2682 case GIMPLE_OMP_CRITICAL:
2683 for (; ctx != NULL; ctx = ctx->outer)
2684 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2685 && (gimple_omp_critical_name (stmt)
2686 == gimple_omp_critical_name (ctx->stmt)))
2688 error_at (gimple_location (stmt),
2689 "critical region may not be nested inside a critical "
2690 "region with the same name");
2691 return false;
2693 break;
2694 case GIMPLE_OMP_TEAMS:
2695 if (ctx == NULL
2696 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2697 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2699 error_at (gimple_location (stmt),
2700 "teams construct not closely nested inside of target "
2701 "region");
2702 return false;
2704 break;
2705 default:
2706 break;
2708 return true;
2712 /* Helper function scan_omp.
2714 Callback for walk_tree or operators in walk_gimple_stmt used to
2715 scan for OpenMP directives in TP. */
2717 static tree
2718 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2720 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2721 omp_context *ctx = (omp_context *) wi->info;
2722 tree t = *tp;
2724 switch (TREE_CODE (t))
2726 case VAR_DECL:
2727 case PARM_DECL:
2728 case LABEL_DECL:
2729 case RESULT_DECL:
2730 if (ctx)
2731 *tp = remap_decl (t, &ctx->cb);
2732 break;
2734 default:
2735 if (ctx && TYPE_P (t))
2736 *tp = remap_type (t, &ctx->cb);
2737 else if (!DECL_P (t))
2739 *walk_subtrees = 1;
2740 if (ctx)
2742 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2743 if (tem != TREE_TYPE (t))
2745 if (TREE_CODE (t) == INTEGER_CST)
2746 *tp = build_int_cst_wide (tem,
2747 TREE_INT_CST_LOW (t),
2748 TREE_INT_CST_HIGH (t));
2749 else
2750 TREE_TYPE (t) = tem;
2754 break;
2757 return NULL_TREE;
2760 /* Return true if FNDECL is a setjmp or a longjmp. */
2762 static bool
2763 setjmp_or_longjmp_p (const_tree fndecl)
2765 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2766 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2767 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2768 return true;
2770 tree declname = DECL_NAME (fndecl);
2771 if (!declname)
2772 return false;
2773 const char *name = IDENTIFIER_POINTER (declname);
2774 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2778 /* Helper function for scan_omp.
2780 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2781 the current statement in GSI. */
2783 static tree
2784 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2785 struct walk_stmt_info *wi)
2787 gimple stmt = gsi_stmt (*gsi);
2788 omp_context *ctx = (omp_context *) wi->info;
2790 if (gimple_has_location (stmt))
2791 input_location = gimple_location (stmt);
2793 /* Check the OpenMP nesting restrictions. */
2794 bool remove = false;
2795 if (is_gimple_omp (stmt))
2796 remove = !check_omp_nesting_restrictions (stmt, ctx);
2797 else if (is_gimple_call (stmt))
2799 tree fndecl = gimple_call_fndecl (stmt);
2800 if (fndecl)
2802 if (setjmp_or_longjmp_p (fndecl)
2803 && ctx
2804 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2805 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2807 remove = true;
2808 error_at (gimple_location (stmt),
2809 "setjmp/longjmp inside simd construct");
2811 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2812 switch (DECL_FUNCTION_CODE (fndecl))
2814 case BUILT_IN_GOMP_BARRIER:
2815 case BUILT_IN_GOMP_CANCEL:
2816 case BUILT_IN_GOMP_CANCELLATION_POINT:
2817 case BUILT_IN_GOMP_TASKYIELD:
2818 case BUILT_IN_GOMP_TASKWAIT:
2819 case BUILT_IN_GOMP_TASKGROUP_START:
2820 case BUILT_IN_GOMP_TASKGROUP_END:
2821 remove = !check_omp_nesting_restrictions (stmt, ctx);
2822 break;
2823 default:
2824 break;
2828 if (remove)
2830 stmt = gimple_build_nop ();
2831 gsi_replace (gsi, stmt, false);
2834 *handled_ops_p = true;
2836 switch (gimple_code (stmt))
2838 case GIMPLE_OACC_KERNELS:
2839 case GIMPLE_OACC_PARALLEL:
2840 scan_oacc_offload (stmt, ctx);
2841 break;
2843 case GIMPLE_OMP_PARALLEL:
2844 taskreg_nesting_level++;
2845 scan_omp_parallel (gsi, ctx);
2846 taskreg_nesting_level--;
2847 break;
2849 case GIMPLE_OMP_TASK:
2850 taskreg_nesting_level++;
2851 scan_omp_task (gsi, ctx);
2852 taskreg_nesting_level--;
2853 break;
2855 case GIMPLE_OMP_FOR:
2856 scan_omp_for (stmt, ctx);
2857 break;
2859 case GIMPLE_OMP_SECTIONS:
2860 scan_omp_sections (stmt, ctx);
2861 break;
2863 case GIMPLE_OMP_SINGLE:
2864 scan_omp_single (stmt, ctx);
2865 break;
2867 case GIMPLE_OMP_SECTION:
2868 case GIMPLE_OMP_MASTER:
2869 case GIMPLE_OMP_TASKGROUP:
2870 case GIMPLE_OMP_ORDERED:
2871 case GIMPLE_OMP_CRITICAL:
2872 ctx = new_omp_context (stmt, ctx);
2873 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2874 break;
2876 case GIMPLE_OMP_TARGET:
2877 scan_omp_target (stmt, ctx);
2878 break;
2880 case GIMPLE_OMP_TEAMS:
2881 scan_omp_teams (stmt, ctx);
2882 break;
2884 case GIMPLE_BIND:
2886 tree var;
2888 *handled_ops_p = false;
2889 if (ctx)
2890 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2891 insert_decl_map (&ctx->cb, var, var);
2893 break;
2894 default:
2895 *handled_ops_p = false;
2896 break;
2899 return NULL_TREE;
2903 /* Scan all the statements starting at the current statement. CTX
2904 contains context information about the OpenMP directives and
2905 clauses found during the scan. */
2907 static void
2908 scan_omp (gimple_seq *body_p, omp_context *ctx)
2910 location_t saved_location;
2911 struct walk_stmt_info wi;
2913 memset (&wi, 0, sizeof (wi));
2914 wi.info = ctx;
2915 wi.want_locations = true;
2917 saved_location = input_location;
2918 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2919 input_location = saved_location;
2922 /* Re-gimplification and code generation routines. */
2924 /* Build a call to GOMP_barrier. */
2926 static gimple
2927 build_omp_barrier (tree lhs)
2929 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2930 : BUILT_IN_GOMP_BARRIER);
2931 gimple g = gimple_build_call (fndecl, 0);
2932 if (lhs)
2933 gimple_call_set_lhs (g, lhs);
2934 return g;
2937 /* If a context was created for STMT when it was scanned, return it. */
2939 static omp_context *
2940 maybe_lookup_ctx (gimple stmt)
2942 splay_tree_node n;
2943 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2944 return n ? (omp_context *) n->value : NULL;
2948 /* Find the mapping for DECL in CTX or the immediately enclosing
2949 context that has a mapping for DECL.
2951 If CTX is a nested parallel directive, we may have to use the decl
2952 mappings created in CTX's parent context. Suppose that we have the
2953 following parallel nesting (variable UIDs showed for clarity):
2955 iD.1562 = 0;
2956 #omp parallel shared(iD.1562) -> outer parallel
2957 iD.1562 = iD.1562 + 1;
2959 #omp parallel shared (iD.1562) -> inner parallel
2960 iD.1562 = iD.1562 - 1;
2962 Each parallel structure will create a distinct .omp_data_s structure
2963 for copying iD.1562 in/out of the directive:
2965 outer parallel .omp_data_s.1.i -> iD.1562
2966 inner parallel .omp_data_s.2.i -> iD.1562
2968 A shared variable mapping will produce a copy-out operation before
2969 the parallel directive and a copy-in operation after it. So, in
2970 this case we would have:
2972 iD.1562 = 0;
2973 .omp_data_o.1.i = iD.1562;
2974 #omp parallel shared(iD.1562) -> outer parallel
2975 .omp_data_i.1 = &.omp_data_o.1
2976 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2978 .omp_data_o.2.i = iD.1562; -> **
2979 #omp parallel shared(iD.1562) -> inner parallel
2980 .omp_data_i.2 = &.omp_data_o.2
2981 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2984 ** This is a problem. The symbol iD.1562 cannot be referenced
2985 inside the body of the outer parallel region. But since we are
2986 emitting this copy operation while expanding the inner parallel
2987 directive, we need to access the CTX structure of the outer
2988 parallel directive to get the correct mapping:
2990 .omp_data_o.2.i = .omp_data_i.1->i
2992 Since there may be other workshare or parallel directives enclosing
2993 the parallel directive, it may be necessary to walk up the context
2994 parent chain. This is not a problem in general because nested
2995 parallelism happens only rarely. */
2997 static tree
2998 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3000 tree t;
3001 omp_context *up;
3003 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3004 t = maybe_lookup_decl (decl, up);
3006 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3008 return t ? t : decl;
3012 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3013 in outer contexts. */
3015 static tree
3016 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3018 tree t = NULL;
3019 omp_context *up;
3021 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3022 t = maybe_lookup_decl (decl, up);
3024 return t ? t : decl;
3028 /* Construct the initialization value for reduction CLAUSE. */
3030 tree
3031 omp_reduction_init (tree clause, tree type)
3033 location_t loc = OMP_CLAUSE_LOCATION (clause);
3034 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3036 case PLUS_EXPR:
3037 case MINUS_EXPR:
3038 case BIT_IOR_EXPR:
3039 case BIT_XOR_EXPR:
3040 case TRUTH_OR_EXPR:
3041 case TRUTH_ORIF_EXPR:
3042 case TRUTH_XOR_EXPR:
3043 case NE_EXPR:
3044 return build_zero_cst (type);
3046 case MULT_EXPR:
3047 case TRUTH_AND_EXPR:
3048 case TRUTH_ANDIF_EXPR:
3049 case EQ_EXPR:
3050 return fold_convert_loc (loc, type, integer_one_node);
3052 case BIT_AND_EXPR:
3053 return fold_convert_loc (loc, type, integer_minus_one_node);
3055 case MAX_EXPR:
3056 if (SCALAR_FLOAT_TYPE_P (type))
3058 REAL_VALUE_TYPE max, min;
3059 if (HONOR_INFINITIES (TYPE_MODE (type)))
3061 real_inf (&max);
3062 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3064 else
3065 real_maxval (&min, 1, TYPE_MODE (type));
3066 return build_real (type, min);
3068 else
3070 gcc_assert (INTEGRAL_TYPE_P (type));
3071 return TYPE_MIN_VALUE (type);
3074 case MIN_EXPR:
3075 if (SCALAR_FLOAT_TYPE_P (type))
3077 REAL_VALUE_TYPE max;
3078 if (HONOR_INFINITIES (TYPE_MODE (type)))
3079 real_inf (&max);
3080 else
3081 real_maxval (&max, 0, TYPE_MODE (type));
3082 return build_real (type, max);
3084 else
3086 gcc_assert (INTEGRAL_TYPE_P (type));
3087 return TYPE_MAX_VALUE (type);
3090 default:
3091 gcc_unreachable ();
3095 /* Return alignment to be assumed for var in CLAUSE, which should be
3096 OMP_CLAUSE_ALIGNED. */
3098 static tree
3099 omp_clause_aligned_alignment (tree clause)
3101 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3102 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3104 /* Otherwise return implementation defined alignment. */
3105 unsigned int al = 1;
3106 enum machine_mode mode, vmode;
3107 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3108 if (vs)
3109 vs = 1 << floor_log2 (vs);
3110 static enum mode_class classes[]
3111 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3112 for (int i = 0; i < 4; i += 2)
3113 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3114 mode != VOIDmode;
3115 mode = GET_MODE_WIDER_MODE (mode))
3117 vmode = targetm.vectorize.preferred_simd_mode (mode);
3118 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3119 continue;
3120 while (vs
3121 && GET_MODE_SIZE (vmode) < vs
3122 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3123 vmode = GET_MODE_2XWIDER_MODE (vmode);
3125 tree type = lang_hooks.types.type_for_mode (mode, 1);
3126 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3127 continue;
3128 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3129 / GET_MODE_SIZE (mode));
3130 if (TYPE_MODE (type) != vmode)
3131 continue;
3132 if (TYPE_ALIGN_UNIT (type) > al)
3133 al = TYPE_ALIGN_UNIT (type);
3135 return build_int_cst (integer_type_node, al);
3138 /* Return maximum possible vectorization factor for the target. */
3140 static int
3141 omp_max_vf (void)
3143 if (!optimize
3144 || optimize_debug
3145 || (!flag_tree_loop_vectorize
3146 && (global_options_set.x_flag_tree_loop_vectorize
3147 || global_options_set.x_flag_tree_vectorize)))
3148 return 1;
3150 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3151 if (vs)
3153 vs = 1 << floor_log2 (vs);
3154 return vs;
3156 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3157 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3158 return GET_MODE_NUNITS (vqimode);
3159 return 1;
3162 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3163 privatization. */
3165 static bool
3166 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3167 tree &idx, tree &lane, tree &ivar, tree &lvar)
3169 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
3171 if (max_vf == 0)
3173 max_vf = omp_max_vf ();
3174 if (max_vf > 1)
3176 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3177 OMP_CLAUSE_SAFELEN);
3178 if (c
3179 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
3180 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3182 if (max_vf > 1)
3184 idx = create_tmp_var (unsigned_type_node, NULL);
3185 lane = create_tmp_var (unsigned_type_node, NULL);
3188 if (max_vf == 1)
3189 return false;
3191 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3192 tree avar = create_tmp_var_raw (atype, NULL);
3193 if (TREE_ADDRESSABLE (new_var))
3194 TREE_ADDRESSABLE (avar) = 1;
3195 DECL_ATTRIBUTES (avar)
3196 = tree_cons (get_identifier ("omp simd array"), NULL,
3197 DECL_ATTRIBUTES (avar));
3198 gimple_add_tmp_var (avar);
3199 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3200 NULL_TREE, NULL_TREE);
3201 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3202 NULL_TREE, NULL_TREE);
3203 if (DECL_P (new_var))
3205 SET_DECL_VALUE_EXPR (new_var, lvar);
3206 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3208 return true;
3211 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3212 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3213 private variables. Initialization statements go in ILIST, while calls
3214 to destructors go in DLIST. */
3216 static void
3217 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3218 omp_context *ctx, struct omp_for_data *fd)
3220 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
3222 tree c, dtor, copyin_seq, x, ptr;
3223 bool copyin_by_ref = false;
3224 bool lastprivate_firstprivate = false;
3225 bool reduction_omp_orig_ref = false;
3226 int pass;
3227 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3228 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD);
3229 int max_vf = 0;
3230 tree lane = NULL_TREE, idx = NULL_TREE;
3231 tree ivar = NULL_TREE, lvar = NULL_TREE;
3232 gimple_seq llist[2] = { NULL, NULL };
3234 copyin_seq = NULL;
3236 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3237 with data sharing clauses referencing variable sized vars. That
3238 is unnecessarily hard to support and very unlikely to result in
3239 vectorized code anyway. */
3240 if (is_simd)
3241 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3242 switch (OMP_CLAUSE_CODE (c))
3244 case OMP_CLAUSE_REDUCTION:
3245 case OMP_CLAUSE_PRIVATE:
3246 case OMP_CLAUSE_FIRSTPRIVATE:
3247 case OMP_CLAUSE_LASTPRIVATE:
3248 case OMP_CLAUSE_LINEAR:
3249 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3250 max_vf = 1;
3251 break;
3252 default:
3253 continue;
3256 /* Do all the fixed sized types in the first pass, and the variable sized
3257 types in the second pass. This makes sure that the scalar arguments to
3258 the variable sized types are processed before we use them in the
3259 variable sized operations. */
3260 for (pass = 0; pass < 2; ++pass)
3262 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3264 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3265 tree var, new_var;
3266 bool by_ref;
3267 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3269 switch (c_kind)
3271 case OMP_CLAUSE_PRIVATE:
3272 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3273 continue;
3274 break;
3275 case OMP_CLAUSE_SHARED:
3276 /* Ignore shared directives in teams construct. */
3277 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3278 continue;
3279 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3281 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3282 continue;
3284 case OMP_CLAUSE_FIRSTPRIVATE:
3285 case OMP_CLAUSE_COPYIN:
3286 case OMP_CLAUSE_LINEAR:
3287 break;
3288 case OMP_CLAUSE_REDUCTION:
3289 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3290 reduction_omp_orig_ref = true;
3291 break;
3292 case OMP_CLAUSE__LOOPTEMP_:
3293 /* Handle _looptemp_ clauses only on parallel. */
3294 if (fd)
3295 continue;
3296 break;
3297 case OMP_CLAUSE_LASTPRIVATE:
3298 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3300 lastprivate_firstprivate = true;
3301 if (pass != 0)
3302 continue;
3304 break;
3305 case OMP_CLAUSE_ALIGNED:
3306 if (pass == 0)
3307 continue;
3308 var = OMP_CLAUSE_DECL (c);
3309 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3310 && !is_global_var (var))
3312 new_var = maybe_lookup_decl (var, ctx);
3313 if (new_var == NULL_TREE)
3314 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3315 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3316 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3317 omp_clause_aligned_alignment (c));
3318 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3319 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3320 gimplify_and_add (x, ilist);
3322 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3323 && is_global_var (var))
3325 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3326 new_var = lookup_decl (var, ctx);
3327 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3328 t = build_fold_addr_expr_loc (clause_loc, t);
3329 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3330 t = build_call_expr_loc (clause_loc, t2, 2, t,
3331 omp_clause_aligned_alignment (c));
3332 t = fold_convert_loc (clause_loc, ptype, t);
3333 x = create_tmp_var (ptype, NULL);
3334 t = build2 (MODIFY_EXPR, ptype, x, t);
3335 gimplify_and_add (t, ilist);
3336 t = build_simple_mem_ref_loc (clause_loc, x);
3337 SET_DECL_VALUE_EXPR (new_var, t);
3338 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3340 continue;
3341 default:
3342 continue;
3345 new_var = var = OMP_CLAUSE_DECL (c);
3346 if (c_kind != OMP_CLAUSE_COPYIN)
3347 new_var = lookup_decl (var, ctx);
3349 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3351 if (pass != 0)
3352 continue;
3354 else if (is_variable_sized (var))
3356 /* For variable sized types, we need to allocate the
3357 actual storage here. Call alloca and store the
3358 result in the pointer decl that we created elsewhere. */
3359 if (pass == 0)
3360 continue;
3362 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3364 gimple stmt;
3365 tree tmp, atmp;
3367 ptr = DECL_VALUE_EXPR (new_var);
3368 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3369 ptr = TREE_OPERAND (ptr, 0);
3370 gcc_assert (DECL_P (ptr));
3371 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3373 /* void *tmp = __builtin_alloca */
3374 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3375 stmt = gimple_build_call (atmp, 1, x);
3376 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3377 gimple_add_tmp_var (tmp);
3378 gimple_call_set_lhs (stmt, tmp);
3380 gimple_seq_add_stmt (ilist, stmt);
3382 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3383 gimplify_assign (ptr, x, ilist);
3386 else if (is_reference (var))
3388 /* For references that are being privatized for Fortran,
3389 allocate new backing storage for the new pointer
3390 variable. This allows us to avoid changing all the
3391 code that expects a pointer to something that expects
3392 a direct variable. */
3393 if (pass == 0)
3394 continue;
3396 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3397 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3399 x = build_receiver_ref (var, false, ctx);
3400 x = build_fold_addr_expr_loc (clause_loc, x);
3402 else if (TREE_CONSTANT (x))
3404 /* For reduction with placeholder in SIMD loop,
3405 defer adding the initialization of the reference,
3406 because if we decide to use SIMD array for it,
3407 the initilization could cause expansion ICE. */
3408 if (c_kind == OMP_CLAUSE_REDUCTION
3409 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
3410 && is_simd)
3411 x = NULL_TREE;
3412 else
3414 const char *name = NULL;
3415 if (DECL_NAME (var))
3416 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3418 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3419 name);
3420 gimple_add_tmp_var (x);
3421 TREE_ADDRESSABLE (x) = 1;
3422 x = build_fold_addr_expr_loc (clause_loc, x);
3425 else
3427 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3428 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3431 if (x)
3433 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3434 gimplify_assign (new_var, x, ilist);
3437 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3439 else if (c_kind == OMP_CLAUSE_REDUCTION
3440 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3442 if (pass == 0)
3443 continue;
3445 else if (pass != 0)
3446 continue;
3448 switch (OMP_CLAUSE_CODE (c))
3450 case OMP_CLAUSE_SHARED:
3451 /* Ignore shared directives in teams construct. */
3452 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3453 continue;
3454 /* Shared global vars are just accessed directly. */
3455 if (is_global_var (new_var))
3456 break;
3457 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3458 needs to be delayed until after fixup_child_record_type so
3459 that we get the correct type during the dereference. */
3460 by_ref = use_pointer_for_field (var, ctx);
3461 x = build_receiver_ref (var, by_ref, ctx);
3462 SET_DECL_VALUE_EXPR (new_var, x);
3463 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3465 /* ??? If VAR is not passed by reference, and the variable
3466 hasn't been initialized yet, then we'll get a warning for
3467 the store into the omp_data_s structure. Ideally, we'd be
3468 able to notice this and not store anything at all, but
3469 we're generating code too early. Suppress the warning. */
3470 if (!by_ref)
3471 TREE_NO_WARNING (var) = 1;
3472 break;
3474 case OMP_CLAUSE_LASTPRIVATE:
3475 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3476 break;
3477 /* FALLTHRU */
3479 case OMP_CLAUSE_PRIVATE:
3480 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3481 x = build_outer_var_ref (var, ctx);
3482 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3484 if (is_task_ctx (ctx))
3485 x = build_receiver_ref (var, false, ctx);
3486 else
3487 x = build_outer_var_ref (var, ctx);
3489 else
3490 x = NULL;
3491 do_private:
3492 tree nx;
3493 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3494 if (is_simd)
3496 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3497 if ((TREE_ADDRESSABLE (new_var) || nx || y
3498 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3499 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3500 idx, lane, ivar, lvar))
3502 if (nx)
3503 x = lang_hooks.decls.omp_clause_default_ctor
3504 (c, unshare_expr (ivar), x);
3505 if (nx && x)
3506 gimplify_and_add (x, &llist[0]);
3507 if (y)
3509 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3510 if (y)
3512 gimple_seq tseq = NULL;
3514 dtor = y;
3515 gimplify_stmt (&dtor, &tseq);
3516 gimple_seq_add_seq (&llist[1], tseq);
3519 break;
3522 if (nx)
3523 gimplify_and_add (nx, ilist);
3524 /* FALLTHRU */
3526 do_dtor:
3527 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3528 if (x)
3530 gimple_seq tseq = NULL;
3532 dtor = x;
3533 gimplify_stmt (&dtor, &tseq);
3534 gimple_seq_add_seq (dlist, tseq);
3536 break;
3538 case OMP_CLAUSE_LINEAR:
3539 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3540 goto do_firstprivate;
3541 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3542 x = NULL;
3543 else
3544 x = build_outer_var_ref (var, ctx);
3545 goto do_private;
3547 case OMP_CLAUSE_FIRSTPRIVATE:
3548 if (is_task_ctx (ctx))
3550 if (is_reference (var) || is_variable_sized (var))
3551 goto do_dtor;
3552 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3553 ctx))
3554 || use_pointer_for_field (var, NULL))
3556 x = build_receiver_ref (var, false, ctx);
3557 SET_DECL_VALUE_EXPR (new_var, x);
3558 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3559 goto do_dtor;
3562 do_firstprivate:
3563 x = build_outer_var_ref (var, ctx);
3564 if (is_simd)
3566 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3567 && gimple_omp_for_combined_into_p (ctx->stmt))
3569 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3570 ? sizetype : TREE_TYPE (x);
3571 tree t = fold_convert (stept,
3572 OMP_CLAUSE_LINEAR_STEP (c));
3573 tree c = find_omp_clause (clauses,
3574 OMP_CLAUSE__LOOPTEMP_);
3575 gcc_assert (c);
3576 tree l = OMP_CLAUSE_DECL (c);
3577 if (fd->collapse == 1)
3579 tree n1 = fd->loop.n1;
3580 tree step = fd->loop.step;
3581 tree itype = TREE_TYPE (l);
3582 if (POINTER_TYPE_P (itype))
3583 itype = signed_type_for (itype);
3584 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3585 if (TYPE_UNSIGNED (itype)
3586 && fd->loop.cond_code == GT_EXPR)
3587 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3588 fold_build1 (NEGATE_EXPR,
3589 itype, l),
3590 fold_build1 (NEGATE_EXPR,
3591 itype, step));
3592 else
3593 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3595 t = fold_build2 (MULT_EXPR, stept,
3596 fold_convert (stept, l), t);
3597 if (POINTER_TYPE_P (TREE_TYPE (x)))
3598 x = fold_build2 (POINTER_PLUS_EXPR,
3599 TREE_TYPE (x), x, t);
3600 else
3601 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3604 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3605 || TREE_ADDRESSABLE (new_var))
3606 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3607 idx, lane, ivar, lvar))
3609 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3611 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3612 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3613 gimplify_and_add (x, ilist);
3614 gimple_stmt_iterator gsi
3615 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3616 gimple g
3617 = gimple_build_assign (unshare_expr (lvar), iv);
3618 gsi_insert_before_without_update (&gsi, g,
3619 GSI_SAME_STMT);
3620 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3621 ? sizetype : TREE_TYPE (x);
3622 tree t = fold_convert (stept,
3623 OMP_CLAUSE_LINEAR_STEP (c));
3624 enum tree_code code = PLUS_EXPR;
3625 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3626 code = POINTER_PLUS_EXPR;
3627 g = gimple_build_assign_with_ops (code, iv, iv, t);
3628 gsi_insert_before_without_update (&gsi, g,
3629 GSI_SAME_STMT);
3630 break;
3632 x = lang_hooks.decls.omp_clause_copy_ctor
3633 (c, unshare_expr (ivar), x);
3634 gimplify_and_add (x, &llist[0]);
3635 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3636 if (x)
3638 gimple_seq tseq = NULL;
3640 dtor = x;
3641 gimplify_stmt (&dtor, &tseq);
3642 gimple_seq_add_seq (&llist[1], tseq);
3644 break;
3647 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3648 gimplify_and_add (x, ilist);
3649 goto do_dtor;
3651 case OMP_CLAUSE__LOOPTEMP_:
3652 gcc_assert (is_parallel_ctx (ctx));
3653 x = build_outer_var_ref (var, ctx);
3654 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3655 gimplify_and_add (x, ilist);
3656 break;
3658 case OMP_CLAUSE_COPYIN:
3659 by_ref = use_pointer_for_field (var, NULL);
3660 x = build_receiver_ref (var, by_ref, ctx);
3661 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3662 append_to_statement_list (x, &copyin_seq);
3663 copyin_by_ref |= by_ref;
3664 break;
3666 case OMP_CLAUSE_REDUCTION:
3667 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3669 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3670 gimple tseq;
3671 x = build_outer_var_ref (var, ctx);
3673 if (is_reference (var)
3674 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3675 TREE_TYPE (x)))
3676 x = build_fold_addr_expr_loc (clause_loc, x);
3677 SET_DECL_VALUE_EXPR (placeholder, x);
3678 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3679 tree new_vard = new_var;
3680 if (is_reference (var))
3682 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3683 new_vard = TREE_OPERAND (new_var, 0);
3684 gcc_assert (DECL_P (new_vard));
3686 if (is_simd
3687 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3688 idx, lane, ivar, lvar))
3690 if (new_vard == new_var)
3692 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3693 SET_DECL_VALUE_EXPR (new_var, ivar);
3695 else
3697 SET_DECL_VALUE_EXPR (new_vard,
3698 build_fold_addr_expr (ivar));
3699 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3701 x = lang_hooks.decls.omp_clause_default_ctor
3702 (c, unshare_expr (ivar),
3703 build_outer_var_ref (var, ctx));
3704 if (x)
3705 gimplify_and_add (x, &llist[0]);
3706 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3708 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3709 lower_omp (&tseq, ctx);
3710 gimple_seq_add_seq (&llist[0], tseq);
3712 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3713 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3714 lower_omp (&tseq, ctx);
3715 gimple_seq_add_seq (&llist[1], tseq);
3716 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3717 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3718 if (new_vard == new_var)
3719 SET_DECL_VALUE_EXPR (new_var, lvar);
3720 else
3721 SET_DECL_VALUE_EXPR (new_vard,
3722 build_fold_addr_expr (lvar));
3723 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3724 if (x)
3726 tseq = NULL;
3727 dtor = x;
3728 gimplify_stmt (&dtor, &tseq);
3729 gimple_seq_add_seq (&llist[1], tseq);
3731 break;
3733 /* If this is a reference to constant size reduction var
3734 with placeholder, we haven't emitted the initializer
3735 for it because it is undesirable if SIMD arrays are used.
3736 But if they aren't used, we need to emit the deferred
3737 initialization now. */
3738 else if (is_reference (var) && is_simd)
3740 tree z
3741 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3742 if (TREE_CONSTANT (z))
3744 const char *name = NULL;
3745 if (DECL_NAME (var))
3746 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3748 z = create_tmp_var_raw
3749 (TREE_TYPE (TREE_TYPE (new_vard)), name);
3750 gimple_add_tmp_var (z);
3751 TREE_ADDRESSABLE (z) = 1;
3752 z = build_fold_addr_expr_loc (clause_loc, z);
3753 gimplify_assign (new_vard, z, ilist);
3756 x = lang_hooks.decls.omp_clause_default_ctor
3757 (c, new_var, unshare_expr (x));
3758 if (x)
3759 gimplify_and_add (x, ilist);
3760 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3762 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3763 lower_omp (&tseq, ctx);
3764 gimple_seq_add_seq (ilist, tseq);
3766 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3767 if (is_simd)
3769 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3770 lower_omp (&tseq, ctx);
3771 gimple_seq_add_seq (dlist, tseq);
3772 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3774 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3775 goto do_dtor;
3777 else
3779 x = omp_reduction_init (c, TREE_TYPE (new_var));
3780 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3781 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3783 /* reduction(-:var) sums up the partial results, so it
3784 acts identically to reduction(+:var). */
3785 if (code == MINUS_EXPR)
3786 code = PLUS_EXPR;
3788 if (is_simd
3789 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3790 idx, lane, ivar, lvar))
3792 tree ref = build_outer_var_ref (var, ctx);
3794 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3796 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3797 ref = build_outer_var_ref (var, ctx);
3798 gimplify_assign (ref, x, &llist[1]);
3800 else
3802 gimplify_assign (new_var, x, ilist);
3803 if (is_simd)
3805 tree ref = build_outer_var_ref (var, ctx);
3807 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3808 ref = build_outer_var_ref (var, ctx);
3809 gimplify_assign (ref, x, dlist);
3813 break;
3815 default:
3816 gcc_unreachable ();
3821 if (lane)
3823 tree uid = create_tmp_var (ptr_type_node, "simduid");
3824 /* Don't want uninit warnings on simduid, it is always uninitialized,
3825 but we use it not for the value, but for the DECL_UID only. */
3826 TREE_NO_WARNING (uid) = 1;
3827 gimple g
3828 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3829 gimple_call_set_lhs (g, lane);
3830 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3831 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3832 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3833 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3834 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3835 gimple_omp_for_set_clauses (ctx->stmt, c);
3836 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3837 build_int_cst (unsigned_type_node, 0),
3838 NULL_TREE);
3839 gimple_seq_add_stmt (ilist, g);
3840 for (int i = 0; i < 2; i++)
3841 if (llist[i])
3843 tree vf = create_tmp_var (unsigned_type_node, NULL);
3844 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3845 gimple_call_set_lhs (g, vf);
3846 gimple_seq *seq = i == 0 ? ilist : dlist;
3847 gimple_seq_add_stmt (seq, g);
3848 tree t = build_int_cst (unsigned_type_node, 0);
3849 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3850 gimple_seq_add_stmt (seq, g);
3851 tree body = create_artificial_label (UNKNOWN_LOCATION);
3852 tree header = create_artificial_label (UNKNOWN_LOCATION);
3853 tree end = create_artificial_label (UNKNOWN_LOCATION);
3854 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3855 gimple_seq_add_stmt (seq, gimple_build_label (body));
3856 gimple_seq_add_seq (seq, llist[i]);
3857 t = build_int_cst (unsigned_type_node, 1);
3858 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3859 gimple_seq_add_stmt (seq, g);
3860 gimple_seq_add_stmt (seq, gimple_build_label (header));
3861 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3862 gimple_seq_add_stmt (seq, g);
3863 gimple_seq_add_stmt (seq, gimple_build_label (end));
3867 /* The copyin sequence is not to be executed by the main thread, since
3868 that would result in self-copies. Perhaps not visible to scalars,
3869 but it certainly is to C++ operator=. */
3870 if (copyin_seq)
3872 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3874 x = build2 (NE_EXPR, boolean_type_node, x,
3875 build_int_cst (TREE_TYPE (x), 0));
3876 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3877 gimplify_and_add (x, ilist);
3880 /* If any copyin variable is passed by reference, we must ensure the
3881 master thread doesn't modify it before it is copied over in all
3882 threads. Similarly for variables in both firstprivate and
3883 lastprivate clauses we need to ensure the lastprivate copying
3884 happens after firstprivate copying in all threads. And similarly
3885 for UDRs if initializer expression refers to omp_orig. */
3886 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3888 /* Don't add any barrier for #pragma omp simd or
3889 #pragma omp distribute. */
3890 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3891 || gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_FOR)
3892 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3895 /* If max_vf is non-zero, then we can use only a vectorization factor
3896 up to the max_vf we chose. So stick it into the safelen clause. */
3897 if (max_vf)
3899 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3900 OMP_CLAUSE_SAFELEN);
3901 if (c == NULL_TREE
3902 || compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3903 max_vf) == 1)
3905 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3906 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3907 max_vf);
3908 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3909 gimple_omp_for_set_clauses (ctx->stmt, c);
3915 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3916 both parallel and workshare constructs. PREDICATE may be NULL if it's
3917 always true. */
3919 static void
3920 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3921 omp_context *ctx)
3923 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
3925 tree x, c, label = NULL, orig_clauses = clauses;
3926 bool par_clauses = false;
3927 tree simduid = NULL, lastlane = NULL;
3929 /* Early exit if there are no lastprivate or linear clauses. */
3930 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3931 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3932 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3933 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3934 break;
3935 if (clauses == NULL)
3937 /* If this was a workshare clause, see if it had been combined
3938 with its parallel. In that case, look for the clauses on the
3939 parallel statement itself. */
3940 if (is_parallel_ctx (ctx))
3941 return;
3943 ctx = ctx->outer;
3944 if (ctx == NULL || !is_parallel_ctx (ctx))
3945 return;
3947 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3948 OMP_CLAUSE_LASTPRIVATE);
3949 if (clauses == NULL)
3950 return;
3951 par_clauses = true;
3954 if (predicate)
3956 gimple stmt;
3957 tree label_true, arm1, arm2;
3959 label = create_artificial_label (UNKNOWN_LOCATION);
3960 label_true = create_artificial_label (UNKNOWN_LOCATION);
3961 arm1 = TREE_OPERAND (predicate, 0);
3962 arm2 = TREE_OPERAND (predicate, 1);
3963 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3964 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3965 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3966 label_true, label);
3967 gimple_seq_add_stmt (stmt_list, stmt);
3968 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3971 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3972 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
3974 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3975 if (simduid)
3976 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3979 for (c = clauses; c ;)
3981 tree var, new_var;
3982 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3984 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3985 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3986 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3988 var = OMP_CLAUSE_DECL (c);
3989 new_var = lookup_decl (var, ctx);
3991 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3993 tree val = DECL_VALUE_EXPR (new_var);
3994 if (TREE_CODE (val) == ARRAY_REF
3995 && VAR_P (TREE_OPERAND (val, 0))
3996 && lookup_attribute ("omp simd array",
3997 DECL_ATTRIBUTES (TREE_OPERAND (val,
3998 0))))
4000 if (lastlane == NULL)
4002 lastlane = create_tmp_var (unsigned_type_node, NULL);
4003 gimple g
4004 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4005 2, simduid,
4006 TREE_OPERAND (val, 1));
4007 gimple_call_set_lhs (g, lastlane);
4008 gimple_seq_add_stmt (stmt_list, g);
4010 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4011 TREE_OPERAND (val, 0), lastlane,
4012 NULL_TREE, NULL_TREE);
4016 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4017 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4019 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4020 gimple_seq_add_seq (stmt_list,
4021 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4022 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4025 x = build_outer_var_ref (var, ctx);
4026 if (is_reference (var))
4027 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4028 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4029 gimplify_and_add (x, stmt_list);
4031 c = OMP_CLAUSE_CHAIN (c);
4032 if (c == NULL && !par_clauses)
4034 /* If this was a workshare clause, see if it had been combined
4035 with its parallel. In that case, continue looking for the
4036 clauses also on the parallel statement itself. */
4037 if (is_parallel_ctx (ctx))
4038 break;
4040 ctx = ctx->outer;
4041 if (ctx == NULL || !is_parallel_ctx (ctx))
4042 break;
4044 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4045 OMP_CLAUSE_LASTPRIVATE);
4046 par_clauses = true;
4050 if (label)
4051 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4055 /* Generate code to implement the REDUCTION clauses. */
4057 static void
4058 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4060 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
4062 gimple_seq sub_seq = NULL;
4063 gimple stmt;
4064 tree x, c;
4065 int count = 0;
4067 /* SIMD reductions are handled in lower_rec_input_clauses. */
4068 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4069 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
4070 return;
4072 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4073 update in that case, otherwise use a lock. */
4074 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4075 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4077 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4079 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4080 count = -1;
4081 break;
4083 count++;
4086 if (count == 0)
4087 return;
4089 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4091 tree var, ref, new_var;
4092 enum tree_code code;
4093 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4095 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4096 continue;
4098 var = OMP_CLAUSE_DECL (c);
4099 new_var = lookup_decl (var, ctx);
4100 if (is_reference (var))
4101 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4102 ref = build_outer_var_ref (var, ctx);
4103 code = OMP_CLAUSE_REDUCTION_CODE (c);
4105 /* reduction(-:var) sums up the partial results, so it acts
4106 identically to reduction(+:var). */
4107 if (code == MINUS_EXPR)
4108 code = PLUS_EXPR;
4110 if (count == 1)
4112 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4114 addr = save_expr (addr);
4115 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4116 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4117 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4118 gimplify_and_add (x, stmt_seqp);
4119 return;
4122 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4124 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4126 if (is_reference (var)
4127 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4128 TREE_TYPE (ref)))
4129 ref = build_fold_addr_expr_loc (clause_loc, ref);
4130 SET_DECL_VALUE_EXPR (placeholder, ref);
4131 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4132 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4133 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4134 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4135 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4137 else
4139 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4140 ref = build_outer_var_ref (var, ctx);
4141 gimplify_assign (ref, x, &sub_seq);
4145 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4147 gimple_seq_add_stmt (stmt_seqp, stmt);
4149 gimple_seq_add_seq (stmt_seqp, sub_seq);
4151 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4153 gimple_seq_add_stmt (stmt_seqp, stmt);
4157 /* Generate code to implement the COPYPRIVATE clauses. */
4159 static void
4160 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4161 omp_context *ctx)
4163 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
4165 tree c;
4167 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4169 tree var, new_var, ref, x;
4170 bool by_ref;
4171 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4173 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4174 continue;
4176 var = OMP_CLAUSE_DECL (c);
4177 by_ref = use_pointer_for_field (var, NULL);
4179 ref = build_sender_ref (var, ctx);
4180 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4181 if (by_ref)
4183 x = build_fold_addr_expr_loc (clause_loc, new_var);
4184 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4186 gimplify_assign (ref, x, slist);
4188 ref = build_receiver_ref (var, false, ctx);
4189 if (by_ref)
4191 ref = fold_convert_loc (clause_loc,
4192 build_pointer_type (TREE_TYPE (new_var)),
4193 ref);
4194 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4196 if (is_reference (var))
4198 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4199 ref = build_simple_mem_ref_loc (clause_loc, ref);
4200 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4202 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4203 gimplify_and_add (x, rlist);
4208 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4209 and REDUCTION from the sender (aka parent) side. */
4211 static void
4212 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4213 omp_context *ctx)
4215 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
4217 tree c;
4219 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4221 tree val, ref, x, var;
4222 bool by_ref, do_in = false, do_out = false;
4223 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4225 switch (OMP_CLAUSE_CODE (c))
4227 case OMP_CLAUSE_PRIVATE:
4228 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4229 break;
4230 continue;
4231 case OMP_CLAUSE_FIRSTPRIVATE:
4232 case OMP_CLAUSE_COPYIN:
4233 case OMP_CLAUSE_LASTPRIVATE:
4234 case OMP_CLAUSE_REDUCTION:
4235 case OMP_CLAUSE__LOOPTEMP_:
4236 break;
4237 default:
4238 continue;
4241 val = OMP_CLAUSE_DECL (c);
4242 var = lookup_decl_in_outer_ctx (val, ctx);
4244 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4245 && is_global_var (var))
4246 continue;
4247 if (is_variable_sized (val))
4248 continue;
4249 by_ref = use_pointer_for_field (val, NULL);
4251 switch (OMP_CLAUSE_CODE (c))
4253 case OMP_CLAUSE_PRIVATE:
4254 case OMP_CLAUSE_FIRSTPRIVATE:
4255 case OMP_CLAUSE_COPYIN:
4256 case OMP_CLAUSE__LOOPTEMP_:
4257 do_in = true;
4258 break;
4260 case OMP_CLAUSE_LASTPRIVATE:
4261 if (by_ref || is_reference (val))
4263 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4264 continue;
4265 do_in = true;
4267 else
4269 do_out = true;
4270 if (lang_hooks.decls.omp_private_outer_ref (val))
4271 do_in = true;
4273 break;
4275 case OMP_CLAUSE_REDUCTION:
4276 do_in = true;
4277 do_out = !(by_ref || is_reference (val));
4278 break;
4280 default:
4281 gcc_unreachable ();
4284 if (do_in)
4286 ref = build_sender_ref (val, ctx);
4287 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4288 gimplify_assign (ref, x, ilist);
4289 if (is_task_ctx (ctx))
4290 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4293 if (do_out)
4295 ref = build_sender_ref (val, ctx);
4296 gimplify_assign (var, ref, olist);
4301 /* Generate code to implement SHARED from the sender (aka parent)
4302 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4303 list things that got automatically shared. */
4305 static void
4306 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4308 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
4310 tree var, ovar, nvar, f, x, record_type;
4312 if (ctx->record_type == NULL)
4313 return;
4315 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4316 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4318 ovar = DECL_ABSTRACT_ORIGIN (f);
4319 nvar = maybe_lookup_decl (ovar, ctx);
4320 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4321 continue;
4323 /* If CTX is a nested parallel directive. Find the immediately
4324 enclosing parallel or workshare construct that contains a
4325 mapping for OVAR. */
4326 var = lookup_decl_in_outer_ctx (ovar, ctx);
4328 if (use_pointer_for_field (ovar, ctx))
4330 x = build_sender_ref (ovar, ctx);
4331 var = build_fold_addr_expr (var);
4332 gimplify_assign (x, var, ilist);
4334 else
4336 x = build_sender_ref (ovar, ctx);
4337 gimplify_assign (x, var, ilist);
4339 if (!TREE_READONLY (var)
4340 /* We don't need to receive a new reference to a result
4341 or parm decl. In fact we may not store to it as we will
4342 invalidate any pending RSO and generate wrong gimple
4343 during inlining. */
4344 && !((TREE_CODE (var) == RESULT_DECL
4345 || TREE_CODE (var) == PARM_DECL)
4346 && DECL_BY_REFERENCE (var)))
4348 x = build_sender_ref (ovar, ctx);
4349 gimplify_assign (var, x, olist);
4356 /* A convenience function to build an empty GIMPLE_COND with just the
4357 condition. */
4359 static gimple
4360 gimple_build_cond_empty (tree cond)
4362 enum tree_code pred_code;
4363 tree lhs, rhs;
4365 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4366 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4370 /* Build the function calls to GOMP_parallel_start etc to actually
4371 generate the parallel operation. REGION is the parallel region
4372 being expanded. BB is the block where to insert the code. WS_ARGS
4373 will be set if this is a call to a combined parallel+workshare
4374 construct, it contains the list of additional arguments needed by
4375 the workshare construct. */
4377 static void
4378 expand_parallel_call (struct omp_region *region, basic_block bb,
4379 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4381 tree t, t1, t2, val, cond, c, clauses, flags;
4382 gimple_stmt_iterator gsi;
4383 gimple stmt;
4384 enum built_in_function start_ix;
4385 int start_ix2;
4386 location_t clause_loc;
4387 vec<tree, va_gc> *args;
4389 clauses = gimple_omp_parallel_clauses (entry_stmt);
4391 /* Determine what flavor of GOMP_parallel we will be
4392 emitting. */
4393 start_ix = BUILT_IN_GOMP_PARALLEL;
4394 if (is_combined_parallel (region))
4396 switch (region->inner->type)
4398 case GIMPLE_OMP_FOR:
4399 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4400 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4401 + (region->inner->sched_kind
4402 == OMP_CLAUSE_SCHEDULE_RUNTIME
4403 ? 3 : region->inner->sched_kind));
4404 start_ix = (enum built_in_function)start_ix2;
4405 break;
4406 case GIMPLE_OMP_SECTIONS:
4407 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4408 break;
4409 default:
4410 gcc_unreachable ();
4414 /* By default, the value of NUM_THREADS is zero (selected at run time)
4415 and there is no conditional. */
4416 cond = NULL_TREE;
4417 val = build_int_cst (unsigned_type_node, 0);
4418 flags = build_int_cst (unsigned_type_node, 0);
4420 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4421 if (c)
4422 cond = OMP_CLAUSE_IF_EXPR (c);
4424 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4425 if (c)
4427 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4428 clause_loc = OMP_CLAUSE_LOCATION (c);
4430 else
4431 clause_loc = gimple_location (entry_stmt);
4433 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4434 if (c)
4435 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4437 /* Ensure 'val' is of the correct type. */
4438 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4440 /* If we found the clause 'if (cond)', build either
4441 (cond != 0) or (cond ? val : 1u). */
4442 if (cond)
4444 gimple_stmt_iterator gsi;
4446 cond = gimple_boolify (cond);
4448 if (integer_zerop (val))
4449 val = fold_build2_loc (clause_loc,
4450 EQ_EXPR, unsigned_type_node, cond,
4451 build_int_cst (TREE_TYPE (cond), 0));
4452 else
4454 basic_block cond_bb, then_bb, else_bb;
4455 edge e, e_then, e_else;
4456 tree tmp_then, tmp_else, tmp_join, tmp_var;
4458 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4459 if (gimple_in_ssa_p (cfun))
4461 tmp_then = make_ssa_name (tmp_var, NULL);
4462 tmp_else = make_ssa_name (tmp_var, NULL);
4463 tmp_join = make_ssa_name (tmp_var, NULL);
4465 else
4467 tmp_then = tmp_var;
4468 tmp_else = tmp_var;
4469 tmp_join = tmp_var;
4472 e = split_block (bb, NULL);
4473 cond_bb = e->src;
4474 bb = e->dest;
4475 remove_edge (e);
4477 then_bb = create_empty_bb (cond_bb);
4478 else_bb = create_empty_bb (then_bb);
4479 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4480 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4482 stmt = gimple_build_cond_empty (cond);
4483 gsi = gsi_start_bb (cond_bb);
4484 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4486 gsi = gsi_start_bb (then_bb);
4487 stmt = gimple_build_assign (tmp_then, val);
4488 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4490 gsi = gsi_start_bb (else_bb);
4491 stmt = gimple_build_assign
4492 (tmp_else, build_int_cst (unsigned_type_node, 1));
4493 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4495 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4496 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4497 if (current_loops)
4499 add_bb_to_loop (then_bb, cond_bb->loop_father);
4500 add_bb_to_loop (else_bb, cond_bb->loop_father);
4502 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4503 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4505 if (gimple_in_ssa_p (cfun))
4507 gimple phi = create_phi_node (tmp_join, bb);
4508 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4509 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4512 val = tmp_join;
4515 gsi = gsi_start_bb (bb);
4516 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4517 false, GSI_CONTINUE_LINKING);
4520 gsi = gsi_last_bb (bb);
4521 t = gimple_omp_parallel_data_arg (entry_stmt);
4522 if (t == NULL)
4523 t1 = null_pointer_node;
4524 else
4525 t1 = build_fold_addr_expr (t);
4526 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4528 vec_alloc (args, 4 + vec_safe_length (ws_args));
4529 args->quick_push (t2);
4530 args->quick_push (t1);
4531 args->quick_push (val);
4532 if (ws_args)
4533 args->splice (*ws_args);
4534 args->quick_push (flags);
4536 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4537 builtin_decl_explicit (start_ix), args);
4539 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4540 false, GSI_CONTINUE_LINKING);
4544 /* Build the function call to GOMP_task to actually
4545 generate the task operation. BB is the block where to insert the code. */
4547 static void
4548 expand_task_call (basic_block bb, gimple entry_stmt)
4550 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4551 gimple_stmt_iterator gsi;
4552 location_t loc = gimple_location (entry_stmt);
4554 clauses = gimple_omp_task_clauses (entry_stmt);
4556 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4557 if (c)
4558 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4559 else
4560 cond = boolean_true_node;
4562 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4563 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4564 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4565 flags = build_int_cst (unsigned_type_node,
4566 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4568 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4569 if (c)
4571 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4572 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4573 build_int_cst (unsigned_type_node, 2),
4574 build_int_cst (unsigned_type_node, 0));
4575 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4577 if (depend)
4578 depend = OMP_CLAUSE_DECL (depend);
4579 else
4580 depend = build_int_cst (ptr_type_node, 0);
4582 gsi = gsi_last_bb (bb);
4583 t = gimple_omp_task_data_arg (entry_stmt);
4584 if (t == NULL)
4585 t2 = null_pointer_node;
4586 else
4587 t2 = build_fold_addr_expr_loc (loc, t);
4588 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4589 t = gimple_omp_task_copy_fn (entry_stmt);
4590 if (t == NULL)
4591 t3 = null_pointer_node;
4592 else
4593 t3 = build_fold_addr_expr_loc (loc, t);
4595 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4596 8, t1, t2, t3,
4597 gimple_omp_task_arg_size (entry_stmt),
4598 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4599 depend);
4601 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4602 false, GSI_CONTINUE_LINKING);
4606 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4607 catch handler and return it. This prevents programs from violating the
4608 structured block semantics with throws. */
4610 static gimple_seq
4611 maybe_catch_exception (gimple_seq body)
4613 gimple g;
4614 tree decl;
4616 if (!flag_exceptions)
4617 return body;
4619 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4620 decl = lang_hooks.eh_protect_cleanup_actions ();
4621 else
4622 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4624 g = gimple_build_eh_must_not_throw (decl);
4625 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4626 GIMPLE_TRY_CATCH);
4628 return gimple_seq_alloc_with_stmt (g);
4631 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4633 static tree
4634 vec2chain (vec<tree, va_gc> *v)
4636 tree chain = NULL_TREE, t;
4637 unsigned ix;
4639 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4641 DECL_CHAIN (t) = chain;
4642 chain = t;
4645 return chain;
4649 /* Remove barriers in REGION->EXIT's block. Note that this is only
4650 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4651 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4652 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4653 removed. */
4655 static void
4656 remove_exit_barrier (struct omp_region *region)
4658 gimple_stmt_iterator gsi;
4659 basic_block exit_bb;
4660 edge_iterator ei;
4661 edge e;
4662 gimple stmt;
4663 int any_addressable_vars = -1;
4665 exit_bb = region->exit;
4667 /* If the parallel region doesn't return, we don't have REGION->EXIT
4668 block at all. */
4669 if (! exit_bb)
4670 return;
4672 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4673 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4674 statements that can appear in between are extremely limited -- no
4675 memory operations at all. Here, we allow nothing at all, so the
4676 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4677 gsi = gsi_last_bb (exit_bb);
4678 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4679 gsi_prev (&gsi);
4680 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4681 return;
4683 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4685 gsi = gsi_last_bb (e->src);
4686 if (gsi_end_p (gsi))
4687 continue;
4688 stmt = gsi_stmt (gsi);
4689 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4690 && !gimple_omp_return_nowait_p (stmt))
4692 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4693 in many cases. If there could be tasks queued, the barrier
4694 might be needed to let the tasks run before some local
4695 variable of the parallel that the task uses as shared
4696 runs out of scope. The task can be spawned either
4697 from within current function (this would be easy to check)
4698 or from some function it calls and gets passed an address
4699 of such a variable. */
4700 if (any_addressable_vars < 0)
4702 gimple parallel_stmt = last_stmt (region->entry);
4703 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4704 tree local_decls, block, decl;
4705 unsigned ix;
4707 any_addressable_vars = 0;
4708 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4709 if (TREE_ADDRESSABLE (decl))
4711 any_addressable_vars = 1;
4712 break;
4714 for (block = gimple_block (stmt);
4715 !any_addressable_vars
4716 && block
4717 && TREE_CODE (block) == BLOCK;
4718 block = BLOCK_SUPERCONTEXT (block))
4720 for (local_decls = BLOCK_VARS (block);
4721 local_decls;
4722 local_decls = DECL_CHAIN (local_decls))
4723 if (TREE_ADDRESSABLE (local_decls))
4725 any_addressable_vars = 1;
4726 break;
4728 if (block == gimple_block (parallel_stmt))
4729 break;
4732 if (!any_addressable_vars)
4733 gimple_omp_return_set_nowait (stmt);
4738 static void
4739 remove_exit_barriers (struct omp_region *region)
4741 if (region->type == GIMPLE_OMP_PARALLEL)
4742 remove_exit_barrier (region);
4744 if (region->inner)
4746 region = region->inner;
4747 remove_exit_barriers (region);
4748 while (region->next)
4750 region = region->next;
4751 remove_exit_barriers (region);
4756 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4757 calls. These can't be declared as const functions, but
4758 within one parallel body they are constant, so they can be
4759 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4760 which are declared const. Similarly for task body, except
4761 that in untied task omp_get_thread_num () can change at any task
4762 scheduling point. */
4764 static void
4765 optimize_omp_library_calls (gimple entry_stmt)
4767 basic_block bb;
4768 gimple_stmt_iterator gsi;
4769 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4770 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4771 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4772 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4773 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4774 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4775 OMP_CLAUSE_UNTIED) != NULL);
4777 FOR_EACH_BB_FN (bb, cfun)
4778 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4780 gimple call = gsi_stmt (gsi);
4781 tree decl;
4783 if (is_gimple_call (call)
4784 && (decl = gimple_call_fndecl (call))
4785 && DECL_EXTERNAL (decl)
4786 && TREE_PUBLIC (decl)
4787 && DECL_INITIAL (decl) == NULL)
4789 tree built_in;
4791 if (DECL_NAME (decl) == thr_num_id)
4793 /* In #pragma omp task untied omp_get_thread_num () can change
4794 during the execution of the task region. */
4795 if (untied_task)
4796 continue;
4797 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4799 else if (DECL_NAME (decl) == num_thr_id)
4800 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4801 else
4802 continue;
4804 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4805 || gimple_call_num_args (call) != 0)
4806 continue;
4808 if (flag_exceptions && !TREE_NOTHROW (decl))
4809 continue;
4811 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4812 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4813 TREE_TYPE (TREE_TYPE (built_in))))
4814 continue;
4816 gimple_call_set_fndecl (call, built_in);
4821 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4822 regimplified. */
4824 static tree
4825 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4827 tree t = *tp;
4829 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4830 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4831 return t;
4833 if (TREE_CODE (t) == ADDR_EXPR)
4834 recompute_tree_invariant_for_addr_expr (t);
4836 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4837 return NULL_TREE;
4840 /* Prepend TO = FROM assignment before *GSI_P. */
4842 static void
4843 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4845 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4846 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4847 true, GSI_SAME_STMT);
4848 gimple stmt = gimple_build_assign (to, from);
4849 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4850 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4851 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4853 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4854 gimple_regimplify_operands (stmt, &gsi);
4858 /* Expand the OpenACC offload directive starting at REGION. */
4860 static void
4861 expand_oacc_offload (struct omp_region *region)
4863 basic_block entry_bb, exit_bb, new_bb;
4864 struct function *child_cfun;
4865 tree child_fn, block, t;
4866 gimple_stmt_iterator gsi;
4867 gimple entry_stmt, stmt;
4868 edge e;
4869 tree (*gimple_omp_child_fn) (const_gimple);
4870 tree (*gimple_omp_data_arg) (const_gimple);
4871 switch (region->type)
4873 case GIMPLE_OACC_KERNELS:
4874 gimple_omp_child_fn = gimple_oacc_kernels_child_fn;
4875 gimple_omp_data_arg = gimple_oacc_kernels_data_arg;
4876 break;
4877 case GIMPLE_OACC_PARALLEL:
4878 gimple_omp_child_fn = gimple_oacc_parallel_child_fn;
4879 gimple_omp_data_arg = gimple_oacc_parallel_data_arg;
4880 break;
4881 default:
4882 gcc_unreachable ();
4885 entry_stmt = last_stmt (region->entry);
4886 child_fn = gimple_omp_child_fn (entry_stmt);
4887 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4889 /* Supported by expand_omp_taskreg, but not here. */
4890 gcc_assert (!child_cfun->cfg);
4891 gcc_assert (!gimple_in_ssa_p (cfun));
4893 entry_bb = region->entry;
4894 exit_bb = region->exit;
4896 /* Preserve indentation of expand_omp_target and expand_omp_taskreg. */
4897 if (1)
4899 unsigned srcidx, dstidx, num;
4901 /* If the parallel region needs data sent from the parent
4902 function, then the very first statement (except possible
4903 tree profile counter updates) of the parallel body
4904 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4905 &.OMP_DATA_O is passed as an argument to the child function,
4906 we need to replace it with the argument as seen by the child
4907 function.
4909 In most cases, this will end up being the identity assignment
4910 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4911 a function call that has been inlined, the original PARM_DECL
4912 .OMP_DATA_I may have been converted into a different local
4913 variable. In which case, we need to keep the assignment. */
4914 if (gimple_omp_data_arg (entry_stmt))
4916 basic_block entry_succ_bb = single_succ (entry_bb);
4917 gimple_stmt_iterator gsi;
4918 tree arg;
4919 gimple parcopy_stmt = NULL;
4920 tree sender = TREE_VEC_ELT (gimple_omp_data_arg (entry_stmt), 0);
4922 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4924 gcc_assert (!gsi_end_p (gsi));
4925 stmt = gsi_stmt (gsi);
4926 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4927 continue;
4929 if (gimple_num_ops (stmt) == 2)
4931 tree arg = gimple_assign_rhs1 (stmt);
4933 /* We're ignore the subcode because we're
4934 effectively doing a STRIP_NOPS. */
4936 if (TREE_CODE (arg) == ADDR_EXPR
4937 && TREE_OPERAND (arg, 0) == sender)
4939 parcopy_stmt = stmt;
4940 break;
4945 gcc_assert (parcopy_stmt != NULL);
4946 arg = DECL_ARGUMENTS (child_fn);
4948 gcc_assert (gimple_assign_lhs (parcopy_stmt) == arg);
4949 gsi_remove (&gsi, true);
4952 /* Declare local variables needed in CHILD_CFUN. */
4953 block = DECL_INITIAL (child_fn);
4954 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4955 /* The gimplifier could record temporaries in the block
4956 rather than in containing function's local_decls chain,
4957 which would mean cgraph missed finalizing them. Do it now. */
4958 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4959 if (TREE_CODE (t) == VAR_DECL
4960 && TREE_STATIC (t)
4961 && !DECL_EXTERNAL (t))
4962 varpool_finalize_decl (t);
4963 DECL_SAVED_TREE (child_fn) = NULL;
4964 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4965 gimple_set_body (child_fn, NULL);
4966 TREE_USED (block) = 1;
4968 /* Reset DECL_CONTEXT on function arguments. */
4969 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
4970 DECL_CONTEXT (t) = child_fn;
4972 /* Split ENTRY_BB at GIMPLE_OACC_PARALLEL,
4973 so that it can be moved to the child function. */
4974 gsi = gsi_last_bb (entry_bb);
4975 stmt = gsi_stmt (gsi);
4976 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OACC_KERNELS
4977 || gimple_code (stmt) == GIMPLE_OACC_PARALLEL));
4978 gsi_remove (&gsi, true);
4979 e = split_block (entry_bb, stmt);
4980 entry_bb = e->dest;
4981 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4983 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4984 if (exit_bb)
4986 gsi = gsi_last_bb (exit_bb);
4987 gcc_assert (!gsi_end_p (gsi)
4988 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4989 stmt = gimple_build_return (NULL);
4990 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4991 gsi_remove (&gsi, true);
4994 /* Move the region into CHILD_CFUN. */
4996 block = gimple_block (entry_stmt);
4998 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
4999 if (exit_bb)
5000 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5001 /* When the expansion process cannot guarantee an up-to-date
5002 loop tree arrange for the child function to fixup loops. */
5003 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5004 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5006 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5007 num = vec_safe_length (child_cfun->local_decls);
5008 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5010 t = (*child_cfun->local_decls)[srcidx];
5011 if (DECL_CONTEXT (t) == cfun->decl)
5012 continue;
5013 if (srcidx != dstidx)
5014 (*child_cfun->local_decls)[dstidx] = t;
5015 dstidx++;
5017 if (dstidx != num)
5018 vec_safe_truncate (child_cfun->local_decls, dstidx);
5020 /* Inform the callgraph about the new function. */
5021 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5022 cgraph_add_new_function (child_fn, true);
5024 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5025 fixed in a following pass. */
5026 push_cfun (child_cfun);
5027 rebuild_cgraph_edges ();
5029 /* Some EH regions might become dead, see PR34608. If
5030 pass_cleanup_cfg isn't the first pass to happen with the
5031 new child, these dead EH edges might cause problems.
5032 Clean them up now. */
5033 if (flag_exceptions)
5035 basic_block bb;
5036 bool changed = false;
5038 FOR_EACH_BB_FN (bb, cfun)
5039 changed |= gimple_purge_dead_eh_edges (bb);
5040 if (changed)
5041 cleanup_tree_cfg ();
5043 pop_cfun ();
5046 /* Emit a library call to launch CHILD_FN. */
5047 tree t1, t2, t3, t4,
5048 t_num_gangs, t_num_workers, t_vector_length,
5049 device, c, clauses;
5050 enum built_in_function start_ix;
5051 location_t clause_loc;
5052 tree (*gimple_omp_clauses) (const_gimple);
5053 switch (region->type)
5055 case GIMPLE_OACC_KERNELS:
5056 gimple_omp_clauses = gimple_oacc_kernels_clauses;
5057 start_ix = BUILT_IN_GOACC_KERNELS;
5058 break;
5059 case GIMPLE_OACC_PARALLEL:
5060 gimple_omp_clauses = gimple_oacc_parallel_clauses;
5061 start_ix = BUILT_IN_GOACC_PARALLEL;
5062 break;
5063 default:
5064 gcc_unreachable ();
5067 clauses = gimple_omp_clauses (entry_stmt);
5069 /* Default values for NUM_GANGS, NUM_WORKERS, and VECTOR_LENGTH. */
5070 t_num_gangs = t_num_workers = t_vector_length
5071 = fold_convert_loc (gimple_location (entry_stmt),
5072 integer_type_node, integer_one_node);
5073 switch (region->type)
5075 case GIMPLE_OACC_PARALLEL:
5076 /* ..., but if present, use the values specified by the respective
5077 clauses, making sure these are of the correct type. */
5078 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
5079 if (c)
5080 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
5081 integer_type_node,
5082 OMP_CLAUSE_NUM_GANGS_EXPR (c));
5083 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
5084 if (c)
5085 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
5086 integer_type_node,
5087 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
5088 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
5089 if (c)
5090 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
5091 integer_type_node,
5092 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
5093 break;
5095 default:
5096 break;
5099 /* By default, the value of DEVICE is -1 (let runtime library choose). */
5100 device = build_int_cst (integer_type_node, -1);
5102 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
5103 gcc_assert (c == NULL);
5104 if (c)
5106 device = OMP_CLAUSE_DEVICE_ID (c);
5107 clause_loc = OMP_CLAUSE_LOCATION (c);
5109 else
5110 clause_loc = gimple_location (entry_stmt);
5112 /* Ensure 'device' is of the correct type. */
5113 device = fold_convert_loc (clause_loc, integer_type_node, device);
5115 gsi = gsi_last_bb (new_bb);
5116 t = gimple_omp_data_arg (entry_stmt);
5117 if (t == NULL)
5119 t1 = size_zero_node;
5120 t2 = build_zero_cst (ptr_type_node);
5121 t3 = t2;
5122 t4 = t2;
5124 else
5126 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
5127 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
5128 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
5129 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
5130 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
5133 gimple g;
5134 /* FIXME: This will be address of
5135 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
5136 symbol, as soon as the linker plugin is able to create it for us. */
5137 tree openmp_target = build_zero_cst (ptr_type_node);
5138 tree fnaddr = build_fold_addr_expr (child_fn);
5139 g = gimple_build_call (builtin_decl_explicit (start_ix),
5140 10, device, fnaddr, openmp_target, t1, t2, t3, t4,
5141 t_num_gangs, t_num_workers, t_vector_length);
5142 gimple_set_location (g, gimple_location (entry_stmt));
5143 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
5146 /* Expand the OpenMP parallel or task directive starting at REGION. */
5148 static void
5149 expand_omp_taskreg (struct omp_region *region)
5151 basic_block entry_bb, exit_bb, new_bb;
5152 struct function *child_cfun;
5153 tree child_fn, block, t;
5154 gimple_stmt_iterator gsi;
5155 gimple entry_stmt, stmt;
5156 edge e;
5157 vec<tree, va_gc> *ws_args;
5159 entry_stmt = last_stmt (region->entry);
5160 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5161 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5163 entry_bb = region->entry;
5164 exit_bb = region->exit;
5166 if (is_combined_parallel (region))
5167 ws_args = region->ws_args;
5168 else
5169 ws_args = NULL;
5171 if (child_cfun->cfg)
5173 /* Due to inlining, it may happen that we have already outlined
5174 the region, in which case all we need to do is make the
5175 sub-graph unreachable and emit the parallel call. */
5176 edge entry_succ_e, exit_succ_e;
5177 gimple_stmt_iterator gsi;
5179 entry_succ_e = single_succ_edge (entry_bb);
5181 gsi = gsi_last_bb (entry_bb);
5182 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5183 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5184 gsi_remove (&gsi, true);
5186 new_bb = entry_bb;
5187 if (exit_bb)
5189 exit_succ_e = single_succ_edge (exit_bb);
5190 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5192 remove_edge_and_dominated_blocks (entry_succ_e);
5194 else
5196 unsigned srcidx, dstidx, num;
5198 /* If the parallel region needs data sent from the parent
5199 function, then the very first statement (except possible
5200 tree profile counter updates) of the parallel body
5201 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5202 &.OMP_DATA_O is passed as an argument to the child function,
5203 we need to replace it with the argument as seen by the child
5204 function.
5206 In most cases, this will end up being the identity assignment
5207 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5208 a function call that has been inlined, the original PARM_DECL
5209 .OMP_DATA_I may have been converted into a different local
5210 variable. In which case, we need to keep the assignment. */
5211 if (gimple_omp_taskreg_data_arg (entry_stmt))
5213 basic_block entry_succ_bb = single_succ (entry_bb);
5214 gimple_stmt_iterator gsi;
5215 tree arg, narg;
5216 gimple parcopy_stmt = NULL;
5218 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5220 gimple stmt;
5222 gcc_assert (!gsi_end_p (gsi));
5223 stmt = gsi_stmt (gsi);
5224 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5225 continue;
5227 if (gimple_num_ops (stmt) == 2)
5229 tree arg = gimple_assign_rhs1 (stmt);
5231 /* We're ignore the subcode because we're
5232 effectively doing a STRIP_NOPS. */
5234 if (TREE_CODE (arg) == ADDR_EXPR
5235 && TREE_OPERAND (arg, 0)
5236 == gimple_omp_taskreg_data_arg (entry_stmt))
5238 parcopy_stmt = stmt;
5239 break;
5244 gcc_assert (parcopy_stmt != NULL);
5245 arg = DECL_ARGUMENTS (child_fn);
5247 if (!gimple_in_ssa_p (cfun))
5249 if (gimple_assign_lhs (parcopy_stmt) == arg)
5250 gsi_remove (&gsi, true);
5251 else
5253 /* ?? Is setting the subcode really necessary ?? */
5254 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5255 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5258 else
5260 /* If we are in ssa form, we must load the value from the default
5261 definition of the argument. That should not be defined now,
5262 since the argument is not used uninitialized. */
5263 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5264 narg = make_ssa_name (arg, gimple_build_nop ());
5265 set_ssa_default_def (cfun, arg, narg);
5266 /* ?? Is setting the subcode really necessary ?? */
5267 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5268 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5269 update_stmt (parcopy_stmt);
5273 /* Declare local variables needed in CHILD_CFUN. */
5274 block = DECL_INITIAL (child_fn);
5275 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5276 /* The gimplifier could record temporaries in parallel/task block
5277 rather than in containing function's local_decls chain,
5278 which would mean cgraph missed finalizing them. Do it now. */
5279 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5280 if (TREE_CODE (t) == VAR_DECL
5281 && TREE_STATIC (t)
5282 && !DECL_EXTERNAL (t))
5283 varpool_finalize_decl (t);
5284 DECL_SAVED_TREE (child_fn) = NULL;
5285 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5286 gimple_set_body (child_fn, NULL);
5287 TREE_USED (block) = 1;
5289 /* Reset DECL_CONTEXT on function arguments. */
5290 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5291 DECL_CONTEXT (t) = child_fn;
5293 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5294 so that it can be moved to the child function. */
5295 gsi = gsi_last_bb (entry_bb);
5296 stmt = gsi_stmt (gsi);
5297 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5298 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5299 gsi_remove (&gsi, true);
5300 e = split_block (entry_bb, stmt);
5301 entry_bb = e->dest;
5302 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5304 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5305 if (exit_bb)
5307 gsi = gsi_last_bb (exit_bb);
5308 gcc_assert (!gsi_end_p (gsi)
5309 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5310 stmt = gimple_build_return (NULL);
5311 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5312 gsi_remove (&gsi, true);
5315 /* Move the parallel region into CHILD_CFUN. */
5317 if (gimple_in_ssa_p (cfun))
5319 init_tree_ssa (child_cfun);
5320 init_ssa_operands (child_cfun);
5321 child_cfun->gimple_df->in_ssa_p = true;
5322 block = NULL_TREE;
5324 else
5325 block = gimple_block (entry_stmt);
5327 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5328 if (exit_bb)
5329 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5330 /* When the OMP expansion process cannot guarantee an up-to-date
5331 loop tree arrange for the child function to fixup loops. */
5332 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5333 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5335 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5336 num = vec_safe_length (child_cfun->local_decls);
5337 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5339 t = (*child_cfun->local_decls)[srcidx];
5340 if (DECL_CONTEXT (t) == cfun->decl)
5341 continue;
5342 if (srcidx != dstidx)
5343 (*child_cfun->local_decls)[dstidx] = t;
5344 dstidx++;
5346 if (dstidx != num)
5347 vec_safe_truncate (child_cfun->local_decls, dstidx);
5349 /* Inform the callgraph about the new function. */
5350 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5351 cgraph_add_new_function (child_fn, true);
5353 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5354 fixed in a following pass. */
5355 push_cfun (child_cfun);
5356 if (optimize)
5357 optimize_omp_library_calls (entry_stmt);
5358 rebuild_cgraph_edges ();
5360 /* Some EH regions might become dead, see PR34608. If
5361 pass_cleanup_cfg isn't the first pass to happen with the
5362 new child, these dead EH edges might cause problems.
5363 Clean them up now. */
5364 if (flag_exceptions)
5366 basic_block bb;
5367 bool changed = false;
5369 FOR_EACH_BB_FN (bb, cfun)
5370 changed |= gimple_purge_dead_eh_edges (bb);
5371 if (changed)
5372 cleanup_tree_cfg ();
5374 if (gimple_in_ssa_p (cfun))
5375 update_ssa (TODO_update_ssa);
5376 pop_cfun ();
5379 /* Emit a library call to launch the children threads. */
5380 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5381 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
5382 else
5383 expand_task_call (new_bb, entry_stmt);
5384 if (gimple_in_ssa_p (cfun))
5385 update_ssa (TODO_update_ssa_only_virtuals);
5389 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5390 of the combined collapse > 1 loop constructs, generate code like:
5391 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5392 if (cond3 is <)
5393 adj = STEP3 - 1;
5394 else
5395 adj = STEP3 + 1;
5396 count3 = (adj + N32 - N31) / STEP3;
5397 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5398 if (cond2 is <)
5399 adj = STEP2 - 1;
5400 else
5401 adj = STEP2 + 1;
5402 count2 = (adj + N22 - N21) / STEP2;
5403 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5404 if (cond1 is <)
5405 adj = STEP1 - 1;
5406 else
5407 adj = STEP1 + 1;
5408 count1 = (adj + N12 - N11) / STEP1;
5409 count = count1 * count2 * count3;
5410 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5411 count = 0;
5412 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5413 of the combined loop constructs, just initialize COUNTS array
5414 from the _looptemp_ clauses. */
5416 /* NOTE: It *could* be better to moosh all of the BBs together,
5417 creating one larger BB with all the computation and the unexpected
5418 jump at the end. I.e.
5420 bool zero3, zero2, zero1, zero;
5422 zero3 = N32 c3 N31;
5423 count3 = (N32 - N31) /[cl] STEP3;
5424 zero2 = N22 c2 N21;
5425 count2 = (N22 - N21) /[cl] STEP2;
5426 zero1 = N12 c1 N11;
5427 count1 = (N12 - N11) /[cl] STEP1;
5428 zero = zero3 || zero2 || zero1;
5429 count = count1 * count2 * count3;
5430 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5432 After all, we expect the zero=false, and thus we expect to have to
5433 evaluate all of the comparison expressions, so short-circuiting
5434 oughtn't be a win. Since the condition isn't protecting a
5435 denominator, we're not concerned about divide-by-zero, so we can
5436 fully evaluate count even if a numerator turned out to be wrong.
5438 It seems like putting this all together would create much better
5439 scheduling opportunities, and less pressure on the chip's branch
5440 predictor. */
5442 static void
5443 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5444 basic_block &entry_bb, tree *counts,
5445 basic_block &zero_iter_bb, int &first_zero_iter,
5446 basic_block &l2_dom_bb)
5448 tree t, type = TREE_TYPE (fd->loop.v);
5449 gimple stmt;
5450 edge e, ne;
5451 int i;
5453 /* Collapsed loops need work for expansion into SSA form. */
5454 gcc_assert (!gimple_in_ssa_p (cfun));
5456 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5457 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5459 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5460 isn't supposed to be handled, as the inner loop doesn't
5461 use it. */
5462 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5463 OMP_CLAUSE__LOOPTEMP_);
5464 gcc_assert (innerc);
5465 for (i = 0; i < fd->collapse; i++)
5467 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5468 OMP_CLAUSE__LOOPTEMP_);
5469 gcc_assert (innerc);
5470 if (i)
5471 counts[i] = OMP_CLAUSE_DECL (innerc);
5472 else
5473 counts[0] = NULL_TREE;
5475 return;
5478 for (i = 0; i < fd->collapse; i++)
5480 tree itype = TREE_TYPE (fd->loops[i].v);
5482 if (SSA_VAR_P (fd->loop.n2)
5483 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5484 fold_convert (itype, fd->loops[i].n1),
5485 fold_convert (itype, fd->loops[i].n2)))
5486 == NULL_TREE || !integer_onep (t)))
5488 tree n1, n2;
5489 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5490 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5491 true, GSI_SAME_STMT);
5492 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5493 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5494 true, GSI_SAME_STMT);
5495 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5496 NULL_TREE, NULL_TREE);
5497 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5498 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5499 expand_omp_regimplify_p, NULL, NULL)
5500 || walk_tree (gimple_cond_rhs_ptr (stmt),
5501 expand_omp_regimplify_p, NULL, NULL))
5503 *gsi = gsi_for_stmt (stmt);
5504 gimple_regimplify_operands (stmt, gsi);
5506 e = split_block (entry_bb, stmt);
5507 if (zero_iter_bb == NULL)
5509 first_zero_iter = i;
5510 zero_iter_bb = create_empty_bb (entry_bb);
5511 if (current_loops)
5512 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5513 *gsi = gsi_after_labels (zero_iter_bb);
5514 stmt = gimple_build_assign (fd->loop.n2,
5515 build_zero_cst (type));
5516 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5517 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5518 entry_bb);
5520 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5521 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5522 e->flags = EDGE_TRUE_VALUE;
5523 e->probability = REG_BR_PROB_BASE - ne->probability;
5524 if (l2_dom_bb == NULL)
5525 l2_dom_bb = entry_bb;
5526 entry_bb = e->dest;
5527 *gsi = gsi_last_bb (entry_bb);
5530 if (POINTER_TYPE_P (itype))
5531 itype = signed_type_for (itype);
5532 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5533 ? -1 : 1));
5534 t = fold_build2 (PLUS_EXPR, itype,
5535 fold_convert (itype, fd->loops[i].step), t);
5536 t = fold_build2 (PLUS_EXPR, itype, t,
5537 fold_convert (itype, fd->loops[i].n2));
5538 t = fold_build2 (MINUS_EXPR, itype, t,
5539 fold_convert (itype, fd->loops[i].n1));
5540 /* ?? We could probably use CEIL_DIV_EXPR instead of
5541 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5542 generate the same code in the end because generically we
5543 don't know that the values involved must be negative for
5544 GT?? */
5545 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5546 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5547 fold_build1 (NEGATE_EXPR, itype, t),
5548 fold_build1 (NEGATE_EXPR, itype,
5549 fold_convert (itype,
5550 fd->loops[i].step)));
5551 else
5552 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5553 fold_convert (itype, fd->loops[i].step));
5554 t = fold_convert (type, t);
5555 if (TREE_CODE (t) == INTEGER_CST)
5556 counts[i] = t;
5557 else
5559 counts[i] = create_tmp_reg (type, ".count");
5560 expand_omp_build_assign (gsi, counts[i], t);
5562 if (SSA_VAR_P (fd->loop.n2))
5564 if (i == 0)
5565 t = counts[0];
5566 else
5567 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5568 expand_omp_build_assign (gsi, fd->loop.n2, t);
5574 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5575 T = V;
5576 V3 = N31 + (T % count3) * STEP3;
5577 T = T / count3;
5578 V2 = N21 + (T % count2) * STEP2;
5579 T = T / count2;
5580 V1 = N11 + T * STEP1;
5581 if this loop doesn't have an inner loop construct combined with it.
5582 If it does have an inner loop construct combined with it and the
5583 iteration count isn't known constant, store values from counts array
5584 into its _looptemp_ temporaries instead. */
5586 static void
5587 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5588 tree *counts, gimple inner_stmt, tree startvar)
5590 int i;
5591 if (gimple_omp_for_combined_p (fd->for_stmt))
5593 /* If fd->loop.n2 is constant, then no propagation of the counts
5594 is needed, they are constant. */
5595 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5596 return;
5598 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5599 ? gimple_omp_parallel_clauses (inner_stmt)
5600 : gimple_omp_for_clauses (inner_stmt);
5601 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5602 isn't supposed to be handled, as the inner loop doesn't
5603 use it. */
5604 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5605 gcc_assert (innerc);
5606 for (i = 0; i < fd->collapse; i++)
5608 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5609 OMP_CLAUSE__LOOPTEMP_);
5610 gcc_assert (innerc);
5611 if (i)
5613 tree tem = OMP_CLAUSE_DECL (innerc);
5614 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5615 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5616 false, GSI_CONTINUE_LINKING);
5617 gimple stmt = gimple_build_assign (tem, t);
5618 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5621 return;
5624 tree type = TREE_TYPE (fd->loop.v);
5625 tree tem = create_tmp_reg (type, ".tem");
5626 gimple stmt = gimple_build_assign (tem, startvar);
5627 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5629 for (i = fd->collapse - 1; i >= 0; i--)
5631 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5632 itype = vtype;
5633 if (POINTER_TYPE_P (vtype))
5634 itype = signed_type_for (vtype);
5635 if (i != 0)
5636 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5637 else
5638 t = tem;
5639 t = fold_convert (itype, t);
5640 t = fold_build2 (MULT_EXPR, itype, t,
5641 fold_convert (itype, fd->loops[i].step));
5642 if (POINTER_TYPE_P (vtype))
5643 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5644 else
5645 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5646 t = force_gimple_operand_gsi (gsi, t,
5647 DECL_P (fd->loops[i].v)
5648 && TREE_ADDRESSABLE (fd->loops[i].v),
5649 NULL_TREE, false,
5650 GSI_CONTINUE_LINKING);
5651 stmt = gimple_build_assign (fd->loops[i].v, t);
5652 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5653 if (i != 0)
5655 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5656 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5657 false, GSI_CONTINUE_LINKING);
5658 stmt = gimple_build_assign (tem, t);
5659 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5665 /* Helper function for expand_omp_for_*. Generate code like:
5666 L10:
5667 V3 += STEP3;
5668 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5669 L11:
5670 V3 = N31;
5671 V2 += STEP2;
5672 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5673 L12:
5674 V2 = N21;
5675 V1 += STEP1;
5676 goto BODY_BB; */
5678 static basic_block
5679 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5680 basic_block body_bb)
5682 basic_block last_bb, bb, collapse_bb = NULL;
5683 int i;
5684 gimple_stmt_iterator gsi;
5685 edge e;
5686 tree t;
5687 gimple stmt;
5689 last_bb = cont_bb;
5690 for (i = fd->collapse - 1; i >= 0; i--)
5692 tree vtype = TREE_TYPE (fd->loops[i].v);
5694 bb = create_empty_bb (last_bb);
5695 if (current_loops)
5696 add_bb_to_loop (bb, last_bb->loop_father);
5697 gsi = gsi_start_bb (bb);
5699 if (i < fd->collapse - 1)
5701 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5702 e->probability = REG_BR_PROB_BASE / 8;
5704 t = fd->loops[i + 1].n1;
5705 t = force_gimple_operand_gsi (&gsi, t,
5706 DECL_P (fd->loops[i + 1].v)
5707 && TREE_ADDRESSABLE (fd->loops[i
5708 + 1].v),
5709 NULL_TREE, false,
5710 GSI_CONTINUE_LINKING);
5711 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5712 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5714 else
5715 collapse_bb = bb;
5717 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5719 if (POINTER_TYPE_P (vtype))
5720 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5721 else
5722 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5723 t = force_gimple_operand_gsi (&gsi, t,
5724 DECL_P (fd->loops[i].v)
5725 && TREE_ADDRESSABLE (fd->loops[i].v),
5726 NULL_TREE, false, GSI_CONTINUE_LINKING);
5727 stmt = gimple_build_assign (fd->loops[i].v, t);
5728 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5730 if (i > 0)
5732 t = fd->loops[i].n2;
5733 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5734 false, GSI_CONTINUE_LINKING);
5735 tree v = fd->loops[i].v;
5736 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5737 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5738 false, GSI_CONTINUE_LINKING);
5739 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5740 stmt = gimple_build_cond_empty (t);
5741 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5742 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5743 e->probability = REG_BR_PROB_BASE * 7 / 8;
5745 else
5746 make_edge (bb, body_bb, EDGE_FALLTHRU);
5747 last_bb = bb;
5750 return collapse_bb;
5754 /* A subroutine of expand_omp_for. Generate code for a parallel
5755 loop with any schedule. Given parameters:
5757 for (V = N1; V cond N2; V += STEP) BODY;
5759 where COND is "<" or ">", we generate pseudocode
5761 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5762 if (more) goto L0; else goto L3;
5764 V = istart0;
5765 iend = iend0;
5767 BODY;
5768 V += STEP;
5769 if (V cond iend) goto L1; else goto L2;
5771 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5774 If this is a combined omp parallel loop, instead of the call to
5775 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5776 If this is gimple_omp_for_combined_p loop, then instead of assigning
5777 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5778 inner GIMPLE_OMP_FOR and V += STEP; and
5779 if (V cond iend) goto L1; else goto L2; are removed.
5781 For collapsed loops, given parameters:
5782 collapse(3)
5783 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5784 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5785 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5786 BODY;
5788 we generate pseudocode
5790 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5791 if (cond3 is <)
5792 adj = STEP3 - 1;
5793 else
5794 adj = STEP3 + 1;
5795 count3 = (adj + N32 - N31) / STEP3;
5796 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5797 if (cond2 is <)
5798 adj = STEP2 - 1;
5799 else
5800 adj = STEP2 + 1;
5801 count2 = (adj + N22 - N21) / STEP2;
5802 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5803 if (cond1 is <)
5804 adj = STEP1 - 1;
5805 else
5806 adj = STEP1 + 1;
5807 count1 = (adj + N12 - N11) / STEP1;
5808 count = count1 * count2 * count3;
5809 goto Z1;
5811 count = 0;
5813 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5814 if (more) goto L0; else goto L3;
5816 V = istart0;
5817 T = V;
5818 V3 = N31 + (T % count3) * STEP3;
5819 T = T / count3;
5820 V2 = N21 + (T % count2) * STEP2;
5821 T = T / count2;
5822 V1 = N11 + T * STEP1;
5823 iend = iend0;
5825 BODY;
5826 V += 1;
5827 if (V < iend) goto L10; else goto L2;
5828 L10:
5829 V3 += STEP3;
5830 if (V3 cond3 N32) goto L1; else goto L11;
5831 L11:
5832 V3 = N31;
5833 V2 += STEP2;
5834 if (V2 cond2 N22) goto L1; else goto L12;
5835 L12:
5836 V2 = N21;
5837 V1 += STEP1;
5838 goto L1;
5840 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5845 static void
5846 expand_omp_for_generic (struct omp_region *region,
5847 struct omp_for_data *fd,
5848 enum built_in_function start_fn,
5849 enum built_in_function next_fn,
5850 gimple inner_stmt)
5852 tree type, istart0, iend0, iend;
5853 tree t, vmain, vback, bias = NULL_TREE;
5854 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5855 basic_block l2_bb = NULL, l3_bb = NULL;
5856 gimple_stmt_iterator gsi;
5857 gimple stmt;
5858 bool in_combined_parallel = is_combined_parallel (region);
5859 bool broken_loop = region->cont == NULL;
5860 edge e, ne;
5861 tree *counts = NULL;
5862 int i;
5864 gcc_assert (!broken_loop || !in_combined_parallel);
5865 gcc_assert (fd->iter_type == long_integer_type_node
5866 || !in_combined_parallel);
5868 type = TREE_TYPE (fd->loop.v);
5869 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5870 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5871 TREE_ADDRESSABLE (istart0) = 1;
5872 TREE_ADDRESSABLE (iend0) = 1;
5874 /* See if we need to bias by LLONG_MIN. */
5875 if (fd->iter_type == long_long_unsigned_type_node
5876 && TREE_CODE (type) == INTEGER_TYPE
5877 && !TYPE_UNSIGNED (type))
5879 tree n1, n2;
5881 if (fd->loop.cond_code == LT_EXPR)
5883 n1 = fd->loop.n1;
5884 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5886 else
5888 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5889 n2 = fd->loop.n1;
5891 if (TREE_CODE (n1) != INTEGER_CST
5892 || TREE_CODE (n2) != INTEGER_CST
5893 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5894 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5897 entry_bb = region->entry;
5898 cont_bb = region->cont;
5899 collapse_bb = NULL;
5900 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5901 gcc_assert (broken_loop
5902 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5903 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5904 l1_bb = single_succ (l0_bb);
5905 if (!broken_loop)
5907 l2_bb = create_empty_bb (cont_bb);
5908 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5909 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5911 else
5912 l2_bb = NULL;
5913 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5914 exit_bb = region->exit;
5916 gsi = gsi_last_bb (entry_bb);
5918 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5919 if (fd->collapse > 1)
5921 int first_zero_iter = -1;
5922 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5924 counts = XALLOCAVEC (tree, fd->collapse);
5925 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5926 zero_iter_bb, first_zero_iter,
5927 l2_dom_bb);
5929 if (zero_iter_bb)
5931 /* Some counts[i] vars might be uninitialized if
5932 some loop has zero iterations. But the body shouldn't
5933 be executed in that case, so just avoid uninit warnings. */
5934 for (i = first_zero_iter; i < fd->collapse; i++)
5935 if (SSA_VAR_P (counts[i]))
5936 TREE_NO_WARNING (counts[i]) = 1;
5937 gsi_prev (&gsi);
5938 e = split_block (entry_bb, gsi_stmt (gsi));
5939 entry_bb = e->dest;
5940 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5941 gsi = gsi_last_bb (entry_bb);
5942 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5943 get_immediate_dominator (CDI_DOMINATORS,
5944 zero_iter_bb));
5947 if (in_combined_parallel)
5949 /* In a combined parallel loop, emit a call to
5950 GOMP_loop_foo_next. */
5951 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5952 build_fold_addr_expr (istart0),
5953 build_fold_addr_expr (iend0));
5955 else
5957 tree t0, t1, t2, t3, t4;
5958 /* If this is not a combined parallel loop, emit a call to
5959 GOMP_loop_foo_start in ENTRY_BB. */
5960 t4 = build_fold_addr_expr (iend0);
5961 t3 = build_fold_addr_expr (istart0);
5962 t2 = fold_convert (fd->iter_type, fd->loop.step);
5963 t1 = fd->loop.n2;
5964 t0 = fd->loop.n1;
5965 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5967 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5968 OMP_CLAUSE__LOOPTEMP_);
5969 gcc_assert (innerc);
5970 t0 = OMP_CLAUSE_DECL (innerc);
5971 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5972 OMP_CLAUSE__LOOPTEMP_);
5973 gcc_assert (innerc);
5974 t1 = OMP_CLAUSE_DECL (innerc);
5976 if (POINTER_TYPE_P (TREE_TYPE (t0))
5977 && TYPE_PRECISION (TREE_TYPE (t0))
5978 != TYPE_PRECISION (fd->iter_type))
5980 /* Avoid casting pointers to integer of a different size. */
5981 tree itype = signed_type_for (type);
5982 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5983 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5985 else
5987 t1 = fold_convert (fd->iter_type, t1);
5988 t0 = fold_convert (fd->iter_type, t0);
5990 if (bias)
5992 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5993 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5995 if (fd->iter_type == long_integer_type_node)
5997 if (fd->chunk_size)
5999 t = fold_convert (fd->iter_type, fd->chunk_size);
6000 t = build_call_expr (builtin_decl_explicit (start_fn),
6001 6, t0, t1, t2, t, t3, t4);
6003 else
6004 t = build_call_expr (builtin_decl_explicit (start_fn),
6005 5, t0, t1, t2, t3, t4);
6007 else
6009 tree t5;
6010 tree c_bool_type;
6011 tree bfn_decl;
6013 /* The GOMP_loop_ull_*start functions have additional boolean
6014 argument, true for < loops and false for > loops.
6015 In Fortran, the C bool type can be different from
6016 boolean_type_node. */
6017 bfn_decl = builtin_decl_explicit (start_fn);
6018 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6019 t5 = build_int_cst (c_bool_type,
6020 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6021 if (fd->chunk_size)
6023 tree bfn_decl = builtin_decl_explicit (start_fn);
6024 t = fold_convert (fd->iter_type, fd->chunk_size);
6025 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6027 else
6028 t = build_call_expr (builtin_decl_explicit (start_fn),
6029 6, t5, t0, t1, t2, t3, t4);
6032 if (TREE_TYPE (t) != boolean_type_node)
6033 t = fold_build2 (NE_EXPR, boolean_type_node,
6034 t, build_int_cst (TREE_TYPE (t), 0));
6035 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6036 true, GSI_SAME_STMT);
6037 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6039 /* Remove the GIMPLE_OMP_FOR statement. */
6040 gsi_remove (&gsi, true);
6042 /* Iteration setup for sequential loop goes in L0_BB. */
6043 tree startvar = fd->loop.v;
6044 tree endvar = NULL_TREE;
6046 if (gimple_omp_for_combined_p (fd->for_stmt))
6048 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6049 && gimple_omp_for_kind (inner_stmt)
6050 == GF_OMP_FOR_KIND_SIMD);
6051 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6052 OMP_CLAUSE__LOOPTEMP_);
6053 gcc_assert (innerc);
6054 startvar = OMP_CLAUSE_DECL (innerc);
6055 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6056 OMP_CLAUSE__LOOPTEMP_);
6057 gcc_assert (innerc);
6058 endvar = OMP_CLAUSE_DECL (innerc);
6061 gsi = gsi_start_bb (l0_bb);
6062 t = istart0;
6063 if (bias)
6064 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6065 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6066 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6067 t = fold_convert (TREE_TYPE (startvar), t);
6068 t = force_gimple_operand_gsi (&gsi, t,
6069 DECL_P (startvar)
6070 && TREE_ADDRESSABLE (startvar),
6071 NULL_TREE, false, GSI_CONTINUE_LINKING);
6072 stmt = gimple_build_assign (startvar, t);
6073 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6075 t = iend0;
6076 if (bias)
6077 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6078 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6079 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6080 t = fold_convert (TREE_TYPE (startvar), t);
6081 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6082 false, GSI_CONTINUE_LINKING);
6083 if (endvar)
6085 stmt = gimple_build_assign (endvar, iend);
6086 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6088 if (fd->collapse > 1)
6089 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6091 if (!broken_loop)
6093 /* Code to control the increment and predicate for the sequential
6094 loop goes in the CONT_BB. */
6095 gsi = gsi_last_bb (cont_bb);
6096 stmt = gsi_stmt (gsi);
6097 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6098 vmain = gimple_omp_continue_control_use (stmt);
6099 vback = gimple_omp_continue_control_def (stmt);
6101 if (!gimple_omp_for_combined_p (fd->for_stmt))
6103 if (POINTER_TYPE_P (type))
6104 t = fold_build_pointer_plus (vmain, fd->loop.step);
6105 else
6106 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6107 t = force_gimple_operand_gsi (&gsi, t,
6108 DECL_P (vback)
6109 && TREE_ADDRESSABLE (vback),
6110 NULL_TREE, true, GSI_SAME_STMT);
6111 stmt = gimple_build_assign (vback, t);
6112 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6114 t = build2 (fd->loop.cond_code, boolean_type_node,
6115 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6116 iend);
6117 stmt = gimple_build_cond_empty (t);
6118 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6121 /* Remove GIMPLE_OMP_CONTINUE. */
6122 gsi_remove (&gsi, true);
6124 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6125 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6127 /* Emit code to get the next parallel iteration in L2_BB. */
6128 gsi = gsi_start_bb (l2_bb);
6130 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6131 build_fold_addr_expr (istart0),
6132 build_fold_addr_expr (iend0));
6133 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6134 false, GSI_CONTINUE_LINKING);
6135 if (TREE_TYPE (t) != boolean_type_node)
6136 t = fold_build2 (NE_EXPR, boolean_type_node,
6137 t, build_int_cst (TREE_TYPE (t), 0));
6138 stmt = gimple_build_cond_empty (t);
6139 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6142 /* Add the loop cleanup function. */
6143 gsi = gsi_last_bb (exit_bb);
6144 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6145 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6146 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6147 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6148 else
6149 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6150 stmt = gimple_build_call (t, 0);
6151 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6152 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6153 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
6154 gsi_remove (&gsi, true);
6156 /* Connect the new blocks. */
6157 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6158 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6160 if (!broken_loop)
6162 gimple_seq phis;
6164 e = find_edge (cont_bb, l3_bb);
6165 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6167 phis = phi_nodes (l3_bb);
6168 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6170 gimple phi = gsi_stmt (gsi);
6171 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6172 PHI_ARG_DEF_FROM_EDGE (phi, e));
6174 remove_edge (e);
6176 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6177 if (current_loops)
6178 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6179 e = find_edge (cont_bb, l1_bb);
6180 if (gimple_omp_for_combined_p (fd->for_stmt))
6182 remove_edge (e);
6183 e = NULL;
6185 else if (fd->collapse > 1)
6187 remove_edge (e);
6188 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6190 else
6191 e->flags = EDGE_TRUE_VALUE;
6192 if (e)
6194 e->probability = REG_BR_PROB_BASE * 7 / 8;
6195 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6197 else
6199 e = find_edge (cont_bb, l2_bb);
6200 e->flags = EDGE_FALLTHRU;
6202 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6204 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6205 recompute_dominator (CDI_DOMINATORS, l2_bb));
6206 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6207 recompute_dominator (CDI_DOMINATORS, l3_bb));
6208 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6209 recompute_dominator (CDI_DOMINATORS, l0_bb));
6210 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6211 recompute_dominator (CDI_DOMINATORS, l1_bb));
6213 struct loop *outer_loop = alloc_loop ();
6214 outer_loop->header = l0_bb;
6215 outer_loop->latch = l2_bb;
6216 add_loop (outer_loop, l0_bb->loop_father);
6218 if (!gimple_omp_for_combined_p (fd->for_stmt))
6220 struct loop *loop = alloc_loop ();
6221 loop->header = l1_bb;
6222 /* The loop may have multiple latches. */
6223 add_loop (loop, outer_loop);
6229 /* A subroutine of expand_omp_for. Generate code for a parallel
6230 loop with static schedule and no specified chunk size. Given
6231 parameters:
6233 for (V = N1; V cond N2; V += STEP) BODY;
6235 where COND is "<" or ">", we generate pseudocode
6237 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6238 if (cond is <)
6239 adj = STEP - 1;
6240 else
6241 adj = STEP + 1;
6242 if ((__typeof (V)) -1 > 0 && cond is >)
6243 n = -(adj + N2 - N1) / -STEP;
6244 else
6245 n = (adj + N2 - N1) / STEP;
6246 q = n / nthreads;
6247 tt = n % nthreads;
6248 if (threadid < tt) goto L3; else goto L4;
6250 tt = 0;
6251 q = q + 1;
6253 s0 = q * threadid + tt;
6254 e0 = s0 + q;
6255 V = s0 * STEP + N1;
6256 if (s0 >= e0) goto L2; else goto L0;
6258 e = e0 * STEP + N1;
6260 BODY;
6261 V += STEP;
6262 if (V cond e) goto L1;
6266 static void
6267 expand_omp_for_static_nochunk (struct omp_region *region,
6268 struct omp_for_data *fd,
6269 gimple inner_stmt)
6271 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6272 tree type, itype, vmain, vback;
6273 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6274 basic_block body_bb, cont_bb, collapse_bb = NULL;
6275 basic_block fin_bb;
6276 gimple_stmt_iterator gsi;
6277 gimple stmt;
6278 edge ep;
6279 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6280 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6281 bool broken_loop = region->cont == NULL;
6282 tree *counts = NULL;
6283 tree n1, n2, step;
6285 itype = type = TREE_TYPE (fd->loop.v);
6286 if (POINTER_TYPE_P (type))
6287 itype = signed_type_for (type);
6289 entry_bb = region->entry;
6290 cont_bb = region->cont;
6291 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6292 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6293 gcc_assert (broken_loop
6294 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6295 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6296 body_bb = single_succ (seq_start_bb);
6297 if (!broken_loop)
6299 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6300 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6302 exit_bb = region->exit;
6304 /* Iteration space partitioning goes in ENTRY_BB. */
6305 gsi = gsi_last_bb (entry_bb);
6306 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6308 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6310 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6311 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6314 if (fd->collapse > 1)
6316 int first_zero_iter = -1;
6317 basic_block l2_dom_bb = NULL;
6319 counts = XALLOCAVEC (tree, fd->collapse);
6320 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6321 fin_bb, first_zero_iter,
6322 l2_dom_bb);
6323 t = NULL_TREE;
6325 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6326 t = integer_one_node;
6327 else
6328 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6329 fold_convert (type, fd->loop.n1),
6330 fold_convert (type, fd->loop.n2));
6331 if (fd->collapse == 1
6332 && TYPE_UNSIGNED (type)
6333 && (t == NULL_TREE || !integer_onep (t)))
6335 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6336 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6337 true, GSI_SAME_STMT);
6338 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6339 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6340 true, GSI_SAME_STMT);
6341 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6342 NULL_TREE, NULL_TREE);
6343 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6344 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6345 expand_omp_regimplify_p, NULL, NULL)
6346 || walk_tree (gimple_cond_rhs_ptr (stmt),
6347 expand_omp_regimplify_p, NULL, NULL))
6349 gsi = gsi_for_stmt (stmt);
6350 gimple_regimplify_operands (stmt, &gsi);
6352 ep = split_block (entry_bb, stmt);
6353 ep->flags = EDGE_TRUE_VALUE;
6354 entry_bb = ep->dest;
6355 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6356 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6357 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6358 if (gimple_in_ssa_p (cfun))
6360 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6361 for (gsi = gsi_start_phis (fin_bb);
6362 !gsi_end_p (gsi); gsi_next (&gsi))
6364 gimple phi = gsi_stmt (gsi);
6365 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6366 ep, UNKNOWN_LOCATION);
6369 gsi = gsi_last_bb (entry_bb);
6372 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6373 t = fold_convert (itype, t);
6374 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6375 true, GSI_SAME_STMT);
6377 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6378 t = fold_convert (itype, t);
6379 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6380 true, GSI_SAME_STMT);
6382 n1 = fd->loop.n1;
6383 n2 = fd->loop.n2;
6384 step = fd->loop.step;
6385 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6387 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6388 OMP_CLAUSE__LOOPTEMP_);
6389 gcc_assert (innerc);
6390 n1 = OMP_CLAUSE_DECL (innerc);
6391 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6392 OMP_CLAUSE__LOOPTEMP_);
6393 gcc_assert (innerc);
6394 n2 = OMP_CLAUSE_DECL (innerc);
6396 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6397 true, NULL_TREE, true, GSI_SAME_STMT);
6398 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6399 true, NULL_TREE, true, GSI_SAME_STMT);
6400 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6401 true, NULL_TREE, true, GSI_SAME_STMT);
6403 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6404 t = fold_build2 (PLUS_EXPR, itype, step, t);
6405 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6406 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6407 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6408 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6409 fold_build1 (NEGATE_EXPR, itype, t),
6410 fold_build1 (NEGATE_EXPR, itype, step));
6411 else
6412 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6413 t = fold_convert (itype, t);
6414 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6416 q = create_tmp_reg (itype, "q");
6417 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6418 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6419 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6421 tt = create_tmp_reg (itype, "tt");
6422 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6423 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6424 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6426 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6427 stmt = gimple_build_cond_empty (t);
6428 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6430 second_bb = split_block (entry_bb, stmt)->dest;
6431 gsi = gsi_last_bb (second_bb);
6432 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6434 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6435 GSI_SAME_STMT);
6436 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
6437 build_int_cst (itype, 1));
6438 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6440 third_bb = split_block (second_bb, stmt)->dest;
6441 gsi = gsi_last_bb (third_bb);
6442 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6444 t = build2 (MULT_EXPR, itype, q, threadid);
6445 t = build2 (PLUS_EXPR, itype, t, tt);
6446 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6448 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6449 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6451 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6452 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6454 /* Remove the GIMPLE_OMP_FOR statement. */
6455 gsi_remove (&gsi, true);
6457 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6458 gsi = gsi_start_bb (seq_start_bb);
6460 tree startvar = fd->loop.v;
6461 tree endvar = NULL_TREE;
6463 if (gimple_omp_for_combined_p (fd->for_stmt))
6465 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6466 ? gimple_omp_parallel_clauses (inner_stmt)
6467 : gimple_omp_for_clauses (inner_stmt);
6468 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6469 gcc_assert (innerc);
6470 startvar = OMP_CLAUSE_DECL (innerc);
6471 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6472 OMP_CLAUSE__LOOPTEMP_);
6473 gcc_assert (innerc);
6474 endvar = OMP_CLAUSE_DECL (innerc);
6476 t = fold_convert (itype, s0);
6477 t = fold_build2 (MULT_EXPR, itype, t, step);
6478 if (POINTER_TYPE_P (type))
6479 t = fold_build_pointer_plus (n1, t);
6480 else
6481 t = fold_build2 (PLUS_EXPR, type, t, n1);
6482 t = fold_convert (TREE_TYPE (startvar), t);
6483 t = force_gimple_operand_gsi (&gsi, t,
6484 DECL_P (startvar)
6485 && TREE_ADDRESSABLE (startvar),
6486 NULL_TREE, false, GSI_CONTINUE_LINKING);
6487 stmt = gimple_build_assign (startvar, t);
6488 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6490 t = fold_convert (itype, e0);
6491 t = fold_build2 (MULT_EXPR, itype, t, step);
6492 if (POINTER_TYPE_P (type))
6493 t = fold_build_pointer_plus (n1, t);
6494 else
6495 t = fold_build2 (PLUS_EXPR, type, t, n1);
6496 t = fold_convert (TREE_TYPE (startvar), t);
6497 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6498 false, GSI_CONTINUE_LINKING);
6499 if (endvar)
6501 stmt = gimple_build_assign (endvar, e);
6502 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6504 if (fd->collapse > 1)
6505 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6507 if (!broken_loop)
6509 /* The code controlling the sequential loop replaces the
6510 GIMPLE_OMP_CONTINUE. */
6511 gsi = gsi_last_bb (cont_bb);
6512 stmt = gsi_stmt (gsi);
6513 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6514 vmain = gimple_omp_continue_control_use (stmt);
6515 vback = gimple_omp_continue_control_def (stmt);
6517 if (!gimple_omp_for_combined_p (fd->for_stmt))
6519 if (POINTER_TYPE_P (type))
6520 t = fold_build_pointer_plus (vmain, step);
6521 else
6522 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6523 t = force_gimple_operand_gsi (&gsi, t,
6524 DECL_P (vback)
6525 && TREE_ADDRESSABLE (vback),
6526 NULL_TREE, true, GSI_SAME_STMT);
6527 stmt = gimple_build_assign (vback, t);
6528 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6530 t = build2 (fd->loop.cond_code, boolean_type_node,
6531 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6532 ? t : vback, e);
6533 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6536 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6537 gsi_remove (&gsi, true);
6539 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6540 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6543 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6544 gsi = gsi_last_bb (exit_bb);
6545 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6547 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6548 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6550 gsi_remove (&gsi, true);
6552 /* Connect all the blocks. */
6553 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6554 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6555 ep = find_edge (entry_bb, second_bb);
6556 ep->flags = EDGE_TRUE_VALUE;
6557 ep->probability = REG_BR_PROB_BASE / 4;
6558 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6559 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6561 if (!broken_loop)
6563 ep = find_edge (cont_bb, body_bb);
6564 if (gimple_omp_for_combined_p (fd->for_stmt))
6566 remove_edge (ep);
6567 ep = NULL;
6569 else if (fd->collapse > 1)
6571 remove_edge (ep);
6572 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6574 else
6575 ep->flags = EDGE_TRUE_VALUE;
6576 find_edge (cont_bb, fin_bb)->flags
6577 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6580 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6581 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6582 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6584 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6585 recompute_dominator (CDI_DOMINATORS, body_bb));
6586 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6587 recompute_dominator (CDI_DOMINATORS, fin_bb));
6589 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6591 struct loop *loop = alloc_loop ();
6592 loop->header = body_bb;
6593 if (collapse_bb == NULL)
6594 loop->latch = cont_bb;
6595 add_loop (loop, body_bb->loop_father);
6600 /* A subroutine of expand_omp_for. Generate code for a parallel
6601 loop with static schedule and a specified chunk size. Given
6602 parameters:
6604 for (V = N1; V cond N2; V += STEP) BODY;
6606 where COND is "<" or ">", we generate pseudocode
6608 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6609 if (cond is <)
6610 adj = STEP - 1;
6611 else
6612 adj = STEP + 1;
6613 if ((__typeof (V)) -1 > 0 && cond is >)
6614 n = -(adj + N2 - N1) / -STEP;
6615 else
6616 n = (adj + N2 - N1) / STEP;
6617 trip = 0;
6618 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6619 here so that V is defined
6620 if the loop is not entered
6622 s0 = (trip * nthreads + threadid) * CHUNK;
6623 e0 = min(s0 + CHUNK, n);
6624 if (s0 < n) goto L1; else goto L4;
6626 V = s0 * STEP + N1;
6627 e = e0 * STEP + N1;
6629 BODY;
6630 V += STEP;
6631 if (V cond e) goto L2; else goto L3;
6633 trip += 1;
6634 goto L0;
6638 static void
6639 expand_omp_for_static_chunk (struct omp_region *region,
6640 struct omp_for_data *fd, gimple inner_stmt)
6642 tree n, s0, e0, e, t;
6643 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6644 tree type, itype, v_main, v_back, v_extra;
6645 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6646 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6647 gimple_stmt_iterator si;
6648 gimple stmt;
6649 edge se;
6650 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6651 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6652 bool broken_loop = region->cont == NULL;
6653 tree *counts = NULL;
6654 tree n1, n2, step;
6656 itype = type = TREE_TYPE (fd->loop.v);
6657 if (POINTER_TYPE_P (type))
6658 itype = signed_type_for (type);
6660 entry_bb = region->entry;
6661 se = split_block (entry_bb, last_stmt (entry_bb));
6662 entry_bb = se->src;
6663 iter_part_bb = se->dest;
6664 cont_bb = region->cont;
6665 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6666 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6667 gcc_assert (broken_loop
6668 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6669 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6670 body_bb = single_succ (seq_start_bb);
6671 if (!broken_loop)
6673 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6674 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6675 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6677 exit_bb = region->exit;
6679 /* Trip and adjustment setup goes in ENTRY_BB. */
6680 si = gsi_last_bb (entry_bb);
6681 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
6683 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6685 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6686 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6689 if (fd->collapse > 1)
6691 int first_zero_iter = -1;
6692 basic_block l2_dom_bb = NULL;
6694 counts = XALLOCAVEC (tree, fd->collapse);
6695 expand_omp_for_init_counts (fd, &si, entry_bb, counts,
6696 fin_bb, first_zero_iter,
6697 l2_dom_bb);
6698 t = NULL_TREE;
6700 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6701 t = integer_one_node;
6702 else
6703 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6704 fold_convert (type, fd->loop.n1),
6705 fold_convert (type, fd->loop.n2));
6706 if (fd->collapse == 1
6707 && TYPE_UNSIGNED (type)
6708 && (t == NULL_TREE || !integer_onep (t)))
6710 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6711 n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
6712 true, GSI_SAME_STMT);
6713 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6714 n2 = force_gimple_operand_gsi (&si, n2, true, NULL_TREE,
6715 true, GSI_SAME_STMT);
6716 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6717 NULL_TREE, NULL_TREE);
6718 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6719 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6720 expand_omp_regimplify_p, NULL, NULL)
6721 || walk_tree (gimple_cond_rhs_ptr (stmt),
6722 expand_omp_regimplify_p, NULL, NULL))
6724 si = gsi_for_stmt (stmt);
6725 gimple_regimplify_operands (stmt, &si);
6727 se = split_block (entry_bb, stmt);
6728 se->flags = EDGE_TRUE_VALUE;
6729 entry_bb = se->dest;
6730 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6731 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6732 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6733 if (gimple_in_ssa_p (cfun))
6735 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6736 for (si = gsi_start_phis (fin_bb);
6737 !gsi_end_p (si); gsi_next (&si))
6739 gimple phi = gsi_stmt (si);
6740 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6741 se, UNKNOWN_LOCATION);
6744 si = gsi_last_bb (entry_bb);
6747 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6748 t = fold_convert (itype, t);
6749 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6750 true, GSI_SAME_STMT);
6752 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6753 t = fold_convert (itype, t);
6754 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6755 true, GSI_SAME_STMT);
6757 n1 = fd->loop.n1;
6758 n2 = fd->loop.n2;
6759 step = fd->loop.step;
6760 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6762 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6763 OMP_CLAUSE__LOOPTEMP_);
6764 gcc_assert (innerc);
6765 n1 = OMP_CLAUSE_DECL (innerc);
6766 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6767 OMP_CLAUSE__LOOPTEMP_);
6768 gcc_assert (innerc);
6769 n2 = OMP_CLAUSE_DECL (innerc);
6771 n1 = force_gimple_operand_gsi (&si, fold_convert (type, n1),
6772 true, NULL_TREE, true, GSI_SAME_STMT);
6773 n2 = force_gimple_operand_gsi (&si, fold_convert (itype, n2),
6774 true, NULL_TREE, true, GSI_SAME_STMT);
6775 step = force_gimple_operand_gsi (&si, fold_convert (itype, step),
6776 true, NULL_TREE, true, GSI_SAME_STMT);
6777 fd->chunk_size
6778 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
6779 true, NULL_TREE, true, GSI_SAME_STMT);
6781 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6782 t = fold_build2 (PLUS_EXPR, itype, step, t);
6783 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6784 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6785 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6786 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6787 fold_build1 (NEGATE_EXPR, itype, t),
6788 fold_build1 (NEGATE_EXPR, itype, step));
6789 else
6790 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6791 t = fold_convert (itype, t);
6792 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6793 true, GSI_SAME_STMT);
6795 trip_var = create_tmp_reg (itype, ".trip");
6796 if (gimple_in_ssa_p (cfun))
6798 trip_init = make_ssa_name (trip_var, NULL);
6799 trip_main = make_ssa_name (trip_var, NULL);
6800 trip_back = make_ssa_name (trip_var, NULL);
6802 else
6804 trip_init = trip_var;
6805 trip_main = trip_var;
6806 trip_back = trip_var;
6809 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6810 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6812 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6813 t = fold_build2 (MULT_EXPR, itype, t, step);
6814 if (POINTER_TYPE_P (type))
6815 t = fold_build_pointer_plus (n1, t);
6816 else
6817 t = fold_build2 (PLUS_EXPR, type, t, n1);
6818 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6819 true, GSI_SAME_STMT);
6821 /* Remove the GIMPLE_OMP_FOR. */
6822 gsi_remove (&si, true);
6824 /* Iteration space partitioning goes in ITER_PART_BB. */
6825 si = gsi_last_bb (iter_part_bb);
6827 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6828 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6829 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6830 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6831 false, GSI_CONTINUE_LINKING);
6833 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6834 t = fold_build2 (MIN_EXPR, itype, t, n);
6835 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6836 false, GSI_CONTINUE_LINKING);
6838 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6839 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6841 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6842 si = gsi_start_bb (seq_start_bb);
6844 tree startvar = fd->loop.v;
6845 tree endvar = NULL_TREE;
6847 if (gimple_omp_for_combined_p (fd->for_stmt))
6849 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6850 ? gimple_omp_parallel_clauses (inner_stmt)
6851 : gimple_omp_for_clauses (inner_stmt);
6852 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6853 gcc_assert (innerc);
6854 startvar = OMP_CLAUSE_DECL (innerc);
6855 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6856 OMP_CLAUSE__LOOPTEMP_);
6857 gcc_assert (innerc);
6858 endvar = OMP_CLAUSE_DECL (innerc);
6861 t = fold_convert (itype, s0);
6862 t = fold_build2 (MULT_EXPR, itype, t, step);
6863 if (POINTER_TYPE_P (type))
6864 t = fold_build_pointer_plus (n1, t);
6865 else
6866 t = fold_build2 (PLUS_EXPR, type, t, n1);
6867 t = fold_convert (TREE_TYPE (startvar), t);
6868 t = force_gimple_operand_gsi (&si, t,
6869 DECL_P (startvar)
6870 && TREE_ADDRESSABLE (startvar),
6871 NULL_TREE, false, GSI_CONTINUE_LINKING);
6872 stmt = gimple_build_assign (startvar, t);
6873 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6875 t = fold_convert (itype, e0);
6876 t = fold_build2 (MULT_EXPR, itype, t, step);
6877 if (POINTER_TYPE_P (type))
6878 t = fold_build_pointer_plus (n1, t);
6879 else
6880 t = fold_build2 (PLUS_EXPR, type, t, n1);
6881 t = fold_convert (TREE_TYPE (startvar), t);
6882 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6883 false, GSI_CONTINUE_LINKING);
6884 if (endvar)
6886 stmt = gimple_build_assign (endvar, e);
6887 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6889 if (fd->collapse > 1)
6890 expand_omp_for_init_vars (fd, &si, counts, inner_stmt, startvar);
6892 if (!broken_loop)
6894 /* The code controlling the sequential loop goes in CONT_BB,
6895 replacing the GIMPLE_OMP_CONTINUE. */
6896 si = gsi_last_bb (cont_bb);
6897 stmt = gsi_stmt (si);
6898 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6899 v_main = gimple_omp_continue_control_use (stmt);
6900 v_back = gimple_omp_continue_control_def (stmt);
6902 if (!gimple_omp_for_combined_p (fd->for_stmt))
6904 if (POINTER_TYPE_P (type))
6905 t = fold_build_pointer_plus (v_main, step);
6906 else
6907 t = fold_build2 (PLUS_EXPR, type, v_main, step);
6908 if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
6909 t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6910 true, GSI_SAME_STMT);
6911 stmt = gimple_build_assign (v_back, t);
6912 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6914 t = build2 (fd->loop.cond_code, boolean_type_node,
6915 DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
6916 ? t : v_back, e);
6917 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
6920 /* Remove GIMPLE_OMP_CONTINUE. */
6921 gsi_remove (&si, true);
6923 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6924 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6926 /* Trip update code goes into TRIP_UPDATE_BB. */
6927 si = gsi_start_bb (trip_update_bb);
6929 t = build_int_cst (itype, 1);
6930 t = build2 (PLUS_EXPR, itype, trip_main, t);
6931 stmt = gimple_build_assign (trip_back, t);
6932 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6935 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6936 si = gsi_last_bb (exit_bb);
6937 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
6939 t = gimple_omp_return_lhs (gsi_stmt (si));
6940 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
6942 gsi_remove (&si, true);
6944 /* Connect the new blocks. */
6945 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6946 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6948 if (!broken_loop)
6950 se = find_edge (cont_bb, body_bb);
6951 if (gimple_omp_for_combined_p (fd->for_stmt))
6953 remove_edge (se);
6954 se = NULL;
6956 else if (fd->collapse > 1)
6958 remove_edge (se);
6959 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6961 else
6962 se->flags = EDGE_TRUE_VALUE;
6963 find_edge (cont_bb, trip_update_bb)->flags
6964 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6966 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6969 if (gimple_in_ssa_p (cfun))
6971 gimple_stmt_iterator psi;
6972 gimple phi;
6973 edge re, ene;
6974 edge_var_map_vector *head;
6975 edge_var_map *vm;
6976 size_t i;
6978 gcc_assert (fd->collapse == 1 && !broken_loop);
6980 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6981 remove arguments of the phi nodes in fin_bb. We need to create
6982 appropriate phi nodes in iter_part_bb instead. */
6983 se = single_pred_edge (fin_bb);
6984 re = single_succ_edge (trip_update_bb);
6985 head = redirect_edge_var_map_vector (re);
6986 ene = single_succ_edge (entry_bb);
6988 psi = gsi_start_phis (fin_bb);
6989 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6990 gsi_next (&psi), ++i)
6992 gimple nphi;
6993 source_location locus;
6995 phi = gsi_stmt (psi);
6996 t = gimple_phi_result (phi);
6997 gcc_assert (t == redirect_edge_var_map_result (vm));
6998 nphi = create_phi_node (t, iter_part_bb);
7000 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7001 locus = gimple_phi_arg_location_from_edge (phi, se);
7003 /* A special case -- fd->loop.v is not yet computed in
7004 iter_part_bb, we need to use v_extra instead. */
7005 if (t == fd->loop.v)
7006 t = v_extra;
7007 add_phi_arg (nphi, t, ene, locus);
7008 locus = redirect_edge_var_map_location (vm);
7009 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7011 gcc_assert (!gsi_end_p (psi) && i == head->length ());
7012 redirect_edge_var_map_clear (re);
7013 while (1)
7015 psi = gsi_start_phis (fin_bb);
7016 if (gsi_end_p (psi))
7017 break;
7018 remove_phi_node (&psi, false);
7021 /* Make phi node for trip. */
7022 phi = create_phi_node (trip_main, iter_part_bb);
7023 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7024 UNKNOWN_LOCATION);
7025 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7026 UNKNOWN_LOCATION);
7029 if (!broken_loop)
7030 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7031 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7032 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7033 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7034 recompute_dominator (CDI_DOMINATORS, fin_bb));
7035 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7036 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7037 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7038 recompute_dominator (CDI_DOMINATORS, body_bb));
7040 if (!broken_loop)
7042 struct loop *trip_loop = alloc_loop ();
7043 trip_loop->header = iter_part_bb;
7044 trip_loop->latch = trip_update_bb;
7045 add_loop (trip_loop, iter_part_bb->loop_father);
7047 if (!gimple_omp_for_combined_p (fd->for_stmt))
7049 struct loop *loop = alloc_loop ();
7050 loop->header = body_bb;
7051 if (collapse_bb == NULL)
7052 loop->latch = cont_bb;
7053 add_loop (loop, trip_loop);
7059 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7060 loop. Given parameters:
7062 for (V = N1; V cond N2; V += STEP) BODY;
7064 where COND is "<" or ">", we generate pseudocode
7066 V = N1;
7067 goto L1;
7069 BODY;
7070 V += STEP;
7072 if (V cond N2) goto L0; else goto L2;
7075 For collapsed loops, given parameters:
7076 collapse(3)
7077 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7078 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7079 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7080 BODY;
7082 we generate pseudocode
7084 if (cond3 is <)
7085 adj = STEP3 - 1;
7086 else
7087 adj = STEP3 + 1;
7088 count3 = (adj + N32 - N31) / STEP3;
7089 if (cond2 is <)
7090 adj = STEP2 - 1;
7091 else
7092 adj = STEP2 + 1;
7093 count2 = (adj + N22 - N21) / STEP2;
7094 if (cond1 is <)
7095 adj = STEP1 - 1;
7096 else
7097 adj = STEP1 + 1;
7098 count1 = (adj + N12 - N11) / STEP1;
7099 count = count1 * count2 * count3;
7100 V = 0;
7101 V1 = N11;
7102 V2 = N21;
7103 V3 = N31;
7104 goto L1;
7106 BODY;
7107 V += 1;
7108 V3 += STEP3;
7109 V2 += (V3 cond3 N32) ? 0 : STEP2;
7110 V3 = (V3 cond3 N32) ? V3 : N31;
7111 V1 += (V2 cond2 N22) ? 0 : STEP1;
7112 V2 = (V2 cond2 N22) ? V2 : N21;
7114 if (V < count) goto L0; else goto L2;
7119 static void
7120 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7122 tree type, t;
7123 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7124 gimple_stmt_iterator gsi;
7125 gimple stmt;
7126 bool broken_loop = region->cont == NULL;
7127 edge e, ne;
7128 tree *counts = NULL;
7129 int i;
7130 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7131 OMP_CLAUSE_SAFELEN);
7132 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7133 OMP_CLAUSE__SIMDUID_);
7134 tree n1, n2;
7136 type = TREE_TYPE (fd->loop.v);
7137 entry_bb = region->entry;
7138 cont_bb = region->cont;
7139 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7140 gcc_assert (broken_loop
7141 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7142 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7143 if (!broken_loop)
7145 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7146 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7147 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7148 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7150 else
7152 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7153 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7154 l2_bb = single_succ (l1_bb);
7156 exit_bb = region->exit;
7157 l2_dom_bb = NULL;
7159 gsi = gsi_last_bb (entry_bb);
7161 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7162 /* Not needed in SSA form right now. */
7163 gcc_assert (!gimple_in_ssa_p (cfun));
7164 if (fd->collapse > 1)
7166 int first_zero_iter = -1;
7167 basic_block zero_iter_bb = l2_bb;
7169 counts = XALLOCAVEC (tree, fd->collapse);
7170 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7171 zero_iter_bb, first_zero_iter,
7172 l2_dom_bb);
7174 if (l2_dom_bb == NULL)
7175 l2_dom_bb = l1_bb;
7177 n1 = fd->loop.n1;
7178 n2 = fd->loop.n2;
7179 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7181 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7182 OMP_CLAUSE__LOOPTEMP_);
7183 gcc_assert (innerc);
7184 n1 = OMP_CLAUSE_DECL (innerc);
7185 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7186 OMP_CLAUSE__LOOPTEMP_);
7187 gcc_assert (innerc);
7188 n2 = OMP_CLAUSE_DECL (innerc);
7189 expand_omp_build_assign (&gsi, fd->loop.v,
7190 fold_convert (type, n1));
7191 if (fd->collapse > 1)
7193 gsi_prev (&gsi);
7194 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7195 gsi_next (&gsi);
7198 else
7200 expand_omp_build_assign (&gsi, fd->loop.v,
7201 fold_convert (type, fd->loop.n1));
7202 if (fd->collapse > 1)
7203 for (i = 0; i < fd->collapse; i++)
7205 tree itype = TREE_TYPE (fd->loops[i].v);
7206 if (POINTER_TYPE_P (itype))
7207 itype = signed_type_for (itype);
7208 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7209 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7213 /* Remove the GIMPLE_OMP_FOR statement. */
7214 gsi_remove (&gsi, true);
7216 if (!broken_loop)
7218 /* Code to control the increment goes in the CONT_BB. */
7219 gsi = gsi_last_bb (cont_bb);
7220 stmt = gsi_stmt (gsi);
7221 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7223 if (POINTER_TYPE_P (type))
7224 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7225 else
7226 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7227 expand_omp_build_assign (&gsi, fd->loop.v, t);
7229 if (fd->collapse > 1)
7231 i = fd->collapse - 1;
7232 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7234 t = fold_convert (sizetype, fd->loops[i].step);
7235 t = fold_build_pointer_plus (fd->loops[i].v, t);
7237 else
7239 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7240 fd->loops[i].step);
7241 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7242 fd->loops[i].v, t);
7244 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7246 for (i = fd->collapse - 1; i > 0; i--)
7248 tree itype = TREE_TYPE (fd->loops[i].v);
7249 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7250 if (POINTER_TYPE_P (itype2))
7251 itype2 = signed_type_for (itype2);
7252 t = build3 (COND_EXPR, itype2,
7253 build2 (fd->loops[i].cond_code, boolean_type_node,
7254 fd->loops[i].v,
7255 fold_convert (itype, fd->loops[i].n2)),
7256 build_int_cst (itype2, 0),
7257 fold_convert (itype2, fd->loops[i - 1].step));
7258 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7259 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7260 else
7261 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7262 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7264 t = build3 (COND_EXPR, itype,
7265 build2 (fd->loops[i].cond_code, boolean_type_node,
7266 fd->loops[i].v,
7267 fold_convert (itype, fd->loops[i].n2)),
7268 fd->loops[i].v,
7269 fold_convert (itype, fd->loops[i].n1));
7270 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7274 /* Remove GIMPLE_OMP_CONTINUE. */
7275 gsi_remove (&gsi, true);
7278 /* Emit the condition in L1_BB. */
7279 gsi = gsi_start_bb (l1_bb);
7281 t = fold_convert (type, n2);
7282 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7283 false, GSI_CONTINUE_LINKING);
7284 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7285 stmt = gimple_build_cond_empty (t);
7286 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7287 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
7288 NULL, NULL)
7289 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
7290 NULL, NULL))
7292 gsi = gsi_for_stmt (stmt);
7293 gimple_regimplify_operands (stmt, &gsi);
7296 /* Remove GIMPLE_OMP_RETURN. */
7297 gsi = gsi_last_bb (exit_bb);
7298 gsi_remove (&gsi, true);
7300 /* Connect the new blocks. */
7301 remove_edge (FALLTHRU_EDGE (entry_bb));
7303 if (!broken_loop)
7305 remove_edge (BRANCH_EDGE (entry_bb));
7306 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7308 e = BRANCH_EDGE (l1_bb);
7309 ne = FALLTHRU_EDGE (l1_bb);
7310 e->flags = EDGE_TRUE_VALUE;
7312 else
7314 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7316 ne = single_succ_edge (l1_bb);
7317 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7320 ne->flags = EDGE_FALSE_VALUE;
7321 e->probability = REG_BR_PROB_BASE * 7 / 8;
7322 ne->probability = REG_BR_PROB_BASE / 8;
7324 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7325 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7326 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7328 if (!broken_loop)
7330 struct loop *loop = alloc_loop ();
7331 loop->header = l1_bb;
7332 loop->latch = cont_bb;
7333 add_loop (loop, l1_bb->loop_father);
7334 if (safelen == NULL_TREE)
7335 loop->safelen = INT_MAX;
7336 else
7338 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7339 if (!tree_fits_uhwi_p (safelen)
7340 || tree_to_uhwi (safelen) > INT_MAX)
7341 loop->safelen = INT_MAX;
7342 else
7343 loop->safelen = tree_to_uhwi (safelen);
7344 if (loop->safelen == 1)
7345 loop->safelen = 0;
7347 if (simduid)
7349 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7350 cfun->has_simduid_loops = true;
7352 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7353 the loop. */
7354 if ((flag_tree_loop_vectorize
7355 || (!global_options_set.x_flag_tree_loop_vectorize
7356 && !global_options_set.x_flag_tree_vectorize))
7357 && loop->safelen > 1)
7359 loop->force_vect = true;
7360 cfun->has_force_vect_loops = true;
7366 /* Expand the OpenMP loop defined by REGION. */
7368 static void
7369 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7371 struct omp_for_data fd;
7372 struct omp_for_data_loop *loops;
7374 loops
7375 = (struct omp_for_data_loop *)
7376 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7377 * sizeof (struct omp_for_data_loop));
7378 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
7379 region->sched_kind = fd.sched_kind;
7381 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7382 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7383 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7384 if (region->cont)
7386 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7387 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7388 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7390 else
7391 /* If there isn't a continue then this is a degerate case where
7392 the introduction of abnormal edges during lowering will prevent
7393 original loops from being detected. Fix that up. */
7394 loops_state_set (LOOPS_NEED_FIXUP);
7396 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_KIND_SIMD)
7397 expand_omp_simd (region, &fd);
7398 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7399 && !fd.have_ordered)
7401 if (fd.chunk_size == NULL)
7402 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7403 else
7404 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7406 else
7408 int fn_index, start_ix, next_ix;
7410 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7411 == GF_OMP_FOR_KIND_FOR);
7412 if (fd.chunk_size == NULL
7413 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7414 fd.chunk_size = integer_zero_node;
7415 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7416 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7417 ? 3 : fd.sched_kind;
7418 fn_index += fd.have_ordered * 4;
7419 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7420 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7421 if (fd.iter_type == long_long_unsigned_type_node)
7423 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7424 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7425 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7426 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7428 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7429 (enum built_in_function) next_ix, inner_stmt);
7432 if (gimple_in_ssa_p (cfun))
7433 update_ssa (TODO_update_ssa_only_virtuals);
7437 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7439 v = GOMP_sections_start (n);
7441 switch (v)
7443 case 0:
7444 goto L2;
7445 case 1:
7446 section 1;
7447 goto L1;
7448 case 2:
7450 case n:
7452 default:
7453 abort ();
7456 v = GOMP_sections_next ();
7457 goto L0;
7459 reduction;
7461 If this is a combined parallel sections, replace the call to
7462 GOMP_sections_start with call to GOMP_sections_next. */
7464 static void
7465 expand_omp_sections (struct omp_region *region)
7467 tree t, u, vin = NULL, vmain, vnext, l2;
7468 unsigned len;
7469 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7470 gimple_stmt_iterator si, switch_si;
7471 gimple sections_stmt, stmt, cont;
7472 edge_iterator ei;
7473 edge e;
7474 struct omp_region *inner;
7475 unsigned i, casei;
7476 bool exit_reachable = region->cont != NULL;
7478 gcc_assert (region->exit != NULL);
7479 entry_bb = region->entry;
7480 l0_bb = single_succ (entry_bb);
7481 l1_bb = region->cont;
7482 l2_bb = region->exit;
7483 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7484 l2 = gimple_block_label (l2_bb);
7485 else
7487 /* This can happen if there are reductions. */
7488 len = EDGE_COUNT (l0_bb->succs);
7489 gcc_assert (len > 0);
7490 e = EDGE_SUCC (l0_bb, len - 1);
7491 si = gsi_last_bb (e->dest);
7492 l2 = NULL_TREE;
7493 if (gsi_end_p (si)
7494 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7495 l2 = gimple_block_label (e->dest);
7496 else
7497 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7499 si = gsi_last_bb (e->dest);
7500 if (gsi_end_p (si)
7501 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7503 l2 = gimple_block_label (e->dest);
7504 break;
7508 if (exit_reachable)
7509 default_bb = create_empty_bb (l1_bb->prev_bb);
7510 else
7511 default_bb = create_empty_bb (l0_bb);
7513 /* We will build a switch() with enough cases for all the
7514 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7515 and a default case to abort if something goes wrong. */
7516 len = EDGE_COUNT (l0_bb->succs);
7518 /* Use vec::quick_push on label_vec throughout, since we know the size
7519 in advance. */
7520 auto_vec<tree> label_vec (len);
7522 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7523 GIMPLE_OMP_SECTIONS statement. */
7524 si = gsi_last_bb (entry_bb);
7525 sections_stmt = gsi_stmt (si);
7526 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7527 vin = gimple_omp_sections_control (sections_stmt);
7528 if (!is_combined_parallel (region))
7530 /* If we are not inside a combined parallel+sections region,
7531 call GOMP_sections_start. */
7532 t = build_int_cst (unsigned_type_node, len - 1);
7533 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7534 stmt = gimple_build_call (u, 1, t);
7536 else
7538 /* Otherwise, call GOMP_sections_next. */
7539 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7540 stmt = gimple_build_call (u, 0);
7542 gimple_call_set_lhs (stmt, vin);
7543 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7544 gsi_remove (&si, true);
7546 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7547 L0_BB. */
7548 switch_si = gsi_last_bb (l0_bb);
7549 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7550 if (exit_reachable)
7552 cont = last_stmt (l1_bb);
7553 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7554 vmain = gimple_omp_continue_control_use (cont);
7555 vnext = gimple_omp_continue_control_def (cont);
7557 else
7559 vmain = vin;
7560 vnext = NULL_TREE;
7563 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7564 label_vec.quick_push (t);
7565 i = 1;
7567 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7568 for (inner = region->inner, casei = 1;
7569 inner;
7570 inner = inner->next, i++, casei++)
7572 basic_block s_entry_bb, s_exit_bb;
7574 /* Skip optional reduction region. */
7575 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7577 --i;
7578 --casei;
7579 continue;
7582 s_entry_bb = inner->entry;
7583 s_exit_bb = inner->exit;
7585 t = gimple_block_label (s_entry_bb);
7586 u = build_int_cst (unsigned_type_node, casei);
7587 u = build_case_label (u, NULL, t);
7588 label_vec.quick_push (u);
7590 si = gsi_last_bb (s_entry_bb);
7591 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7592 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7593 gsi_remove (&si, true);
7594 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7596 if (s_exit_bb == NULL)
7597 continue;
7599 si = gsi_last_bb (s_exit_bb);
7600 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7601 gsi_remove (&si, true);
7603 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7606 /* Error handling code goes in DEFAULT_BB. */
7607 t = gimple_block_label (default_bb);
7608 u = build_case_label (NULL, NULL, t);
7609 make_edge (l0_bb, default_bb, 0);
7610 if (current_loops)
7611 add_bb_to_loop (default_bb, current_loops->tree_root);
7613 stmt = gimple_build_switch (vmain, u, label_vec);
7614 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7615 gsi_remove (&switch_si, true);
7617 si = gsi_start_bb (default_bb);
7618 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7619 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7621 if (exit_reachable)
7623 tree bfn_decl;
7625 /* Code to get the next section goes in L1_BB. */
7626 si = gsi_last_bb (l1_bb);
7627 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7629 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7630 stmt = gimple_build_call (bfn_decl, 0);
7631 gimple_call_set_lhs (stmt, vnext);
7632 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7633 gsi_remove (&si, true);
7635 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7638 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7639 si = gsi_last_bb (l2_bb);
7640 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7641 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7642 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7643 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7644 else
7645 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7646 stmt = gimple_build_call (t, 0);
7647 if (gimple_omp_return_lhs (gsi_stmt (si)))
7648 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7649 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7650 gsi_remove (&si, true);
7652 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7656 /* Expand code for an OpenMP single directive. We've already expanded
7657 much of the code, here we simply place the GOMP_barrier call. */
7659 static void
7660 expand_omp_single (struct omp_region *region)
7662 basic_block entry_bb, exit_bb;
7663 gimple_stmt_iterator si;
7665 entry_bb = region->entry;
7666 exit_bb = region->exit;
7668 si = gsi_last_bb (entry_bb);
7669 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7670 gsi_remove (&si, true);
7671 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7673 si = gsi_last_bb (exit_bb);
7674 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7676 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7677 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7679 gsi_remove (&si, true);
7680 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7684 /* Generic expansion for OpenMP synchronization directives: master,
7685 ordered and critical. All we need to do here is remove the entry
7686 and exit markers for REGION. */
7688 static void
7689 expand_omp_synch (struct omp_region *region)
7691 basic_block entry_bb, exit_bb;
7692 gimple_stmt_iterator si;
7694 entry_bb = region->entry;
7695 exit_bb = region->exit;
7697 si = gsi_last_bb (entry_bb);
7698 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7699 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7700 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7701 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7702 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7703 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7704 gsi_remove (&si, true);
7705 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7707 if (exit_bb)
7709 si = gsi_last_bb (exit_bb);
7710 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7711 gsi_remove (&si, true);
7712 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7716 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7717 operation as a normal volatile load. */
7719 static bool
7720 expand_omp_atomic_load (basic_block load_bb, tree addr,
7721 tree loaded_val, int index)
7723 enum built_in_function tmpbase;
7724 gimple_stmt_iterator gsi;
7725 basic_block store_bb;
7726 location_t loc;
7727 gimple stmt;
7728 tree decl, call, type, itype;
7730 gsi = gsi_last_bb (load_bb);
7731 stmt = gsi_stmt (gsi);
7732 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7733 loc = gimple_location (stmt);
7735 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7736 is smaller than word size, then expand_atomic_load assumes that the load
7737 is atomic. We could avoid the builtin entirely in this case. */
7739 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7740 decl = builtin_decl_explicit (tmpbase);
7741 if (decl == NULL_TREE)
7742 return false;
7744 type = TREE_TYPE (loaded_val);
7745 itype = TREE_TYPE (TREE_TYPE (decl));
7747 call = build_call_expr_loc (loc, decl, 2, addr,
7748 build_int_cst (NULL,
7749 gimple_omp_atomic_seq_cst_p (stmt)
7750 ? MEMMODEL_SEQ_CST
7751 : MEMMODEL_RELAXED));
7752 if (!useless_type_conversion_p (type, itype))
7753 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7754 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7756 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7757 gsi_remove (&gsi, true);
7759 store_bb = single_succ (load_bb);
7760 gsi = gsi_last_bb (store_bb);
7761 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7762 gsi_remove (&gsi, true);
7764 if (gimple_in_ssa_p (cfun))
7765 update_ssa (TODO_update_ssa_no_phi);
7767 return true;
7770 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7771 operation as a normal volatile store. */
7773 static bool
7774 expand_omp_atomic_store (basic_block load_bb, tree addr,
7775 tree loaded_val, tree stored_val, int index)
7777 enum built_in_function tmpbase;
7778 gimple_stmt_iterator gsi;
7779 basic_block store_bb = single_succ (load_bb);
7780 location_t loc;
7781 gimple stmt;
7782 tree decl, call, type, itype;
7783 enum machine_mode imode;
7784 bool exchange;
7786 gsi = gsi_last_bb (load_bb);
7787 stmt = gsi_stmt (gsi);
7788 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7790 /* If the load value is needed, then this isn't a store but an exchange. */
7791 exchange = gimple_omp_atomic_need_value_p (stmt);
7793 gsi = gsi_last_bb (store_bb);
7794 stmt = gsi_stmt (gsi);
7795 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7796 loc = gimple_location (stmt);
7798 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7799 is smaller than word size, then expand_atomic_store assumes that the store
7800 is atomic. We could avoid the builtin entirely in this case. */
7802 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7803 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7804 decl = builtin_decl_explicit (tmpbase);
7805 if (decl == NULL_TREE)
7806 return false;
7808 type = TREE_TYPE (stored_val);
7810 /* Dig out the type of the function's second argument. */
7811 itype = TREE_TYPE (decl);
7812 itype = TYPE_ARG_TYPES (itype);
7813 itype = TREE_CHAIN (itype);
7814 itype = TREE_VALUE (itype);
7815 imode = TYPE_MODE (itype);
7817 if (exchange && !can_atomic_exchange_p (imode, true))
7818 return false;
7820 if (!useless_type_conversion_p (itype, type))
7821 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7822 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7823 build_int_cst (NULL,
7824 gimple_omp_atomic_seq_cst_p (stmt)
7825 ? MEMMODEL_SEQ_CST
7826 : MEMMODEL_RELAXED));
7827 if (exchange)
7829 if (!useless_type_conversion_p (type, itype))
7830 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7831 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7834 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7835 gsi_remove (&gsi, true);
7837 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7838 gsi = gsi_last_bb (load_bb);
7839 gsi_remove (&gsi, true);
7841 if (gimple_in_ssa_p (cfun))
7842 update_ssa (TODO_update_ssa_no_phi);
7844 return true;
7847 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7848 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7849 size of the data type, and thus usable to find the index of the builtin
7850 decl. Returns false if the expression is not of the proper form. */
7852 static bool
7853 expand_omp_atomic_fetch_op (basic_block load_bb,
7854 tree addr, tree loaded_val,
7855 tree stored_val, int index)
7857 enum built_in_function oldbase, newbase, tmpbase;
7858 tree decl, itype, call;
7859 tree lhs, rhs;
7860 basic_block store_bb = single_succ (load_bb);
7861 gimple_stmt_iterator gsi;
7862 gimple stmt;
7863 location_t loc;
7864 enum tree_code code;
7865 bool need_old, need_new;
7866 enum machine_mode imode;
7867 bool seq_cst;
7869 /* We expect to find the following sequences:
7871 load_bb:
7872 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7874 store_bb:
7875 val = tmp OP something; (or: something OP tmp)
7876 GIMPLE_OMP_STORE (val)
7878 ???FIXME: Allow a more flexible sequence.
7879 Perhaps use data flow to pick the statements.
7883 gsi = gsi_after_labels (store_bb);
7884 stmt = gsi_stmt (gsi);
7885 loc = gimple_location (stmt);
7886 if (!is_gimple_assign (stmt))
7887 return false;
7888 gsi_next (&gsi);
7889 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7890 return false;
7891 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7892 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7893 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7894 gcc_checking_assert (!need_old || !need_new);
7896 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7897 return false;
7899 /* Check for one of the supported fetch-op operations. */
7900 code = gimple_assign_rhs_code (stmt);
7901 switch (code)
7903 case PLUS_EXPR:
7904 case POINTER_PLUS_EXPR:
7905 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7906 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7907 break;
7908 case MINUS_EXPR:
7909 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7910 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7911 break;
7912 case BIT_AND_EXPR:
7913 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7914 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7915 break;
7916 case BIT_IOR_EXPR:
7917 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7918 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7919 break;
7920 case BIT_XOR_EXPR:
7921 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7922 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7923 break;
7924 default:
7925 return false;
7928 /* Make sure the expression is of the proper form. */
7929 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7930 rhs = gimple_assign_rhs2 (stmt);
7931 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7932 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7933 rhs = gimple_assign_rhs1 (stmt);
7934 else
7935 return false;
7937 tmpbase = ((enum built_in_function)
7938 ((need_new ? newbase : oldbase) + index + 1));
7939 decl = builtin_decl_explicit (tmpbase);
7940 if (decl == NULL_TREE)
7941 return false;
7942 itype = TREE_TYPE (TREE_TYPE (decl));
7943 imode = TYPE_MODE (itype);
7945 /* We could test all of the various optabs involved, but the fact of the
7946 matter is that (with the exception of i486 vs i586 and xadd) all targets
7947 that support any atomic operaton optab also implements compare-and-swap.
7948 Let optabs.c take care of expanding any compare-and-swap loop. */
7949 if (!can_compare_and_swap_p (imode, true))
7950 return false;
7952 gsi = gsi_last_bb (load_bb);
7953 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7955 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7956 It only requires that the operation happen atomically. Thus we can
7957 use the RELAXED memory model. */
7958 call = build_call_expr_loc (loc, decl, 3, addr,
7959 fold_convert_loc (loc, itype, rhs),
7960 build_int_cst (NULL,
7961 seq_cst ? MEMMODEL_SEQ_CST
7962 : MEMMODEL_RELAXED));
7964 if (need_old || need_new)
7966 lhs = need_old ? loaded_val : stored_val;
7967 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7968 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7970 else
7971 call = fold_convert_loc (loc, void_type_node, call);
7972 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7973 gsi_remove (&gsi, true);
7975 gsi = gsi_last_bb (store_bb);
7976 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7977 gsi_remove (&gsi, true);
7978 gsi = gsi_last_bb (store_bb);
7979 gsi_remove (&gsi, true);
7981 if (gimple_in_ssa_p (cfun))
7982 update_ssa (TODO_update_ssa_no_phi);
7984 return true;
7987 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7989 oldval = *addr;
7990 repeat:
7991 newval = rhs; // with oldval replacing *addr in rhs
7992 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7993 if (oldval != newval)
7994 goto repeat;
7996 INDEX is log2 of the size of the data type, and thus usable to find the
7997 index of the builtin decl. */
7999 static bool
8000 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8001 tree addr, tree loaded_val, tree stored_val,
8002 int index)
8004 tree loadedi, storedi, initial, new_storedi, old_vali;
8005 tree type, itype, cmpxchg, iaddr;
8006 gimple_stmt_iterator si;
8007 basic_block loop_header = single_succ (load_bb);
8008 gimple phi, stmt;
8009 edge e;
8010 enum built_in_function fncode;
8012 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8013 order to use the RELAXED memory model effectively. */
8014 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8015 + index + 1);
8016 cmpxchg = builtin_decl_explicit (fncode);
8017 if (cmpxchg == NULL_TREE)
8018 return false;
8019 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8020 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8022 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8023 return false;
8025 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8026 si = gsi_last_bb (load_bb);
8027 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8029 /* For floating-point values, we'll need to view-convert them to integers
8030 so that we can perform the atomic compare and swap. Simplify the
8031 following code by always setting up the "i"ntegral variables. */
8032 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8034 tree iaddr_val;
8036 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8037 true), NULL);
8038 iaddr_val
8039 = force_gimple_operand_gsi (&si,
8040 fold_convert (TREE_TYPE (iaddr), addr),
8041 false, NULL_TREE, true, GSI_SAME_STMT);
8042 stmt = gimple_build_assign (iaddr, iaddr_val);
8043 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8044 loadedi = create_tmp_var (itype, NULL);
8045 if (gimple_in_ssa_p (cfun))
8046 loadedi = make_ssa_name (loadedi, NULL);
8048 else
8050 iaddr = addr;
8051 loadedi = loaded_val;
8054 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8055 tree loaddecl = builtin_decl_explicit (fncode);
8056 if (loaddecl)
8057 initial
8058 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8059 build_call_expr (loaddecl, 2, iaddr,
8060 build_int_cst (NULL_TREE,
8061 MEMMODEL_RELAXED)));
8062 else
8063 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8064 build_int_cst (TREE_TYPE (iaddr), 0));
8066 initial
8067 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8068 GSI_SAME_STMT);
8070 /* Move the value to the LOADEDI temporary. */
8071 if (gimple_in_ssa_p (cfun))
8073 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8074 phi = create_phi_node (loadedi, loop_header);
8075 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8076 initial);
8078 else
8079 gsi_insert_before (&si,
8080 gimple_build_assign (loadedi, initial),
8081 GSI_SAME_STMT);
8082 if (loadedi != loaded_val)
8084 gimple_stmt_iterator gsi2;
8085 tree x;
8087 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8088 gsi2 = gsi_start_bb (loop_header);
8089 if (gimple_in_ssa_p (cfun))
8091 gimple stmt;
8092 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8093 true, GSI_SAME_STMT);
8094 stmt = gimple_build_assign (loaded_val, x);
8095 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8097 else
8099 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8100 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8101 true, GSI_SAME_STMT);
8104 gsi_remove (&si, true);
8106 si = gsi_last_bb (store_bb);
8107 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8109 if (iaddr == addr)
8110 storedi = stored_val;
8111 else
8112 storedi =
8113 force_gimple_operand_gsi (&si,
8114 build1 (VIEW_CONVERT_EXPR, itype,
8115 stored_val), true, NULL_TREE, true,
8116 GSI_SAME_STMT);
8118 /* Build the compare&swap statement. */
8119 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8120 new_storedi = force_gimple_operand_gsi (&si,
8121 fold_convert (TREE_TYPE (loadedi),
8122 new_storedi),
8123 true, NULL_TREE,
8124 true, GSI_SAME_STMT);
8126 if (gimple_in_ssa_p (cfun))
8127 old_vali = loadedi;
8128 else
8130 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
8131 stmt = gimple_build_assign (old_vali, loadedi);
8132 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8134 stmt = gimple_build_assign (loadedi, new_storedi);
8135 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8138 /* Note that we always perform the comparison as an integer, even for
8139 floating point. This allows the atomic operation to properly
8140 succeed even with NaNs and -0.0. */
8141 stmt = gimple_build_cond_empty
8142 (build2 (NE_EXPR, boolean_type_node,
8143 new_storedi, old_vali));
8144 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8146 /* Update cfg. */
8147 e = single_succ_edge (store_bb);
8148 e->flags &= ~EDGE_FALLTHRU;
8149 e->flags |= EDGE_FALSE_VALUE;
8151 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8153 /* Copy the new value to loadedi (we already did that before the condition
8154 if we are not in SSA). */
8155 if (gimple_in_ssa_p (cfun))
8157 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8158 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8161 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8162 gsi_remove (&si, true);
8164 struct loop *loop = alloc_loop ();
8165 loop->header = loop_header;
8166 loop->latch = store_bb;
8167 add_loop (loop, loop_header->loop_father);
8169 if (gimple_in_ssa_p (cfun))
8170 update_ssa (TODO_update_ssa_no_phi);
8172 return true;
8175 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8177 GOMP_atomic_start ();
8178 *addr = rhs;
8179 GOMP_atomic_end ();
8181 The result is not globally atomic, but works so long as all parallel
8182 references are within #pragma omp atomic directives. According to
8183 responses received from omp@openmp.org, appears to be within spec.
8184 Which makes sense, since that's how several other compilers handle
8185 this situation as well.
8186 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8187 expanding. STORED_VAL is the operand of the matching
8188 GIMPLE_OMP_ATOMIC_STORE.
8190 We replace
8191 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8192 loaded_val = *addr;
8194 and replace
8195 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8196 *addr = stored_val;
8199 static bool
8200 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8201 tree addr, tree loaded_val, tree stored_val)
8203 gimple_stmt_iterator si;
8204 gimple stmt;
8205 tree t;
8207 si = gsi_last_bb (load_bb);
8208 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8210 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8211 t = build_call_expr (t, 0);
8212 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8214 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8215 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8216 gsi_remove (&si, true);
8218 si = gsi_last_bb (store_bb);
8219 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8221 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8222 stored_val);
8223 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8225 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8226 t = build_call_expr (t, 0);
8227 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8228 gsi_remove (&si, true);
8230 if (gimple_in_ssa_p (cfun))
8231 update_ssa (TODO_update_ssa_no_phi);
8232 return true;
8235 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8236 using expand_omp_atomic_fetch_op. If it failed, we try to
8237 call expand_omp_atomic_pipeline, and if it fails too, the
8238 ultimate fallback is wrapping the operation in a mutex
8239 (expand_omp_atomic_mutex). REGION is the atomic region built
8240 by build_omp_regions_1(). */
8242 static void
8243 expand_omp_atomic (struct omp_region *region)
8245 basic_block load_bb = region->entry, store_bb = region->exit;
8246 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
8247 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8248 tree addr = gimple_omp_atomic_load_rhs (load);
8249 tree stored_val = gimple_omp_atomic_store_val (store);
8250 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8251 HOST_WIDE_INT index;
8253 /* Make sure the type is one of the supported sizes. */
8254 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8255 index = exact_log2 (index);
8256 if (index >= 0 && index <= 4)
8258 unsigned int align = TYPE_ALIGN_UNIT (type);
8260 /* __sync builtins require strict data alignment. */
8261 if (exact_log2 (align) >= index)
8263 /* Atomic load. */
8264 if (loaded_val == stored_val
8265 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8266 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8267 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8268 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8269 return;
8271 /* Atomic store. */
8272 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8273 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8274 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8275 && store_bb == single_succ (load_bb)
8276 && first_stmt (store_bb) == store
8277 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8278 stored_val, index))
8279 return;
8281 /* When possible, use specialized atomic update functions. */
8282 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8283 && store_bb == single_succ (load_bb)
8284 && expand_omp_atomic_fetch_op (load_bb, addr,
8285 loaded_val, stored_val, index))
8286 return;
8288 /* If we don't have specialized __sync builtins, try and implement
8289 as a compare and swap loop. */
8290 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8291 loaded_val, stored_val, index))
8292 return;
8296 /* The ultimate fallback is wrapping the operation in a mutex. */
8297 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8301 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8303 static void
8304 expand_omp_target (struct omp_region *region)
8306 basic_block entry_bb, exit_bb, new_bb;
8307 struct function *child_cfun = NULL;
8308 tree child_fn = NULL_TREE, block, t;
8309 gimple_stmt_iterator gsi;
8310 gimple entry_stmt, stmt;
8311 edge e;
8313 entry_stmt = last_stmt (region->entry);
8314 new_bb = region->entry;
8315 int kind = gimple_omp_target_kind (entry_stmt);
8316 if (kind == GF_OMP_TARGET_KIND_REGION)
8318 child_fn = gimple_omp_target_child_fn (entry_stmt);
8319 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8322 entry_bb = region->entry;
8323 exit_bb = region->exit;
8325 if (kind == GF_OMP_TARGET_KIND_REGION)
8327 unsigned srcidx, dstidx, num;
8329 /* If the target region needs data sent from the parent
8330 function, then the very first statement (except possible
8331 tree profile counter updates) of the parallel body
8332 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8333 &.OMP_DATA_O is passed as an argument to the child function,
8334 we need to replace it with the argument as seen by the child
8335 function.
8337 In most cases, this will end up being the identity assignment
8338 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8339 a function call that has been inlined, the original PARM_DECL
8340 .OMP_DATA_I may have been converted into a different local
8341 variable. In which case, we need to keep the assignment. */
8342 if (gimple_omp_target_data_arg (entry_stmt))
8344 basic_block entry_succ_bb = single_succ (entry_bb);
8345 gimple_stmt_iterator gsi;
8346 tree arg;
8347 gimple tgtcopy_stmt = NULL;
8348 tree sender
8349 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
8351 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8353 gcc_assert (!gsi_end_p (gsi));
8354 stmt = gsi_stmt (gsi);
8355 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8356 continue;
8358 if (gimple_num_ops (stmt) == 2)
8360 tree arg = gimple_assign_rhs1 (stmt);
8362 /* We're ignoring the subcode because we're
8363 effectively doing a STRIP_NOPS. */
8365 if (TREE_CODE (arg) == ADDR_EXPR
8366 && TREE_OPERAND (arg, 0) == sender)
8368 tgtcopy_stmt = stmt;
8369 break;
8374 gcc_assert (tgtcopy_stmt != NULL);
8375 arg = DECL_ARGUMENTS (child_fn);
8377 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8378 gsi_remove (&gsi, true);
8381 /* Declare local variables needed in CHILD_CFUN. */
8382 block = DECL_INITIAL (child_fn);
8383 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8384 /* The gimplifier could record temporaries in target block
8385 rather than in containing function's local_decls chain,
8386 which would mean cgraph missed finalizing them. Do it now. */
8387 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8388 if (TREE_CODE (t) == VAR_DECL
8389 && TREE_STATIC (t)
8390 && !DECL_EXTERNAL (t))
8391 varpool_finalize_decl (t);
8392 DECL_SAVED_TREE (child_fn) = NULL;
8393 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8394 gimple_set_body (child_fn, NULL);
8395 TREE_USED (block) = 1;
8397 /* Reset DECL_CONTEXT on function arguments. */
8398 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8399 DECL_CONTEXT (t) = child_fn;
8401 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8402 so that it can be moved to the child function. */
8403 gsi = gsi_last_bb (entry_bb);
8404 stmt = gsi_stmt (gsi);
8405 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
8406 && gimple_omp_target_kind (stmt)
8407 == GF_OMP_TARGET_KIND_REGION);
8408 gsi_remove (&gsi, true);
8409 e = split_block (entry_bb, stmt);
8410 entry_bb = e->dest;
8411 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8413 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8414 if (exit_bb)
8416 gsi = gsi_last_bb (exit_bb);
8417 gcc_assert (!gsi_end_p (gsi)
8418 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8419 stmt = gimple_build_return (NULL);
8420 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8421 gsi_remove (&gsi, true);
8424 /* Move the target region into CHILD_CFUN. */
8426 block = gimple_block (entry_stmt);
8428 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8429 if (exit_bb)
8430 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8431 /* When the OMP expansion process cannot guarantee an up-to-date
8432 loop tree arrange for the child function to fixup loops. */
8433 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8434 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8436 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8437 num = vec_safe_length (child_cfun->local_decls);
8438 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8440 t = (*child_cfun->local_decls)[srcidx];
8441 if (DECL_CONTEXT (t) == cfun->decl)
8442 continue;
8443 if (srcidx != dstidx)
8444 (*child_cfun->local_decls)[dstidx] = t;
8445 dstidx++;
8447 if (dstidx != num)
8448 vec_safe_truncate (child_cfun->local_decls, dstidx);
8450 /* Inform the callgraph about the new function. */
8451 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8452 cgraph_add_new_function (child_fn, true);
8454 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8455 fixed in a following pass. */
8456 push_cfun (child_cfun);
8457 rebuild_cgraph_edges ();
8459 /* Some EH regions might become dead, see PR34608. If
8460 pass_cleanup_cfg isn't the first pass to happen with the
8461 new child, these dead EH edges might cause problems.
8462 Clean them up now. */
8463 if (flag_exceptions)
8465 basic_block bb;
8466 bool changed = false;
8468 FOR_EACH_BB_FN (bb, cfun)
8469 changed |= gimple_purge_dead_eh_edges (bb);
8470 if (changed)
8471 cleanup_tree_cfg ();
8473 pop_cfun ();
8476 /* Emit a library call to launch the target region, or do data
8477 transfers. */
8478 tree t1, t2, t3, t4, device, cond, c, clauses;
8479 enum built_in_function start_ix;
8480 location_t clause_loc;
8482 clauses = gimple_omp_target_clauses (entry_stmt);
8484 switch (kind)
8486 case GF_OMP_TARGET_KIND_REGION:
8487 start_ix = BUILT_IN_GOMP_TARGET;
8488 break;
8489 case GF_OMP_TARGET_KIND_DATA:
8490 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8491 break;
8492 case GF_OMP_TARGET_KIND_UPDATE:
8493 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8494 break;
8495 case GF_OMP_TARGET_KIND_OACC_DATA:
8496 start_ix = BUILT_IN_GOACC_DATA_START;
8497 break;
8498 default:
8499 gcc_unreachable ();
8502 /* By default, the value of DEVICE is -1 (let runtime library choose)
8503 and there is no conditional. */
8504 cond = NULL_TREE;
8505 device = build_int_cst (integer_type_node, -1);
8507 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8508 gcc_assert (!c || kind != GF_OMP_TARGET_KIND_OACC_DATA);
8509 if (c)
8510 cond = OMP_CLAUSE_IF_EXPR (c);
8512 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8513 gcc_assert (!c || kind != GF_OMP_TARGET_KIND_OACC_DATA);
8514 if (c)
8516 device = OMP_CLAUSE_DEVICE_ID (c);
8517 clause_loc = OMP_CLAUSE_LOCATION (c);
8519 else
8520 clause_loc = gimple_location (entry_stmt);
8522 /* Ensure 'device' is of the correct type. */
8523 device = fold_convert_loc (clause_loc, integer_type_node, device);
8525 /* If we found the clause 'if (cond)', build
8526 (cond ? device : -2). */
8527 if (cond)
8529 gcc_assert (kind != GF_OMP_TARGET_KIND_OACC_DATA);
8530 cond = gimple_boolify (cond);
8532 basic_block cond_bb, then_bb, else_bb;
8533 edge e;
8534 tree tmp_var;
8536 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8537 if (kind != GF_OMP_TARGET_KIND_REGION)
8539 gsi = gsi_last_bb (new_bb);
8540 gsi_prev (&gsi);
8541 e = split_block (new_bb, gsi_stmt (gsi));
8543 else
8544 e = split_block (new_bb, NULL);
8545 cond_bb = e->src;
8546 new_bb = e->dest;
8547 remove_edge (e);
8549 then_bb = create_empty_bb (cond_bb);
8550 else_bb = create_empty_bb (then_bb);
8551 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8552 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8554 stmt = gimple_build_cond_empty (cond);
8555 gsi = gsi_last_bb (cond_bb);
8556 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8558 gsi = gsi_start_bb (then_bb);
8559 stmt = gimple_build_assign (tmp_var, device);
8560 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8562 gsi = gsi_start_bb (else_bb);
8563 stmt = gimple_build_assign (tmp_var,
8564 build_int_cst (integer_type_node, -2));
8565 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8567 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8568 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8569 if (current_loops)
8571 add_bb_to_loop (then_bb, cond_bb->loop_father);
8572 add_bb_to_loop (else_bb, cond_bb->loop_father);
8574 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8575 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8577 device = tmp_var;
8580 gsi = gsi_last_bb (new_bb);
8581 t = gimple_omp_target_data_arg (entry_stmt);
8582 if (t == NULL)
8584 t1 = size_zero_node;
8585 t2 = build_zero_cst (ptr_type_node);
8586 t3 = t2;
8587 t4 = t2;
8589 else
8591 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8592 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8593 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8594 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8595 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8598 gimple g;
8599 /* FIXME: This will be address of
8600 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8601 symbol, as soon as the linker plugin is able to create it for us. */
8602 tree openmp_target = build_zero_cst (ptr_type_node);
8603 if (kind == GF_OMP_TARGET_KIND_REGION)
8605 tree fnaddr = build_fold_addr_expr (child_fn);
8606 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8607 device, fnaddr, openmp_target, t1, t2, t3, t4);
8609 else
8610 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8611 device, openmp_target, t1, t2, t3, t4);
8612 gimple_set_location (g, gimple_location (entry_stmt));
8613 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8614 if (kind != GF_OMP_TARGET_KIND_REGION)
8616 g = gsi_stmt (gsi);
8617 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8618 gsi_remove (&gsi, true);
8620 if ((kind == GF_OMP_TARGET_KIND_DATA
8621 || kind == GF_OMP_TARGET_KIND_OACC_DATA)
8622 && region->exit)
8624 gsi = gsi_last_bb (region->exit);
8625 g = gsi_stmt (gsi);
8626 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8627 gsi_remove (&gsi, true);
8632 /* Expand the parallel region tree rooted at REGION. Expansion
8633 proceeds in depth-first order. Innermost regions are expanded
8634 first. This way, parallel regions that require a new function to
8635 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8636 internal dependencies in their body. */
8638 static void
8639 expand_omp (struct omp_region *region)
8641 while (region)
8643 location_t saved_location;
8644 gimple inner_stmt = NULL;
8646 /* First, determine whether this is a combined parallel+workshare
8647 region. */
8648 if (region->type == GIMPLE_OMP_PARALLEL)
8649 determine_parallel_type (region);
8651 if (region->type == GIMPLE_OMP_FOR
8652 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8653 inner_stmt = last_stmt (region->inner->entry);
8655 if (region->inner)
8656 expand_omp (region->inner);
8658 saved_location = input_location;
8659 if (gimple_has_location (last_stmt (region->entry)))
8660 input_location = gimple_location (last_stmt (region->entry));
8662 switch (region->type)
8664 case GIMPLE_OACC_KERNELS:
8665 case GIMPLE_OACC_PARALLEL:
8666 expand_oacc_offload (region);
8667 break;
8669 case GIMPLE_OMP_PARALLEL:
8670 case GIMPLE_OMP_TASK:
8671 expand_omp_taskreg (region);
8672 break;
8674 case GIMPLE_OMP_FOR:
8675 expand_omp_for (region, inner_stmt);
8676 break;
8678 case GIMPLE_OMP_SECTIONS:
8679 expand_omp_sections (region);
8680 break;
8682 case GIMPLE_OMP_SECTION:
8683 /* Individual omp sections are handled together with their
8684 parent GIMPLE_OMP_SECTIONS region. */
8685 break;
8687 case GIMPLE_OMP_SINGLE:
8688 expand_omp_single (region);
8689 break;
8691 case GIMPLE_OMP_MASTER:
8692 case GIMPLE_OMP_TASKGROUP:
8693 case GIMPLE_OMP_ORDERED:
8694 case GIMPLE_OMP_CRITICAL:
8695 case GIMPLE_OMP_TEAMS:
8696 expand_omp_synch (region);
8697 break;
8699 case GIMPLE_OMP_ATOMIC_LOAD:
8700 expand_omp_atomic (region);
8701 break;
8703 case GIMPLE_OMP_TARGET:
8704 expand_omp_target (region);
8705 break;
8707 default:
8708 gcc_unreachable ();
8711 input_location = saved_location;
8712 region = region->next;
8717 /* Helper for build_omp_regions. Scan the dominator tree starting at
8718 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8719 true, the function ends once a single tree is built (otherwise, whole
8720 forest of OMP constructs may be built). */
8722 static void
8723 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8724 bool single_tree)
8726 gimple_stmt_iterator gsi;
8727 gimple stmt;
8728 basic_block son;
8730 gsi = gsi_last_bb (bb);
8731 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8733 struct omp_region *region;
8734 enum gimple_code code;
8736 stmt = gsi_stmt (gsi);
8737 code = gimple_code (stmt);
8738 if (code == GIMPLE_OMP_RETURN)
8740 /* STMT is the return point out of region PARENT. Mark it
8741 as the exit point and make PARENT the immediately
8742 enclosing region. */
8743 gcc_assert (parent);
8744 region = parent;
8745 region->exit = bb;
8746 parent = parent->outer;
8748 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8750 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8751 GIMPLE_OMP_RETURN, but matches with
8752 GIMPLE_OMP_ATOMIC_LOAD. */
8753 gcc_assert (parent);
8754 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8755 region = parent;
8756 region->exit = bb;
8757 parent = parent->outer;
8760 else if (code == GIMPLE_OMP_CONTINUE)
8762 gcc_assert (parent);
8763 parent->cont = bb;
8765 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8767 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8768 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8771 else if (code == GIMPLE_OMP_TARGET
8772 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8773 new_omp_region (bb, code, parent);
8774 else
8776 /* Otherwise, this directive becomes the parent for a new
8777 region. */
8778 region = new_omp_region (bb, code, parent);
8779 parent = region;
8783 if (single_tree && !parent)
8784 return;
8786 for (son = first_dom_son (CDI_DOMINATORS, bb);
8787 son;
8788 son = next_dom_son (CDI_DOMINATORS, son))
8789 build_omp_regions_1 (son, parent, single_tree);
8792 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8793 root_omp_region. */
8795 static void
8796 build_omp_regions_root (basic_block root)
8798 gcc_assert (root_omp_region == NULL);
8799 build_omp_regions_1 (root, NULL, true);
8800 gcc_assert (root_omp_region != NULL);
8803 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8805 void
8806 omp_expand_local (basic_block head)
8808 build_omp_regions_root (head);
8809 if (dump_file && (dump_flags & TDF_DETAILS))
8811 fprintf (dump_file, "\nOMP region tree\n\n");
8812 dump_omp_region (dump_file, root_omp_region, 0);
8813 fprintf (dump_file, "\n");
8816 remove_exit_barriers (root_omp_region);
8817 expand_omp (root_omp_region);
8819 free_omp_regions ();
8822 /* Scan the CFG and build a tree of OMP regions. Return the root of
8823 the OMP region tree. */
8825 static void
8826 build_omp_regions (void)
8828 gcc_assert (root_omp_region == NULL);
8829 calculate_dominance_info (CDI_DOMINATORS);
8830 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8833 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8835 static unsigned int
8836 execute_expand_omp (void)
8838 build_omp_regions ();
8840 if (!root_omp_region)
8841 return 0;
8843 if (dump_file)
8845 fprintf (dump_file, "\nOMP region tree\n\n");
8846 dump_omp_region (dump_file, root_omp_region, 0);
8847 fprintf (dump_file, "\n");
8850 remove_exit_barriers (root_omp_region);
8852 expand_omp (root_omp_region);
8854 cleanup_tree_cfg ();
8856 free_omp_regions ();
8858 return 0;
8861 /* OMP expansion -- the default pass, run before creation of SSA form. */
8863 static bool
8864 gate_expand_omp (void)
8866 return ((flag_openacc != 0 || flag_openmp != 0 || flag_openmp_simd != 0
8867 || flag_cilkplus != 0) && !seen_error ());
8870 namespace {
8872 const pass_data pass_data_expand_omp =
8874 GIMPLE_PASS, /* type */
8875 "ompexp", /* name */
8876 OPTGROUP_NONE, /* optinfo_flags */
8877 true, /* has_gate */
8878 true, /* has_execute */
8879 TV_NONE, /* tv_id */
8880 PROP_gimple_any, /* properties_required */
8881 0, /* properties_provided */
8882 0, /* properties_destroyed */
8883 0, /* todo_flags_start */
8884 0, /* todo_flags_finish */
8887 class pass_expand_omp : public gimple_opt_pass
8889 public:
8890 pass_expand_omp (gcc::context *ctxt)
8891 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8894 /* opt_pass methods: */
8895 bool gate () { return gate_expand_omp (); }
8896 unsigned int execute () { return execute_expand_omp (); }
8898 }; // class pass_expand_omp
8900 } // anon namespace
8902 gimple_opt_pass *
8903 make_pass_expand_omp (gcc::context *ctxt)
8905 return new pass_expand_omp (ctxt);
8908 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8910 /* Lower the OpenACC offload directive in the current statement
8911 in GSI_P. CTX holds context information for the directive. */
8913 static void
8914 lower_oacc_offload (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8916 tree clauses;
8917 tree child_fn, t, c;
8918 gimple stmt = gsi_stmt (*gsi_p);
8919 gimple par_bind, bind;
8920 gimple_seq par_body, olist, ilist, new_body;
8921 location_t loc = gimple_location (stmt);
8922 unsigned int map_cnt = 0;
8923 tree (*gimple_omp_clauses) (const_gimple);
8924 void (*gimple_omp_set_data_arg) (gimple, tree);
8925 switch (gimple_code (stmt))
8927 case GIMPLE_OACC_KERNELS:
8928 gimple_omp_clauses = gimple_oacc_kernels_clauses;
8929 gimple_omp_set_data_arg = gimple_oacc_kernels_set_data_arg;
8930 break;
8931 case GIMPLE_OACC_PARALLEL:
8932 gimple_omp_clauses = gimple_oacc_parallel_clauses;
8933 gimple_omp_set_data_arg = gimple_oacc_parallel_set_data_arg;
8934 break;
8935 default:
8936 gcc_unreachable ();
8939 clauses = gimple_omp_clauses (stmt);
8940 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
8941 par_body = gimple_bind_body (par_bind);
8942 child_fn = ctx->cb.dst_fn;
8944 push_gimplify_context ();
8946 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
8947 switch (OMP_CLAUSE_CODE (c))
8949 tree var, x;
8951 default:
8952 break;
8953 case OMP_CLAUSE_MAP:
8954 var = OMP_CLAUSE_DECL (c);
8955 if (!DECL_P (var))
8957 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
8958 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
8959 map_cnt++;
8960 continue;
8963 if (DECL_SIZE (var)
8964 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
8966 tree var2 = DECL_VALUE_EXPR (var);
8967 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
8968 var2 = TREE_OPERAND (var2, 0);
8969 gcc_assert (DECL_P (var2));
8970 var = var2;
8973 if (!maybe_lookup_field (var, ctx))
8974 continue;
8976 /* Preserve indentation of lower_omp_target. */
8977 if (1)
8979 x = build_receiver_ref (var, true, ctx);
8980 tree new_var = lookup_decl (var, ctx);
8981 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
8982 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
8983 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
8984 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
8985 x = build_simple_mem_ref (x);
8986 SET_DECL_VALUE_EXPR (new_var, x);
8987 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
8989 map_cnt++;
8992 target_nesting_level++;
8993 lower_omp (&par_body, ctx);
8994 target_nesting_level--;
8996 /* Declare all the variables created by mapping and the variables
8997 declared in the scope of the body. */
8998 record_vars_into (ctx->block_vars, child_fn);
8999 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9001 olist = NULL;
9002 ilist = NULL;
9003 if (ctx->record_type)
9005 ctx->sender_decl
9006 = create_tmp_var (ctx->record_type, ".omp_data_arr");
9007 DECL_NAMELESS (ctx->sender_decl) = 1;
9008 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9009 t = make_tree_vec (3);
9010 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
9011 TREE_VEC_ELT (t, 1)
9012 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
9013 ".omp_data_sizes");
9014 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
9015 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
9016 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
9017 TREE_VEC_ELT (t, 2)
9018 = create_tmp_var (build_array_type_nelts (short_unsigned_type_node,
9019 map_cnt),
9020 ".omp_data_kinds");
9021 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
9022 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
9023 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
9024 gimple_omp_set_data_arg (stmt, t);
9026 vec<constructor_elt, va_gc> *vsize;
9027 vec<constructor_elt, va_gc> *vkind;
9028 vec_alloc (vsize, map_cnt);
9029 vec_alloc (vkind, map_cnt);
9030 unsigned int map_idx = 0;
9032 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9033 switch (OMP_CLAUSE_CODE (c))
9035 tree ovar, nc;
9037 default:
9038 break;
9039 case OMP_CLAUSE_MAP:
9040 nc = c;
9041 ovar = OMP_CLAUSE_DECL (c);
9042 if (!DECL_P (ovar))
9044 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9045 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9047 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
9048 == get_base_address (ovar));
9049 nc = OMP_CLAUSE_CHAIN (c);
9050 ovar = OMP_CLAUSE_DECL (nc);
9052 else
9054 tree x = build_sender_ref (ovar, ctx);
9055 tree v
9056 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
9057 gimplify_assign (x, v, &ilist);
9058 nc = NULL_TREE;
9061 else
9063 if (DECL_SIZE (ovar)
9064 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
9066 tree ovar2 = DECL_VALUE_EXPR (ovar);
9067 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
9068 ovar2 = TREE_OPERAND (ovar2, 0);
9069 gcc_assert (DECL_P (ovar2));
9070 ovar = ovar2;
9072 if (!maybe_lookup_field (ovar, ctx))
9073 continue;
9076 if (nc)
9078 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
9079 tree x = build_sender_ref (ovar, ctx);
9080 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9081 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9082 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9083 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
9085 tree avar
9086 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
9087 mark_addressable (avar);
9088 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
9089 avar = build_fold_addr_expr (avar);
9090 gimplify_assign (x, avar, &ilist);
9092 else if (is_gimple_reg (var))
9094 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
9095 mark_addressable (avar);
9096 enum omp_clause_map_kind map_kind
9097 = OMP_CLAUSE_MAP_KIND (c);
9098 if ((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
9099 && (map_kind & OMP_CLAUSE_MAP_TO))
9100 || map_kind == OMP_CLAUSE_MAP_POINTER)
9101 gimplify_assign (avar, var, &ilist);
9102 avar = build_fold_addr_expr (avar);
9103 gimplify_assign (x, avar, &ilist);
9104 if ((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
9105 && (map_kind & OMP_CLAUSE_MAP_FROM))
9106 && !TYPE_READONLY (TREE_TYPE (var)))
9108 x = build_sender_ref (ovar, ctx);
9109 x = build_simple_mem_ref (x);
9110 gimplify_assign (var, x, &olist);
9113 else
9115 var = build_fold_addr_expr (var);
9116 gimplify_assign (x, var, &ilist);
9119 tree s = OMP_CLAUSE_SIZE (c);
9120 if (s == NULL_TREE)
9121 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
9122 s = fold_convert (size_type_node, s);
9123 tree purpose = size_int (map_idx++);
9124 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
9125 if (TREE_CODE (s) != INTEGER_CST)
9126 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
9128 unsigned short tkind = 0;
9129 switch (OMP_CLAUSE_CODE (c))
9131 case OMP_CLAUSE_MAP:
9132 tkind = OMP_CLAUSE_MAP_KIND (c);
9133 break;
9134 default:
9135 gcc_unreachable ();
9137 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
9138 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
9139 talign = DECL_ALIGN_UNIT (ovar);
9140 talign = ceil_log2 (talign);
9141 tkind |= talign << 8;
9142 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
9143 build_int_cst (short_unsigned_type_node,
9144 tkind));
9145 if (nc && nc != c)
9146 c = nc;
9149 gcc_assert (map_idx == map_cnt);
9151 DECL_INITIAL (TREE_VEC_ELT (t, 1))
9152 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
9153 DECL_INITIAL (TREE_VEC_ELT (t, 2))
9154 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
9155 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
9157 gimple_seq initlist = NULL;
9158 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
9159 TREE_VEC_ELT (t, 1)),
9160 &initlist, true, NULL_TREE);
9161 gimple_seq_add_seq (&ilist, initlist);
9163 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
9164 NULL);
9165 TREE_THIS_VOLATILE (clobber) = 1;
9166 gimple_seq_add_stmt (&olist,
9167 gimple_build_assign (TREE_VEC_ELT (t, 1),
9168 clobber));
9171 tree clobber = build_constructor (ctx->record_type, NULL);
9172 TREE_THIS_VOLATILE (clobber) = 1;
9173 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9174 clobber));
9177 /* Once all the expansions are done, sequence all the different
9178 fragments inside gimple_omp_body. */
9180 new_body = NULL;
9182 if (ctx->record_type)
9184 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9185 /* fixup_child_record_type might have changed receiver_decl's type. */
9186 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9187 gimple_seq_add_stmt (&new_body,
9188 gimple_build_assign (ctx->receiver_decl, t));
9191 gimple_seq_add_seq (&new_body, par_body);
9192 gcc_assert (!ctx->cancellable);
9193 new_body = maybe_catch_exception (new_body);
9194 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9195 gimple_omp_set_body (stmt, new_body);
9197 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9198 gsi_replace (gsi_p, bind, true);
9199 gimple_bind_add_seq (bind, ilist);
9200 gimple_bind_add_stmt (bind, stmt);
9201 gimple_bind_add_seq (bind, olist);
9203 pop_gimplify_context (NULL);
9206 /* If ctx is a worksharing context inside of a cancellable parallel
9207 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9208 and conditional branch to parallel's cancel_label to handle
9209 cancellation in the implicit barrier. */
9211 static void
9212 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9214 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
9216 gimple omp_return = gimple_seq_last_stmt (*body);
9217 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
9218 if (gimple_omp_return_nowait_p (omp_return))
9219 return;
9220 if (ctx->outer
9221 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
9222 && ctx->outer->cancellable)
9224 tree lhs = create_tmp_var (boolean_type_node, NULL);
9225 gimple_omp_return_set_lhs (omp_return, lhs);
9226 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
9227 gimple g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
9228 ctx->outer->cancel_label, fallthru_label);
9229 gimple_seq_add_stmt (body, g);
9230 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
9234 /* Lower the OpenMP sections directive in the current statement in GSI_P.
9235 CTX is the enclosing OMP context for the current statement. */
9237 static void
9238 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9240 tree block, control;
9241 gimple_stmt_iterator tgsi;
9242 gimple stmt, new_stmt, bind, t;
9243 gimple_seq ilist, dlist, olist, new_body;
9245 stmt = gsi_stmt (*gsi_p);
9247 push_gimplify_context ();
9249 dlist = NULL;
9250 ilist = NULL;
9251 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
9252 &ilist, &dlist, ctx, NULL);
9254 new_body = gimple_omp_body (stmt);
9255 gimple_omp_set_body (stmt, NULL);
9256 tgsi = gsi_start (new_body);
9257 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
9259 omp_context *sctx;
9260 gimple sec_start;
9262 sec_start = gsi_stmt (tgsi);
9263 sctx = maybe_lookup_ctx (sec_start);
9264 gcc_assert (sctx);
9266 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
9267 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
9268 GSI_CONTINUE_LINKING);
9269 gimple_omp_set_body (sec_start, NULL);
9271 if (gsi_one_before_end_p (tgsi))
9273 gimple_seq l = NULL;
9274 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
9275 &l, ctx);
9276 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
9277 gimple_omp_section_set_last (sec_start);
9280 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
9281 GSI_CONTINUE_LINKING);
9284 block = make_node (BLOCK);
9285 bind = gimple_build_bind (NULL, new_body, block);
9287 olist = NULL;
9288 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
9290 block = make_node (BLOCK);
9291 new_stmt = gimple_build_bind (NULL, NULL, block);
9292 gsi_replace (gsi_p, new_stmt, true);
9294 pop_gimplify_context (new_stmt);
9295 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9296 BLOCK_VARS (block) = gimple_bind_vars (bind);
9297 if (BLOCK_VARS (block))
9298 TREE_USED (block) = 1;
9300 new_body = NULL;
9301 gimple_seq_add_seq (&new_body, ilist);
9302 gimple_seq_add_stmt (&new_body, stmt);
9303 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
9304 gimple_seq_add_stmt (&new_body, bind);
9306 control = create_tmp_var (unsigned_type_node, ".section");
9307 t = gimple_build_omp_continue (control, control);
9308 gimple_omp_sections_set_control (stmt, control);
9309 gimple_seq_add_stmt (&new_body, t);
9311 gimple_seq_add_seq (&new_body, olist);
9312 if (ctx->cancellable)
9313 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9314 gimple_seq_add_seq (&new_body, dlist);
9316 new_body = maybe_catch_exception (new_body);
9318 t = gimple_build_omp_return
9319 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
9320 OMP_CLAUSE_NOWAIT));
9321 gimple_seq_add_stmt (&new_body, t);
9322 maybe_add_implicit_barrier_cancel (ctx, &new_body);
9324 gimple_bind_set_body (new_stmt, new_body);
9328 /* A subroutine of lower_omp_single. Expand the simple form of
9329 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
9331 if (GOMP_single_start ())
9332 BODY;
9333 [ GOMP_barrier (); ] -> unless 'nowait' is present.
9335 FIXME. It may be better to delay expanding the logic of this until
9336 pass_expand_omp. The expanded logic may make the job more difficult
9337 to a synchronization analysis pass. */
9339 static void
9340 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
9342 location_t loc = gimple_location (single_stmt);
9343 tree tlabel = create_artificial_label (loc);
9344 tree flabel = create_artificial_label (loc);
9345 gimple call, cond;
9346 tree lhs, decl;
9348 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
9349 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
9350 call = gimple_build_call (decl, 0);
9351 gimple_call_set_lhs (call, lhs);
9352 gimple_seq_add_stmt (pre_p, call);
9354 cond = gimple_build_cond (EQ_EXPR, lhs,
9355 fold_convert_loc (loc, TREE_TYPE (lhs),
9356 boolean_true_node),
9357 tlabel, flabel);
9358 gimple_seq_add_stmt (pre_p, cond);
9359 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
9360 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9361 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
9365 /* A subroutine of lower_omp_single. Expand the simple form of
9366 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
9368 #pragma omp single copyprivate (a, b, c)
9370 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
9373 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
9375 BODY;
9376 copyout.a = a;
9377 copyout.b = b;
9378 copyout.c = c;
9379 GOMP_single_copy_end (&copyout);
9381 else
9383 a = copyout_p->a;
9384 b = copyout_p->b;
9385 c = copyout_p->c;
9387 GOMP_barrier ();
9390 FIXME. It may be better to delay expanding the logic of this until
9391 pass_expand_omp. The expanded logic may make the job more difficult
9392 to a synchronization analysis pass. */
9394 static void
9395 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
9397 tree ptr_type, t, l0, l1, l2, bfn_decl;
9398 gimple_seq copyin_seq;
9399 location_t loc = gimple_location (single_stmt);
9401 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
9403 ptr_type = build_pointer_type (ctx->record_type);
9404 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
9406 l0 = create_artificial_label (loc);
9407 l1 = create_artificial_label (loc);
9408 l2 = create_artificial_label (loc);
9410 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
9411 t = build_call_expr_loc (loc, bfn_decl, 0);
9412 t = fold_convert_loc (loc, ptr_type, t);
9413 gimplify_assign (ctx->receiver_decl, t, pre_p);
9415 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
9416 build_int_cst (ptr_type, 0));
9417 t = build3 (COND_EXPR, void_type_node, t,
9418 build_and_jump (&l0), build_and_jump (&l1));
9419 gimplify_and_add (t, pre_p);
9421 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
9423 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9425 copyin_seq = NULL;
9426 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
9427 &copyin_seq, ctx);
9429 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9430 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
9431 t = build_call_expr_loc (loc, bfn_decl, 1, t);
9432 gimplify_and_add (t, pre_p);
9434 t = build_and_jump (&l2);
9435 gimplify_and_add (t, pre_p);
9437 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
9439 gimple_seq_add_seq (pre_p, copyin_seq);
9441 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
9445 /* Expand code for an OpenMP single directive. */
9447 static void
9448 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9450 tree block;
9451 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
9452 gimple_seq bind_body, bind_body_tail = NULL, dlist;
9454 push_gimplify_context ();
9456 block = make_node (BLOCK);
9457 bind = gimple_build_bind (NULL, NULL, block);
9458 gsi_replace (gsi_p, bind, true);
9459 bind_body = NULL;
9460 dlist = NULL;
9461 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
9462 &bind_body, &dlist, ctx, NULL);
9463 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
9465 gimple_seq_add_stmt (&bind_body, single_stmt);
9467 if (ctx->record_type)
9468 lower_omp_single_copy (single_stmt, &bind_body, ctx);
9469 else
9470 lower_omp_single_simple (single_stmt, &bind_body);
9472 gimple_omp_set_body (single_stmt, NULL);
9474 gimple_seq_add_seq (&bind_body, dlist);
9476 bind_body = maybe_catch_exception (bind_body);
9478 t = gimple_build_omp_return
9479 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
9480 OMP_CLAUSE_NOWAIT));
9481 gimple_seq_add_stmt (&bind_body_tail, t);
9482 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
9483 if (ctx->record_type)
9485 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9486 tree clobber = build_constructor (ctx->record_type, NULL);
9487 TREE_THIS_VOLATILE (clobber) = 1;
9488 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9489 clobber), GSI_SAME_STMT);
9491 gimple_seq_add_seq (&bind_body, bind_body_tail);
9492 gimple_bind_set_body (bind, bind_body);
9494 pop_gimplify_context (bind);
9496 gimple_bind_append_vars (bind, ctx->block_vars);
9497 BLOCK_VARS (block) = ctx->block_vars;
9498 if (BLOCK_VARS (block))
9499 TREE_USED (block) = 1;
9503 /* Expand code for an OpenMP master directive. */
9505 static void
9506 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9508 tree block, lab = NULL, x, bfn_decl;
9509 gimple stmt = gsi_stmt (*gsi_p), bind;
9510 location_t loc = gimple_location (stmt);
9511 gimple_seq tseq;
9513 push_gimplify_context ();
9515 block = make_node (BLOCK);
9516 bind = gimple_build_bind (NULL, NULL, block);
9517 gsi_replace (gsi_p, bind, true);
9518 gimple_bind_add_stmt (bind, stmt);
9520 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9521 x = build_call_expr_loc (loc, bfn_decl, 0);
9522 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
9523 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9524 tseq = NULL;
9525 gimplify_and_add (x, &tseq);
9526 gimple_bind_add_seq (bind, tseq);
9528 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9529 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9530 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9531 gimple_omp_set_body (stmt, NULL);
9533 gimple_bind_add_stmt (bind, gimple_build_label (lab));
9535 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9537 pop_gimplify_context (bind);
9539 gimple_bind_append_vars (bind, ctx->block_vars);
9540 BLOCK_VARS (block) = ctx->block_vars;
9544 /* Expand code for an OpenMP taskgroup directive. */
9546 static void
9547 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9549 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9550 tree block = make_node (BLOCK);
9552 bind = gimple_build_bind (NULL, NULL, block);
9553 gsi_replace (gsi_p, bind, true);
9554 gimple_bind_add_stmt (bind, stmt);
9556 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9558 gimple_bind_add_stmt (bind, x);
9560 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9561 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9562 gimple_omp_set_body (stmt, NULL);
9564 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9566 gimple_bind_append_vars (bind, ctx->block_vars);
9567 BLOCK_VARS (block) = ctx->block_vars;
9571 /* Expand code for an OpenMP ordered directive. */
9573 static void
9574 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9576 tree block;
9577 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9579 push_gimplify_context ();
9581 block = make_node (BLOCK);
9582 bind = gimple_build_bind (NULL, NULL, block);
9583 gsi_replace (gsi_p, bind, true);
9584 gimple_bind_add_stmt (bind, stmt);
9586 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
9588 gimple_bind_add_stmt (bind, x);
9590 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9591 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9592 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9593 gimple_omp_set_body (stmt, NULL);
9595 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
9596 gimple_bind_add_stmt (bind, x);
9598 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9600 pop_gimplify_context (bind);
9602 gimple_bind_append_vars (bind, ctx->block_vars);
9603 BLOCK_VARS (block) = gimple_bind_vars (bind);
9607 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9608 substitution of a couple of function calls. But in the NAMED case,
9609 requires that languages coordinate a symbol name. It is therefore
9610 best put here in common code. */
9612 static GTY((param1_is (tree), param2_is (tree)))
9613 splay_tree critical_name_mutexes;
9615 static void
9616 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9618 tree block;
9619 tree name, lock, unlock;
9620 gimple stmt = gsi_stmt (*gsi_p), bind;
9621 location_t loc = gimple_location (stmt);
9622 gimple_seq tbody;
9624 name = gimple_omp_critical_name (stmt);
9625 if (name)
9627 tree decl;
9628 splay_tree_node n;
9630 if (!critical_name_mutexes)
9631 critical_name_mutexes
9632 = splay_tree_new_ggc (splay_tree_compare_pointers,
9633 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
9634 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
9636 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
9637 if (n == NULL)
9639 char *new_str;
9641 decl = create_tmp_var_raw (ptr_type_node, NULL);
9643 new_str = ACONCAT ((".gomp_critical_user_",
9644 IDENTIFIER_POINTER (name), NULL));
9645 DECL_NAME (decl) = get_identifier (new_str);
9646 TREE_PUBLIC (decl) = 1;
9647 TREE_STATIC (decl) = 1;
9648 DECL_COMMON (decl) = 1;
9649 DECL_ARTIFICIAL (decl) = 1;
9650 DECL_IGNORED_P (decl) = 1;
9651 varpool_finalize_decl (decl);
9653 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
9654 (splay_tree_value) decl);
9656 else
9657 decl = (tree) n->value;
9659 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
9660 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
9662 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
9663 unlock = build_call_expr_loc (loc, unlock, 1,
9664 build_fold_addr_expr_loc (loc, decl));
9666 else
9668 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
9669 lock = build_call_expr_loc (loc, lock, 0);
9671 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
9672 unlock = build_call_expr_loc (loc, unlock, 0);
9675 push_gimplify_context ();
9677 block = make_node (BLOCK);
9678 bind = gimple_build_bind (NULL, NULL, block);
9679 gsi_replace (gsi_p, bind, true);
9680 gimple_bind_add_stmt (bind, stmt);
9682 tbody = gimple_bind_body (bind);
9683 gimplify_and_add (lock, &tbody);
9684 gimple_bind_set_body (bind, tbody);
9686 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9687 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9688 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9689 gimple_omp_set_body (stmt, NULL);
9691 tbody = gimple_bind_body (bind);
9692 gimplify_and_add (unlock, &tbody);
9693 gimple_bind_set_body (bind, tbody);
9695 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9697 pop_gimplify_context (bind);
9698 gimple_bind_append_vars (bind, ctx->block_vars);
9699 BLOCK_VARS (block) = gimple_bind_vars (bind);
9703 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9704 for a lastprivate clause. Given a loop control predicate of (V
9705 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9706 is appended to *DLIST, iterator initialization is appended to
9707 *BODY_P. */
9709 static void
9710 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
9711 gimple_seq *dlist, struct omp_context *ctx)
9713 tree clauses, cond, vinit;
9714 enum tree_code cond_code;
9715 gimple_seq stmts;
9717 cond_code = fd->loop.cond_code;
9718 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
9720 /* When possible, use a strict equality expression. This can let VRP
9721 type optimizations deduce the value and remove a copy. */
9722 if (tree_fits_shwi_p (fd->loop.step))
9724 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
9725 if (step == 1 || step == -1)
9726 cond_code = EQ_EXPR;
9729 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
9731 clauses = gimple_omp_for_clauses (fd->for_stmt);
9732 stmts = NULL;
9733 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
9734 if (!gimple_seq_empty_p (stmts))
9736 gimple_seq_add_seq (&stmts, *dlist);
9737 *dlist = stmts;
9739 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9740 vinit = fd->loop.n1;
9741 if (cond_code == EQ_EXPR
9742 && tree_fits_shwi_p (fd->loop.n2)
9743 && ! integer_zerop (fd->loop.n2))
9744 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
9745 else
9746 vinit = unshare_expr (vinit);
9748 /* Initialize the iterator variable, so that threads that don't execute
9749 any iterations don't execute the lastprivate clauses by accident. */
9750 gimplify_assign (fd->loop.v, vinit, body_p);
9755 /* Lower code for an OpenMP loop directive. */
9757 static void
9758 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9760 tree *rhs_p, block;
9761 struct omp_for_data fd, *fdp = NULL;
9762 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
9763 gimple_seq omp_for_body, body, dlist;
9764 size_t i;
9766 push_gimplify_context ();
9768 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
9770 block = make_node (BLOCK);
9771 new_stmt = gimple_build_bind (NULL, NULL, block);
9772 /* Replace at gsi right away, so that 'stmt' is no member
9773 of a sequence anymore as we're going to add to to a different
9774 one below. */
9775 gsi_replace (gsi_p, new_stmt, true);
9777 /* Move declaration of temporaries in the loop body before we make
9778 it go away. */
9779 omp_for_body = gimple_omp_body (stmt);
9780 if (!gimple_seq_empty_p (omp_for_body)
9781 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9783 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
9784 tree vars = gimple_bind_vars (inner_bind);
9785 gimple_bind_append_vars (new_stmt, vars);
9786 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9787 keep them on the inner_bind and it's block. */
9788 gimple_bind_set_vars (inner_bind, NULL_TREE);
9789 if (gimple_bind_block (inner_bind))
9790 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9793 if (gimple_omp_for_combined_into_p (stmt))
9795 extract_omp_for_data (stmt, &fd, NULL);
9796 fdp = &fd;
9798 /* We need two temporaries with fd.loop.v type (istart/iend)
9799 and then (fd.collapse - 1) temporaries with the same
9800 type for count2 ... countN-1 vars if not constant. */
9801 size_t count = 2;
9802 tree type = fd.iter_type;
9803 if (fd.collapse > 1
9804 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9805 count += fd.collapse - 1;
9806 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9807 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9808 tree clauses = *pc;
9809 if (parallel_for)
9810 outerc
9811 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9812 OMP_CLAUSE__LOOPTEMP_);
9813 for (i = 0; i < count; i++)
9815 tree temp;
9816 if (parallel_for)
9818 gcc_assert (outerc);
9819 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9820 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9821 OMP_CLAUSE__LOOPTEMP_);
9823 else
9824 temp = create_tmp_var (type, NULL);
9825 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9826 OMP_CLAUSE_DECL (*pc) = temp;
9827 pc = &OMP_CLAUSE_CHAIN (*pc);
9829 *pc = clauses;
9832 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9833 dlist = NULL;
9834 body = NULL;
9835 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9836 fdp);
9837 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9839 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9841 /* Lower the header expressions. At this point, we can assume that
9842 the header is of the form:
9844 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9846 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9847 using the .omp_data_s mapping, if needed. */
9848 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9850 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9851 if (!is_gimple_min_invariant (*rhs_p))
9852 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9854 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9855 if (!is_gimple_min_invariant (*rhs_p))
9856 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9858 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9859 if (!is_gimple_min_invariant (*rhs_p))
9860 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9863 /* Once lowered, extract the bounds and clauses. */
9864 extract_omp_for_data (stmt, &fd, NULL);
9866 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9868 gimple_seq_add_stmt (&body, stmt);
9869 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9871 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9872 fd.loop.v));
9874 /* After the loop, add exit clauses. */
9875 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9877 if (ctx->cancellable)
9878 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9880 gimple_seq_add_seq (&body, dlist);
9882 body = maybe_catch_exception (body);
9884 /* Region exit marker goes at the end of the loop body. */
9885 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9886 maybe_add_implicit_barrier_cancel (ctx, &body);
9887 pop_gimplify_context (new_stmt);
9889 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9890 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9891 if (BLOCK_VARS (block))
9892 TREE_USED (block) = 1;
9894 gimple_bind_set_body (new_stmt, body);
9895 gimple_omp_set_body (stmt, NULL);
9896 gimple_omp_for_set_pre_body (stmt, NULL);
9899 /* Callback for walk_stmts. Check if the current statement only contains
9900 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9902 static tree
9903 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9904 bool *handled_ops_p,
9905 struct walk_stmt_info *wi)
9907 int *info = (int *) wi->info;
9908 gimple stmt = gsi_stmt (*gsi_p);
9910 *handled_ops_p = true;
9911 switch (gimple_code (stmt))
9913 WALK_SUBSTMTS;
9915 case GIMPLE_OMP_FOR:
9916 case GIMPLE_OMP_SECTIONS:
9917 *info = *info == 0 ? 1 : -1;
9918 break;
9919 default:
9920 *info = -1;
9921 break;
9923 return NULL;
9926 struct omp_taskcopy_context
9928 /* This field must be at the beginning, as we do "inheritance": Some
9929 callback functions for tree-inline.c (e.g., omp_copy_decl)
9930 receive a copy_body_data pointer that is up-casted to an
9931 omp_context pointer. */
9932 copy_body_data cb;
9933 omp_context *ctx;
9936 static tree
9937 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9939 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9941 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9942 return create_tmp_var (TREE_TYPE (var), NULL);
9944 return var;
9947 static tree
9948 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9950 tree name, new_fields = NULL, type, f;
9952 type = lang_hooks.types.make_type (RECORD_TYPE);
9953 name = DECL_NAME (TYPE_NAME (orig_type));
9954 name = build_decl (gimple_location (tcctx->ctx->stmt),
9955 TYPE_DECL, name, type);
9956 TYPE_NAME (type) = name;
9958 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9960 tree new_f = copy_node (f);
9961 DECL_CONTEXT (new_f) = type;
9962 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9963 TREE_CHAIN (new_f) = new_fields;
9964 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9965 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9966 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9967 &tcctx->cb, NULL);
9968 new_fields = new_f;
9969 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
9971 TYPE_FIELDS (type) = nreverse (new_fields);
9972 layout_type (type);
9973 return type;
9976 /* Create task copyfn. */
9978 static void
9979 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9981 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
9983 struct function *child_cfun;
9984 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9985 tree record_type, srecord_type, bind, list;
9986 bool record_needs_remap = false, srecord_needs_remap = false;
9987 splay_tree_node n;
9988 struct omp_taskcopy_context tcctx;
9989 location_t loc = gimple_location (task_stmt);
9991 child_fn = gimple_omp_task_copy_fn (task_stmt);
9992 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9993 gcc_assert (child_cfun->cfg == NULL);
9994 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9996 /* Reset DECL_CONTEXT on function arguments. */
9997 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9998 DECL_CONTEXT (t) = child_fn;
10000 /* Populate the function. */
10001 push_gimplify_context ();
10002 push_cfun (child_cfun);
10004 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10005 TREE_SIDE_EFFECTS (bind) = 1;
10006 list = NULL;
10007 DECL_SAVED_TREE (child_fn) = bind;
10008 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10010 /* Remap src and dst argument types if needed. */
10011 record_type = ctx->record_type;
10012 srecord_type = ctx->srecord_type;
10013 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10014 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10016 record_needs_remap = true;
10017 break;
10019 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10020 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10022 srecord_needs_remap = true;
10023 break;
10026 if (record_needs_remap || srecord_needs_remap)
10028 memset (&tcctx, '\0', sizeof (tcctx));
10029 tcctx.cb.src_fn = ctx->cb.src_fn;
10030 tcctx.cb.dst_fn = child_fn;
10031 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
10032 gcc_checking_assert (tcctx.cb.src_node);
10033 tcctx.cb.dst_node = tcctx.cb.src_node;
10034 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10035 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10036 tcctx.cb.eh_lp_nr = 0;
10037 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10038 tcctx.cb.decl_map = pointer_map_create ();
10039 tcctx.ctx = ctx;
10041 if (record_needs_remap)
10042 record_type = task_copyfn_remap_type (&tcctx, record_type);
10043 if (srecord_needs_remap)
10044 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10046 else
10047 tcctx.cb.decl_map = NULL;
10049 arg = DECL_ARGUMENTS (child_fn);
10050 TREE_TYPE (arg) = build_pointer_type (record_type);
10051 sarg = DECL_CHAIN (arg);
10052 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10054 /* First pass: initialize temporaries used in record_type and srecord_type
10055 sizes and field offsets. */
10056 if (tcctx.cb.decl_map)
10057 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10058 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10060 tree *p;
10062 decl = OMP_CLAUSE_DECL (c);
10063 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
10064 if (p == NULL)
10065 continue;
10066 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10067 sf = (tree) n->value;
10068 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
10069 src = build_simple_mem_ref_loc (loc, sarg);
10070 src = omp_build_component_ref (src, sf);
10071 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10072 append_to_statement_list (t, &list);
10075 /* Second pass: copy shared var pointers and copy construct non-VLA
10076 firstprivate vars. */
10077 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10078 switch (OMP_CLAUSE_CODE (c))
10080 case OMP_CLAUSE_SHARED:
10081 decl = OMP_CLAUSE_DECL (c);
10082 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10083 if (n == NULL)
10084 break;
10085 f = (tree) n->value;
10086 if (tcctx.cb.decl_map)
10087 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
10088 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10089 sf = (tree) n->value;
10090 if (tcctx.cb.decl_map)
10091 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
10092 src = build_simple_mem_ref_loc (loc, sarg);
10093 src = omp_build_component_ref (src, sf);
10094 dst = build_simple_mem_ref_loc (loc, arg);
10095 dst = omp_build_component_ref (dst, f);
10096 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10097 append_to_statement_list (t, &list);
10098 break;
10099 case OMP_CLAUSE_FIRSTPRIVATE:
10100 decl = OMP_CLAUSE_DECL (c);
10101 if (is_variable_sized (decl))
10102 break;
10103 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10104 if (n == NULL)
10105 break;
10106 f = (tree) n->value;
10107 if (tcctx.cb.decl_map)
10108 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
10109 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10110 if (n != NULL)
10112 sf = (tree) n->value;
10113 if (tcctx.cb.decl_map)
10114 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
10115 src = build_simple_mem_ref_loc (loc, sarg);
10116 src = omp_build_component_ref (src, sf);
10117 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
10118 src = build_simple_mem_ref_loc (loc, src);
10120 else
10121 src = decl;
10122 dst = build_simple_mem_ref_loc (loc, arg);
10123 dst = omp_build_component_ref (dst, f);
10124 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10125 append_to_statement_list (t, &list);
10126 break;
10127 case OMP_CLAUSE_PRIVATE:
10128 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10129 break;
10130 decl = OMP_CLAUSE_DECL (c);
10131 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10132 f = (tree) n->value;
10133 if (tcctx.cb.decl_map)
10134 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
10135 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10136 if (n != NULL)
10138 sf = (tree) n->value;
10139 if (tcctx.cb.decl_map)
10140 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
10141 src = build_simple_mem_ref_loc (loc, sarg);
10142 src = omp_build_component_ref (src, sf);
10143 if (use_pointer_for_field (decl, NULL))
10144 src = build_simple_mem_ref_loc (loc, src);
10146 else
10147 src = decl;
10148 dst = build_simple_mem_ref_loc (loc, arg);
10149 dst = omp_build_component_ref (dst, f);
10150 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10151 append_to_statement_list (t, &list);
10152 break;
10153 default:
10154 break;
10157 /* Last pass: handle VLA firstprivates. */
10158 if (tcctx.cb.decl_map)
10159 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10160 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10162 tree ind, ptr, df;
10164 decl = OMP_CLAUSE_DECL (c);
10165 if (!is_variable_sized (decl))
10166 continue;
10167 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10168 if (n == NULL)
10169 continue;
10170 f = (tree) n->value;
10171 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
10172 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10173 ind = DECL_VALUE_EXPR (decl);
10174 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10175 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10176 n = splay_tree_lookup (ctx->sfield_map,
10177 (splay_tree_key) TREE_OPERAND (ind, 0));
10178 sf = (tree) n->value;
10179 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
10180 src = build_simple_mem_ref_loc (loc, sarg);
10181 src = omp_build_component_ref (src, sf);
10182 src = build_simple_mem_ref_loc (loc, src);
10183 dst = build_simple_mem_ref_loc (loc, arg);
10184 dst = omp_build_component_ref (dst, f);
10185 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10186 append_to_statement_list (t, &list);
10187 n = splay_tree_lookup (ctx->field_map,
10188 (splay_tree_key) TREE_OPERAND (ind, 0));
10189 df = (tree) n->value;
10190 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
10191 ptr = build_simple_mem_ref_loc (loc, arg);
10192 ptr = omp_build_component_ref (ptr, df);
10193 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
10194 build_fold_addr_expr_loc (loc, dst));
10195 append_to_statement_list (t, &list);
10198 t = build1 (RETURN_EXPR, void_type_node, NULL);
10199 append_to_statement_list (t, &list);
10201 if (tcctx.cb.decl_map)
10202 pointer_map_destroy (tcctx.cb.decl_map);
10203 pop_gimplify_context (NULL);
10204 BIND_EXPR_BODY (bind) = list;
10205 pop_cfun ();
10208 static void
10209 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
10211 tree c, clauses;
10212 gimple g;
10213 size_t n_in = 0, n_out = 0, idx = 2, i;
10215 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
10216 OMP_CLAUSE_DEPEND);
10217 gcc_assert (clauses);
10218 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10219 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10220 switch (OMP_CLAUSE_DEPEND_KIND (c))
10222 case OMP_CLAUSE_DEPEND_IN:
10223 n_in++;
10224 break;
10225 case OMP_CLAUSE_DEPEND_OUT:
10226 case OMP_CLAUSE_DEPEND_INOUT:
10227 n_out++;
10228 break;
10229 default:
10230 gcc_unreachable ();
10232 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
10233 tree array = create_tmp_var (type, NULL);
10234 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
10235 NULL_TREE);
10236 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
10237 gimple_seq_add_stmt (iseq, g);
10238 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
10239 NULL_TREE);
10240 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
10241 gimple_seq_add_stmt (iseq, g);
10242 for (i = 0; i < 2; i++)
10244 if ((i ? n_in : n_out) == 0)
10245 continue;
10246 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10247 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
10248 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
10250 tree t = OMP_CLAUSE_DECL (c);
10251 t = fold_convert (ptr_type_node, t);
10252 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
10253 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
10254 NULL_TREE, NULL_TREE);
10255 g = gimple_build_assign (r, t);
10256 gimple_seq_add_stmt (iseq, g);
10259 tree *p = gimple_omp_task_clauses_ptr (stmt);
10260 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
10261 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
10262 OMP_CLAUSE_CHAIN (c) = *p;
10263 *p = c;
10264 tree clobber = build_constructor (type, NULL);
10265 TREE_THIS_VOLATILE (clobber) = 1;
10266 g = gimple_build_assign (array, clobber);
10267 gimple_seq_add_stmt (oseq, g);
10270 /* Lower the OpenMP parallel or task directive in the current statement
10271 in GSI_P. CTX holds context information for the directive. */
10273 static void
10274 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10276 tree clauses;
10277 tree child_fn, t;
10278 gimple stmt = gsi_stmt (*gsi_p);
10279 gimple par_bind, bind, dep_bind = NULL;
10280 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
10281 location_t loc = gimple_location (stmt);
10283 clauses = gimple_omp_taskreg_clauses (stmt);
10284 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
10285 par_body = gimple_bind_body (par_bind);
10286 child_fn = ctx->cb.dst_fn;
10287 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
10288 && !gimple_omp_parallel_combined_p (stmt))
10290 struct walk_stmt_info wi;
10291 int ws_num = 0;
10293 memset (&wi, 0, sizeof (wi));
10294 wi.info = &ws_num;
10295 wi.val_only = true;
10296 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
10297 if (ws_num == 1)
10298 gimple_omp_parallel_set_combined_p (stmt, true);
10300 gimple_seq dep_ilist = NULL;
10301 gimple_seq dep_olist = NULL;
10302 if (gimple_code (stmt) == GIMPLE_OMP_TASK
10303 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
10305 push_gimplify_context ();
10306 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
10307 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
10310 if (ctx->srecord_type)
10311 create_task_copyfn (stmt, ctx);
10313 push_gimplify_context ();
10315 par_olist = NULL;
10316 par_ilist = NULL;
10317 par_rlist = NULL;
10318 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
10319 lower_omp (&par_body, ctx);
10320 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
10321 lower_reduction_clauses (clauses, &par_rlist, ctx);
10323 /* Declare all the variables created by mapping and the variables
10324 declared in the scope of the parallel body. */
10325 record_vars_into (ctx->block_vars, child_fn);
10326 record_vars_into (gimple_bind_vars (par_bind), child_fn);
10328 if (ctx->record_type)
10330 ctx->sender_decl
10331 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
10332 : ctx->record_type, ".omp_data_o");
10333 DECL_NAMELESS (ctx->sender_decl) = 1;
10334 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10335 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
10338 olist = NULL;
10339 ilist = NULL;
10340 lower_send_clauses (clauses, &ilist, &olist, ctx);
10341 lower_send_shared_vars (&ilist, &olist, ctx);
10343 if (ctx->record_type)
10345 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
10346 TREE_THIS_VOLATILE (clobber) = 1;
10347 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10348 clobber));
10351 /* Once all the expansions are done, sequence all the different
10352 fragments inside gimple_omp_body. */
10354 new_body = NULL;
10356 if (ctx->record_type)
10358 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10359 /* fixup_child_record_type might have changed receiver_decl's type. */
10360 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10361 gimple_seq_add_stmt (&new_body,
10362 gimple_build_assign (ctx->receiver_decl, t));
10365 gimple_seq_add_seq (&new_body, par_ilist);
10366 gimple_seq_add_seq (&new_body, par_body);
10367 gimple_seq_add_seq (&new_body, par_rlist);
10368 if (ctx->cancellable)
10369 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10370 gimple_seq_add_seq (&new_body, par_olist);
10371 new_body = maybe_catch_exception (new_body);
10372 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10373 gimple_omp_set_body (stmt, new_body);
10375 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
10376 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
10377 gimple_bind_add_seq (bind, ilist);
10378 gimple_bind_add_stmt (bind, stmt);
10379 gimple_bind_add_seq (bind, olist);
10381 pop_gimplify_context (NULL);
10383 if (dep_bind)
10385 gimple_bind_add_seq (dep_bind, dep_ilist);
10386 gimple_bind_add_stmt (dep_bind, bind);
10387 gimple_bind_add_seq (dep_bind, dep_olist);
10388 pop_gimplify_context (dep_bind);
10392 /* Lower the GIMPLE_OMP_TARGET in the current statement
10393 in GSI_P. CTX holds context information for the directive. */
10395 static void
10396 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10398 tree clauses;
10399 tree child_fn, t, c;
10400 gimple stmt = gsi_stmt (*gsi_p);
10401 gimple tgt_bind = NULL, bind;
10402 gimple_seq tgt_body = NULL, olist, ilist, new_body;
10403 location_t loc = gimple_location (stmt);
10404 int kind = gimple_omp_target_kind (stmt);
10405 unsigned int map_cnt = 0;
10407 clauses = gimple_omp_target_clauses (stmt);
10408 if (kind == GF_OMP_TARGET_KIND_REGION)
10410 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
10411 tgt_body = gimple_bind_body (tgt_bind);
10413 else if (kind == GF_OMP_TARGET_KIND_DATA
10414 || kind == GF_OMP_TARGET_KIND_OACC_DATA)
10415 tgt_body = gimple_omp_body (stmt);
10416 child_fn = ctx->cb.dst_fn;
10418 push_gimplify_context ();
10420 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10421 switch (OMP_CLAUSE_CODE (c))
10423 tree var, x;
10425 default:
10426 break;
10427 case OMP_CLAUSE_MAP:
10428 #ifdef ENABLE_CHECKING
10429 /* First check what we're prepared to handle in the following. */
10430 switch (OMP_CLAUSE_MAP_KIND (c))
10432 case OMP_CLAUSE_MAP_ALLOC:
10433 case OMP_CLAUSE_MAP_TO:
10434 case OMP_CLAUSE_MAP_FROM:
10435 case OMP_CLAUSE_MAP_TOFROM:
10436 case OMP_CLAUSE_MAP_POINTER:
10437 break;
10438 case OMP_CLAUSE_MAP_FORCE_ALLOC:
10439 case OMP_CLAUSE_MAP_FORCE_TO:
10440 case OMP_CLAUSE_MAP_FORCE_FROM:
10441 case OMP_CLAUSE_MAP_FORCE_TOFROM:
10442 case OMP_CLAUSE_MAP_FORCE_PRESENT:
10443 case OMP_CLAUSE_MAP_FORCE_DEALLOC:
10444 case OMP_CLAUSE_MAP_FORCE_DEVICEPTR:
10445 gcc_assert (kind == GF_OMP_TARGET_KIND_OACC_DATA);
10446 break;
10447 default:
10448 gcc_unreachable ();
10450 #endif
10451 /* FALLTHRU */
10453 case OMP_CLAUSE_TO:
10454 case OMP_CLAUSE_FROM:
10455 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
10456 gcc_assert (kind != GF_OMP_TARGET_KIND_OACC_DATA);
10457 var = OMP_CLAUSE_DECL (c);
10458 if (!DECL_P (var))
10460 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10461 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10462 map_cnt++;
10463 continue;
10466 if (DECL_SIZE (var)
10467 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
10469 tree var2 = DECL_VALUE_EXPR (var);
10470 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
10471 var2 = TREE_OPERAND (var2, 0);
10472 gcc_assert (DECL_P (var2));
10473 var = var2;
10476 if (!maybe_lookup_field (var, ctx))
10477 continue;
10479 if (kind == GF_OMP_TARGET_KIND_REGION)
10481 x = build_receiver_ref (var, true, ctx);
10482 tree new_var = lookup_decl (var, ctx);
10483 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10484 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10485 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10486 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
10487 x = build_simple_mem_ref (x);
10488 SET_DECL_VALUE_EXPR (new_var, x);
10489 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
10491 map_cnt++;
10494 if (kind == GF_OMP_TARGET_KIND_REGION)
10496 target_nesting_level++;
10497 lower_omp (&tgt_body, ctx);
10498 target_nesting_level--;
10500 else if (kind == GF_OMP_TARGET_KIND_DATA
10501 || kind == GF_OMP_TARGET_KIND_OACC_DATA)
10502 lower_omp (&tgt_body, ctx);
10504 if (kind == GF_OMP_TARGET_KIND_REGION)
10506 /* Declare all the variables created by mapping and the variables
10507 declared in the scope of the target body. */
10508 record_vars_into (ctx->block_vars, child_fn);
10509 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
10512 olist = NULL;
10513 ilist = NULL;
10514 if (ctx->record_type)
10516 ctx->sender_decl
10517 = create_tmp_var (ctx->record_type, ".omp_data_arr");
10518 DECL_NAMELESS (ctx->sender_decl) = 1;
10519 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10520 t = make_tree_vec (3);
10521 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
10522 TREE_VEC_ELT (t, 1)
10523 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
10524 ".omp_data_sizes");
10525 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
10526 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
10527 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
10528 tree tkind_type;
10529 int talign_shift;
10530 switch (kind)
10532 case GF_OMP_TARGET_KIND_REGION:
10533 case GF_OMP_TARGET_KIND_DATA:
10534 case GF_OMP_TARGET_KIND_UPDATE:
10535 tkind_type = unsigned_char_type_node;
10536 talign_shift = 3;
10537 break;
10538 case GF_OMP_TARGET_KIND_OACC_DATA:
10539 tkind_type = short_unsigned_type_node;
10540 talign_shift = 8;
10541 break;
10542 default:
10543 gcc_unreachable ();
10545 TREE_VEC_ELT (t, 2)
10546 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
10547 ".omp_data_kinds");
10548 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
10549 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
10550 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
10551 gimple_omp_target_set_data_arg (stmt, t);
10553 vec<constructor_elt, va_gc> *vsize;
10554 vec<constructor_elt, va_gc> *vkind;
10555 vec_alloc (vsize, map_cnt);
10556 vec_alloc (vkind, map_cnt);
10557 unsigned int map_idx = 0;
10559 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10560 switch (OMP_CLAUSE_CODE (c))
10562 tree ovar, nc;
10564 default:
10565 break;
10566 case OMP_CLAUSE_MAP:
10567 case OMP_CLAUSE_TO:
10568 case OMP_CLAUSE_FROM:
10569 nc = c;
10570 ovar = OMP_CLAUSE_DECL (c);
10571 if (!DECL_P (ovar))
10573 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10574 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10576 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
10577 == get_base_address (ovar));
10578 nc = OMP_CLAUSE_CHAIN (c);
10579 ovar = OMP_CLAUSE_DECL (nc);
10581 else
10583 tree x = build_sender_ref (ovar, ctx);
10584 tree v
10585 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
10586 gimplify_assign (x, v, &ilist);
10587 nc = NULL_TREE;
10590 else
10592 if (DECL_SIZE (ovar)
10593 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
10595 tree ovar2 = DECL_VALUE_EXPR (ovar);
10596 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
10597 ovar2 = TREE_OPERAND (ovar2, 0);
10598 gcc_assert (DECL_P (ovar2));
10599 ovar = ovar2;
10601 if (!maybe_lookup_field (ovar, ctx))
10602 continue;
10605 if (nc)
10607 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
10608 tree x = build_sender_ref (ovar, ctx);
10609 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10610 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10611 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10612 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
10614 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10615 tree avar
10616 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
10617 mark_addressable (avar);
10618 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
10619 avar = build_fold_addr_expr (avar);
10620 gimplify_assign (x, avar, &ilist);
10622 else if (is_gimple_reg (var))
10624 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10625 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
10626 mark_addressable (avar);
10627 enum omp_clause_map_kind map_kind
10628 = OMP_CLAUSE_MAP_KIND (c);
10629 if ((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
10630 && (map_kind & OMP_CLAUSE_MAP_TO))
10631 || map_kind == OMP_CLAUSE_MAP_POINTER)
10632 gimplify_assign (avar, var, &ilist);
10633 avar = build_fold_addr_expr (avar);
10634 gimplify_assign (x, avar, &ilist);
10635 if ((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
10636 && (map_kind & OMP_CLAUSE_MAP_FROM))
10637 && !TYPE_READONLY (TREE_TYPE (var)))
10639 x = build_sender_ref (ovar, ctx);
10640 x = build_simple_mem_ref (x);
10641 gimplify_assign (var, x, &olist);
10644 else
10646 var = build_fold_addr_expr (var);
10647 gimplify_assign (x, var, &ilist);
10650 tree s = OMP_CLAUSE_SIZE (c);
10651 if (s == NULL_TREE)
10652 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
10653 s = fold_convert (size_type_node, s);
10654 tree purpose = size_int (map_idx++);
10655 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
10656 if (TREE_CODE (s) != INTEGER_CST)
10657 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
10659 unsigned HOST_WIDE_INT tkind;
10660 switch (OMP_CLAUSE_CODE (c))
10662 case OMP_CLAUSE_MAP:
10663 tkind = OMP_CLAUSE_MAP_KIND (c);
10664 break;
10665 case OMP_CLAUSE_TO:
10666 tkind = OMP_CLAUSE_MAP_TO;
10667 break;
10668 case OMP_CLAUSE_FROM:
10669 tkind = OMP_CLAUSE_MAP_FROM;
10670 break;
10671 default:
10672 gcc_unreachable ();
10674 gcc_assert (tkind < (HOST_WIDE_INT_C (1U) << talign_shift));
10675 unsigned HOST_WIDE_INT talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
10676 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
10677 talign = DECL_ALIGN_UNIT (ovar);
10678 talign = ceil_log2 (talign);
10679 tkind |= talign << talign_shift;
10680 gcc_assert (tkind <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
10681 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
10682 build_int_cstu (tkind_type, tkind));
10683 if (nc && nc != c)
10684 c = nc;
10687 gcc_assert (map_idx == map_cnt);
10689 DECL_INITIAL (TREE_VEC_ELT (t, 1))
10690 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
10691 DECL_INITIAL (TREE_VEC_ELT (t, 2))
10692 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
10693 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
10695 gimple_seq initlist = NULL;
10696 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
10697 TREE_VEC_ELT (t, 1)),
10698 &initlist, true, NULL_TREE);
10699 gimple_seq_add_seq (&ilist, initlist);
10701 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
10702 NULL);
10703 TREE_THIS_VOLATILE (clobber) = 1;
10704 gimple_seq_add_stmt (&olist,
10705 gimple_build_assign (TREE_VEC_ELT (t, 1),
10706 clobber));
10709 tree clobber = build_constructor (ctx->record_type, NULL);
10710 TREE_THIS_VOLATILE (clobber) = 1;
10711 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10712 clobber));
10715 /* Once all the expansions are done, sequence all the different
10716 fragments inside gimple_omp_body. */
10718 new_body = NULL;
10720 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
10722 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10723 /* fixup_child_record_type might have changed receiver_decl's type. */
10724 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10725 gimple_seq_add_stmt (&new_body,
10726 gimple_build_assign (ctx->receiver_decl, t));
10729 if (kind == GF_OMP_TARGET_KIND_REGION)
10731 gimple_seq_add_seq (&new_body, tgt_body);
10732 new_body = maybe_catch_exception (new_body);
10734 else if (kind == GF_OMP_TARGET_KIND_DATA
10735 || kind == GF_OMP_TARGET_KIND_OACC_DATA)
10736 new_body = tgt_body;
10737 if (kind != GF_OMP_TARGET_KIND_UPDATE)
10739 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10740 gimple_omp_set_body (stmt, new_body);
10743 bind = gimple_build_bind (NULL, NULL,
10744 tgt_bind ? gimple_bind_block (tgt_bind)
10745 : NULL_TREE);
10746 gsi_replace (gsi_p, bind, true);
10747 gimple_bind_add_seq (bind, ilist);
10748 gimple_bind_add_stmt (bind, stmt);
10749 gimple_bind_add_seq (bind, olist);
10751 pop_gimplify_context (NULL);
10754 /* Expand code for an OpenMP teams directive. */
10756 static void
10757 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10759 gimple teams_stmt = gsi_stmt (*gsi_p);
10760 push_gimplify_context ();
10762 tree block = make_node (BLOCK);
10763 gimple bind = gimple_build_bind (NULL, NULL, block);
10764 gsi_replace (gsi_p, bind, true);
10765 gimple_seq bind_body = NULL;
10766 gimple_seq dlist = NULL;
10767 gimple_seq olist = NULL;
10769 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10770 OMP_CLAUSE_NUM_TEAMS);
10771 if (num_teams == NULL_TREE)
10772 num_teams = build_int_cst (unsigned_type_node, 0);
10773 else
10775 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
10776 num_teams = fold_convert (unsigned_type_node, num_teams);
10777 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
10779 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10780 OMP_CLAUSE_THREAD_LIMIT);
10781 if (thread_limit == NULL_TREE)
10782 thread_limit = build_int_cst (unsigned_type_node, 0);
10783 else
10785 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10786 thread_limit = fold_convert (unsigned_type_node, thread_limit);
10787 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
10788 fb_rvalue);
10791 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
10792 &bind_body, &dlist, ctx, NULL);
10793 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
10794 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
10795 gimple_seq_add_stmt (&bind_body, teams_stmt);
10797 location_t loc = gimple_location (teams_stmt);
10798 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
10799 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10800 gimple_set_location (call, loc);
10801 gimple_seq_add_stmt (&bind_body, call);
10803 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10804 gimple_omp_set_body (teams_stmt, NULL);
10805 gimple_seq_add_seq (&bind_body, olist);
10806 gimple_seq_add_seq (&bind_body, dlist);
10807 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10808 gimple_bind_set_body (bind, bind_body);
10810 pop_gimplify_context (bind);
10812 gimple_bind_append_vars (bind, ctx->block_vars);
10813 BLOCK_VARS (block) = ctx->block_vars;
10814 if (BLOCK_VARS (block))
10815 TREE_USED (block) = 1;
10819 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10820 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10821 of OpenMP context, but with task_shared_vars set. */
10823 static tree
10824 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10825 void *data)
10827 tree t = *tp;
10829 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10830 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
10831 return t;
10833 if (task_shared_vars
10834 && DECL_P (t)
10835 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10836 return t;
10838 /* If a global variable has been privatized, TREE_CONSTANT on
10839 ADDR_EXPR might be wrong. */
10840 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10841 recompute_tree_invariant_for_addr_expr (t);
10843 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10844 return NULL_TREE;
10847 static void
10848 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10850 gimple stmt = gsi_stmt (*gsi_p);
10851 struct walk_stmt_info wi;
10853 if (gimple_has_location (stmt))
10854 input_location = gimple_location (stmt);
10856 if (task_shared_vars)
10857 memset (&wi, '\0', sizeof (wi));
10859 /* If we have issued syntax errors, avoid doing any heavy lifting.
10860 Just replace the OpenMP directives with a NOP to avoid
10861 confusing RTL expansion. */
10862 if (seen_error () && is_gimple_omp (stmt))
10864 gsi_replace (gsi_p, gimple_build_nop (), true);
10865 return;
10868 switch (gimple_code (stmt))
10870 case GIMPLE_COND:
10871 if ((ctx || task_shared_vars)
10872 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
10873 ctx ? NULL : &wi, NULL)
10874 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
10875 ctx ? NULL : &wi, NULL)))
10876 gimple_regimplify_operands (stmt, gsi_p);
10877 break;
10878 case GIMPLE_CATCH:
10879 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
10880 break;
10881 case GIMPLE_EH_FILTER:
10882 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10883 break;
10884 case GIMPLE_TRY:
10885 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10886 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10887 break;
10888 case GIMPLE_TRANSACTION:
10889 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
10890 break;
10891 case GIMPLE_BIND:
10892 lower_omp (gimple_bind_body_ptr (stmt), ctx);
10893 break;
10894 case GIMPLE_OACC_KERNELS:
10895 case GIMPLE_OACC_PARALLEL:
10896 ctx = maybe_lookup_ctx (stmt);
10897 gcc_assert (ctx);
10898 gcc_assert (!ctx->cancellable);
10899 lower_oacc_offload (gsi_p, ctx);
10900 break;
10901 case GIMPLE_OMP_PARALLEL:
10902 case GIMPLE_OMP_TASK:
10903 ctx = maybe_lookup_ctx (stmt);
10904 gcc_assert (ctx);
10905 if (ctx->cancellable)
10906 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10907 lower_omp_taskreg (gsi_p, ctx);
10908 break;
10909 case GIMPLE_OMP_FOR:
10910 ctx = maybe_lookup_ctx (stmt);
10911 gcc_assert (ctx);
10912 if (ctx->cancellable)
10913 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10914 lower_omp_for (gsi_p, ctx);
10915 break;
10916 case GIMPLE_OMP_SECTIONS:
10917 ctx = maybe_lookup_ctx (stmt);
10918 gcc_assert (ctx);
10919 if (ctx->cancellable)
10920 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10921 lower_omp_sections (gsi_p, ctx);
10922 break;
10923 case GIMPLE_OMP_SINGLE:
10924 ctx = maybe_lookup_ctx (stmt);
10925 gcc_assert (ctx);
10926 lower_omp_single (gsi_p, ctx);
10927 break;
10928 case GIMPLE_OMP_MASTER:
10929 ctx = maybe_lookup_ctx (stmt);
10930 gcc_assert (ctx);
10931 lower_omp_master (gsi_p, ctx);
10932 break;
10933 case GIMPLE_OMP_TASKGROUP:
10934 ctx = maybe_lookup_ctx (stmt);
10935 gcc_assert (ctx);
10936 lower_omp_taskgroup (gsi_p, ctx);
10937 break;
10938 case GIMPLE_OMP_ORDERED:
10939 ctx = maybe_lookup_ctx (stmt);
10940 gcc_assert (ctx);
10941 lower_omp_ordered (gsi_p, ctx);
10942 break;
10943 case GIMPLE_OMP_CRITICAL:
10944 ctx = maybe_lookup_ctx (stmt);
10945 gcc_assert (ctx);
10946 lower_omp_critical (gsi_p, ctx);
10947 break;
10948 case GIMPLE_OMP_ATOMIC_LOAD:
10949 if ((ctx || task_shared_vars)
10950 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
10951 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10952 gimple_regimplify_operands (stmt, gsi_p);
10953 break;
10954 case GIMPLE_OMP_TARGET:
10955 ctx = maybe_lookup_ctx (stmt);
10956 gcc_assert (ctx);
10957 if (gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_DATA)
10958 gcc_assert (!ctx->cancellable);
10959 lower_omp_target (gsi_p, ctx);
10960 break;
10961 case GIMPLE_OMP_TEAMS:
10962 ctx = maybe_lookup_ctx (stmt);
10963 gcc_assert (ctx);
10964 lower_omp_teams (gsi_p, ctx);
10965 break;
10966 case GIMPLE_CALL:
10967 tree fndecl;
10968 fndecl = gimple_call_fndecl (stmt);
10969 if (fndecl
10970 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10971 switch (DECL_FUNCTION_CODE (fndecl))
10973 case BUILT_IN_GOMP_BARRIER:
10974 if (ctx == NULL)
10975 break;
10976 /* FALLTHRU */
10977 case BUILT_IN_GOMP_CANCEL:
10978 case BUILT_IN_GOMP_CANCELLATION_POINT:
10979 omp_context *cctx;
10980 cctx = ctx;
10981 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10982 cctx = cctx->outer;
10983 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10984 if (!cctx->cancellable)
10986 if (DECL_FUNCTION_CODE (fndecl)
10987 == BUILT_IN_GOMP_CANCELLATION_POINT)
10989 stmt = gimple_build_nop ();
10990 gsi_replace (gsi_p, stmt, false);
10992 break;
10994 tree lhs;
10995 lhs = create_tmp_var (boolean_type_node, NULL);
10996 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10998 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10999 gimple_call_set_fndecl (stmt, fndecl);
11000 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
11002 gimple_call_set_lhs (stmt, lhs);
11003 tree fallthru_label;
11004 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11005 gimple g;
11006 g = gimple_build_label (fallthru_label);
11007 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11008 g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
11009 cctx->cancel_label, fallthru_label);
11010 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11011 break;
11012 default:
11013 break;
11015 /* FALLTHRU */
11016 default:
11017 if ((ctx || task_shared_vars)
11018 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11019 ctx ? NULL : &wi))
11020 gimple_regimplify_operands (stmt, gsi_p);
11021 break;
11025 static void
11026 lower_omp (gimple_seq *body, omp_context *ctx)
11028 location_t saved_location = input_location;
11029 gimple_stmt_iterator gsi;
11030 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11031 lower_omp_1 (&gsi, ctx);
11032 /* During gimplification, we haven't folded statments inside offloading
11033 regions (gimplify.c:maybe_fold_stmt); do that now. */
11034 if (target_nesting_level)
11035 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11036 fold_stmt (&gsi);
11037 input_location = saved_location;
11040 /* Main entry point. */
11042 static unsigned int
11043 execute_lower_omp (void)
11045 gimple_seq body;
11047 /* This pass always runs, to provide PROP_gimple_lomp.
11048 But often, there is nothing to do. */
11049 if (flag_openacc == 0 && flag_openmp == 0 && flag_openmp_simd == 0
11050 && flag_cilkplus == 0)
11051 return 0;
11053 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11054 delete_omp_context);
11056 body = gimple_body (current_function_decl);
11057 scan_omp (&body, NULL);
11058 gcc_assert (taskreg_nesting_level == 0);
11060 if (all_contexts->root)
11062 if (task_shared_vars)
11063 push_gimplify_context ();
11064 lower_omp (&body, NULL);
11065 if (task_shared_vars)
11066 pop_gimplify_context (NULL);
11069 if (all_contexts)
11071 splay_tree_delete (all_contexts);
11072 all_contexts = NULL;
11074 BITMAP_FREE (task_shared_vars);
11075 return 0;
11078 namespace {
11080 const pass_data pass_data_lower_omp =
11082 GIMPLE_PASS, /* type */
11083 "omplower", /* name */
11084 OPTGROUP_NONE, /* optinfo_flags */
11085 false, /* has_gate */
11086 true, /* has_execute */
11087 TV_NONE, /* tv_id */
11088 PROP_gimple_any, /* properties_required */
11089 PROP_gimple_lomp, /* properties_provided */
11090 0, /* properties_destroyed */
11091 0, /* todo_flags_start */
11092 0, /* todo_flags_finish */
11095 class pass_lower_omp : public gimple_opt_pass
11097 public:
11098 pass_lower_omp (gcc::context *ctxt)
11099 : gimple_opt_pass (pass_data_lower_omp, ctxt)
11102 /* opt_pass methods: */
11103 unsigned int execute () { return execute_lower_omp (); }
11105 }; // class pass_lower_omp
11107 } // anon namespace
11109 gimple_opt_pass *
11110 make_pass_lower_omp (gcc::context *ctxt)
11112 return new pass_lower_omp (ctxt);
11115 /* The following is a utility to diagnose structured block violations.
11116 It is not part of the "omplower" pass, as that's invoked too late. It
11117 should be invoked by the respective front ends after gimplification. */
11119 static splay_tree all_labels;
11121 /* Check for mismatched contexts and generate an error if needed. Return
11122 true if an error is detected. */
11124 static bool
11125 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
11126 gimple branch_ctx, gimple label_ctx)
11128 gcc_assert (!branch_ctx || is_gimple_omp (branch_ctx));
11129 gcc_assert (!label_ctx || is_gimple_omp (label_ctx));
11131 if (label_ctx == branch_ctx)
11132 return false;
11134 const char* kind = NULL;
11136 if (flag_cilkplus)
11138 if ((branch_ctx
11139 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
11140 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
11141 || (label_ctx
11142 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
11143 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
11144 kind = "Cilk Plus";
11146 if (flag_openacc)
11148 if ((branch_ctx && is_gimple_omp_oacc_specifically (branch_ctx))
11149 || (label_ctx && is_gimple_omp_oacc_specifically (label_ctx)))
11151 gcc_assert (kind == NULL);
11152 kind = "OpenACC";
11155 if (kind == NULL)
11157 gcc_assert (flag_openmp);
11158 kind = "OpenMP";
11162 Previously we kept track of the label's entire context in diagnose_sb_[12]
11163 so we could traverse it and issue a correct "exit" or "enter" error
11164 message upon a structured block violation.
11166 We built the context by building a list with tree_cons'ing, but there is
11167 no easy counterpart in gimple tuples. It seems like far too much work
11168 for issuing exit/enter error messages. If someone really misses the
11169 distinct error message... patches welcome.
11172 #if 0
11173 /* Try to avoid confusing the user by producing and error message
11174 with correct "exit" or "enter" verbiage. We prefer "exit"
11175 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
11176 if (branch_ctx == NULL)
11177 exit_p = false;
11178 else
11180 while (label_ctx)
11182 if (TREE_VALUE (label_ctx) == branch_ctx)
11184 exit_p = false;
11185 break;
11187 label_ctx = TREE_CHAIN (label_ctx);
11191 if (exit_p)
11192 error ("invalid exit from %s structured block", kind);
11193 else
11194 error ("invalid entry to %s structured block", kind);
11195 #endif
11197 /* If it's obvious we have an invalid entry, be specific about the error. */
11198 if (branch_ctx == NULL)
11199 error ("invalid entry to %s structured block", kind);
11200 else
11202 /* Otherwise, be vague and lazy, but efficient. */
11203 error ("invalid branch to/from %s structured block", kind);
11206 gsi_replace (gsi_p, gimple_build_nop (), false);
11207 return true;
11210 /* Pass 1: Create a minimal tree of structured blocks, and record
11211 where each label is found. */
11213 static tree
11214 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
11215 struct walk_stmt_info *wi)
11217 gimple context = (gimple) wi->info;
11218 gimple inner_context;
11219 gimple stmt = gsi_stmt (*gsi_p);
11221 *handled_ops_p = true;
11223 switch (gimple_code (stmt))
11225 WALK_SUBSTMTS;
11227 case GIMPLE_OACC_KERNELS:
11228 case GIMPLE_OACC_PARALLEL:
11229 case GIMPLE_OMP_PARALLEL:
11230 case GIMPLE_OMP_TASK:
11231 case GIMPLE_OMP_SECTIONS:
11232 case GIMPLE_OMP_SINGLE:
11233 case GIMPLE_OMP_SECTION:
11234 case GIMPLE_OMP_MASTER:
11235 case GIMPLE_OMP_ORDERED:
11236 case GIMPLE_OMP_CRITICAL:
11237 case GIMPLE_OMP_TARGET:
11238 case GIMPLE_OMP_TEAMS:
11239 case GIMPLE_OMP_TASKGROUP:
11240 /* The minimal context here is just the current construct. */
11241 inner_context = stmt;
11242 wi->info = inner_context;
11243 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
11244 wi->info = context;
11245 break;
11247 case GIMPLE_OMP_FOR:
11248 inner_context = stmt;
11249 wi->info = inner_context;
11250 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
11251 walk them. */
11252 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
11253 diagnose_sb_1, NULL, wi);
11254 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
11255 wi->info = context;
11256 break;
11258 case GIMPLE_LABEL:
11259 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
11260 (splay_tree_value) context);
11261 break;
11263 default:
11264 break;
11267 return NULL_TREE;
11270 /* Pass 2: Check each branch and see if its context differs from that of
11271 the destination label's context. */
11273 static tree
11274 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
11275 struct walk_stmt_info *wi)
11277 gimple context = (gimple) wi->info;
11278 splay_tree_node n;
11279 gimple stmt = gsi_stmt (*gsi_p);
11281 *handled_ops_p = true;
11283 switch (gimple_code (stmt))
11285 WALK_SUBSTMTS;
11287 case GIMPLE_OACC_KERNELS:
11288 case GIMPLE_OACC_PARALLEL:
11289 case GIMPLE_OMP_PARALLEL:
11290 case GIMPLE_OMP_TASK:
11291 case GIMPLE_OMP_SECTIONS:
11292 case GIMPLE_OMP_SINGLE:
11293 case GIMPLE_OMP_SECTION:
11294 case GIMPLE_OMP_MASTER:
11295 case GIMPLE_OMP_ORDERED:
11296 case GIMPLE_OMP_CRITICAL:
11297 case GIMPLE_OMP_TARGET:
11298 case GIMPLE_OMP_TEAMS:
11299 case GIMPLE_OMP_TASKGROUP:
11300 wi->info = stmt;
11301 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
11302 wi->info = context;
11303 break;
11305 case GIMPLE_OMP_FOR:
11306 wi->info = stmt;
11307 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
11308 walk them. */
11309 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
11310 diagnose_sb_2, NULL, wi);
11311 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
11312 wi->info = context;
11313 break;
11315 case GIMPLE_COND:
11317 tree lab = gimple_cond_true_label (stmt);
11318 if (lab)
11320 n = splay_tree_lookup (all_labels,
11321 (splay_tree_key) lab);
11322 diagnose_sb_0 (gsi_p, context,
11323 n ? (gimple) n->value : NULL);
11325 lab = gimple_cond_false_label (stmt);
11326 if (lab)
11328 n = splay_tree_lookup (all_labels,
11329 (splay_tree_key) lab);
11330 diagnose_sb_0 (gsi_p, context,
11331 n ? (gimple) n->value : NULL);
11334 break;
11336 case GIMPLE_GOTO:
11338 tree lab = gimple_goto_dest (stmt);
11339 if (TREE_CODE (lab) != LABEL_DECL)
11340 break;
11342 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
11343 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
11345 break;
11347 case GIMPLE_SWITCH:
11349 unsigned int i;
11350 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
11352 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
11353 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
11354 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
11355 break;
11358 break;
11360 case GIMPLE_RETURN:
11361 diagnose_sb_0 (gsi_p, context, NULL);
11362 break;
11364 default:
11365 break;
11368 return NULL_TREE;
11371 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
11372 GIMPLE codes. */
11373 bool
11374 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
11375 int *region_idx)
11377 gimple last = last_stmt (bb);
11378 enum gimple_code code = gimple_code (last);
11379 struct omp_region *cur_region = *region;
11380 bool fallthru = false;
11382 switch (code)
11384 case GIMPLE_OACC_KERNELS:
11385 case GIMPLE_OACC_PARALLEL:
11386 case GIMPLE_OMP_PARALLEL:
11387 case GIMPLE_OMP_TASK:
11388 case GIMPLE_OMP_FOR:
11389 case GIMPLE_OMP_SINGLE:
11390 case GIMPLE_OMP_TEAMS:
11391 case GIMPLE_OMP_MASTER:
11392 case GIMPLE_OMP_TASKGROUP:
11393 case GIMPLE_OMP_ORDERED:
11394 case GIMPLE_OMP_CRITICAL:
11395 case GIMPLE_OMP_SECTION:
11396 cur_region = new_omp_region (bb, code, cur_region);
11397 fallthru = true;
11398 break;
11400 case GIMPLE_OMP_TARGET:
11401 cur_region = new_omp_region (bb, code, cur_region);
11402 fallthru = true;
11403 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
11404 cur_region = cur_region->outer;
11405 break;
11407 case GIMPLE_OMP_SECTIONS:
11408 cur_region = new_omp_region (bb, code, cur_region);
11409 fallthru = true;
11410 break;
11412 case GIMPLE_OMP_SECTIONS_SWITCH:
11413 fallthru = false;
11414 break;
11416 case GIMPLE_OMP_ATOMIC_LOAD:
11417 case GIMPLE_OMP_ATOMIC_STORE:
11418 fallthru = true;
11419 break;
11421 case GIMPLE_OMP_RETURN:
11422 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
11423 somewhere other than the next block. This will be
11424 created later. */
11425 cur_region->exit = bb;
11426 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
11427 cur_region = cur_region->outer;
11428 break;
11430 case GIMPLE_OMP_CONTINUE:
11431 cur_region->cont = bb;
11432 switch (cur_region->type)
11434 case GIMPLE_OMP_FOR:
11435 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11436 succs edges as abnormal to prevent splitting
11437 them. */
11438 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
11439 /* Make the loopback edge. */
11440 make_edge (bb, single_succ (cur_region->entry),
11441 EDGE_ABNORMAL);
11443 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11444 corresponds to the case that the body of the loop
11445 is not executed at all. */
11446 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
11447 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
11448 fallthru = false;
11449 break;
11451 case GIMPLE_OMP_SECTIONS:
11452 /* Wire up the edges into and out of the nested sections. */
11454 basic_block switch_bb = single_succ (cur_region->entry);
11456 struct omp_region *i;
11457 for (i = cur_region->inner; i ; i = i->next)
11459 gcc_assert (i->type == GIMPLE_OMP_SECTION);
11460 make_edge (switch_bb, i->entry, 0);
11461 make_edge (i->exit, bb, EDGE_FALLTHRU);
11464 /* Make the loopback edge to the block with
11465 GIMPLE_OMP_SECTIONS_SWITCH. */
11466 make_edge (bb, switch_bb, 0);
11468 /* Make the edge from the switch to exit. */
11469 make_edge (switch_bb, bb->next_bb, 0);
11470 fallthru = false;
11472 break;
11474 default:
11475 gcc_unreachable ();
11477 break;
11479 default:
11480 gcc_unreachable ();
11483 if (*region != cur_region)
11485 *region = cur_region;
11486 if (cur_region)
11487 *region_idx = cur_region->entry->index;
11488 else
11489 *region_idx = 0;
11492 return fallthru;
11495 static unsigned int
11496 diagnose_omp_structured_block_errors (void)
11498 struct walk_stmt_info wi;
11499 gimple_seq body = gimple_body (current_function_decl);
11501 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
11503 memset (&wi, 0, sizeof (wi));
11504 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
11506 memset (&wi, 0, sizeof (wi));
11507 wi.want_locations = true;
11508 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
11510 gimple_set_body (current_function_decl, body);
11512 splay_tree_delete (all_labels);
11513 all_labels = NULL;
11515 return 0;
11518 static bool
11519 gate_diagnose_omp_blocks (void)
11521 return flag_openacc || flag_openmp || flag_cilkplus;
11524 namespace {
11526 const pass_data pass_data_diagnose_omp_blocks =
11528 GIMPLE_PASS, /* type */
11529 "*diagnose_omp_blocks", /* name */
11530 OPTGROUP_NONE, /* optinfo_flags */
11531 true, /* has_gate */
11532 true, /* has_execute */
11533 TV_NONE, /* tv_id */
11534 PROP_gimple_any, /* properties_required */
11535 0, /* properties_provided */
11536 0, /* properties_destroyed */
11537 0, /* todo_flags_start */
11538 0, /* todo_flags_finish */
11541 class pass_diagnose_omp_blocks : public gimple_opt_pass
11543 public:
11544 pass_diagnose_omp_blocks (gcc::context *ctxt)
11545 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
11548 /* opt_pass methods: */
11549 bool gate () { return gate_diagnose_omp_blocks (); }
11550 unsigned int execute () {
11551 return diagnose_omp_structured_block_errors ();
11554 }; // class pass_diagnose_omp_blocks
11556 } // anon namespace
11558 gimple_opt_pass *
11559 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
11561 return new pass_diagnose_omp_blocks (ctxt);
11564 /* SIMD clone supporting code. */
11566 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11567 of arguments to reserve space for. */
11569 static struct cgraph_simd_clone *
11570 simd_clone_struct_alloc (int nargs)
11572 struct cgraph_simd_clone *clone_info;
11573 size_t len = (sizeof (struct cgraph_simd_clone)
11574 + nargs * sizeof (struct cgraph_simd_clone_arg));
11575 clone_info = (struct cgraph_simd_clone *)
11576 ggc_internal_cleared_alloc (len);
11577 return clone_info;
11580 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11582 static inline void
11583 simd_clone_struct_copy (struct cgraph_simd_clone *to,
11584 struct cgraph_simd_clone *from)
11586 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
11587 + ((from->nargs - from->inbranch)
11588 * sizeof (struct cgraph_simd_clone_arg))));
11591 /* Return vector of parameter types of function FNDECL. This uses
11592 TYPE_ARG_TYPES if available, otherwise falls back to types of
11593 DECL_ARGUMENTS types. */
11595 vec<tree>
11596 simd_clone_vector_of_formal_parm_types (tree fndecl)
11598 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
11599 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
11600 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
11601 unsigned int i;
11602 tree arg;
11603 FOR_EACH_VEC_ELT (args, i, arg)
11604 args[i] = TREE_TYPE (args[i]);
11605 return args;
11608 /* Given a simd function in NODE, extract the simd specific
11609 information from the OMP clauses passed in CLAUSES, and return
11610 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11611 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11612 otherwise set to FALSE. */
11614 static struct cgraph_simd_clone *
11615 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
11616 bool *inbranch_specified)
11618 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
11619 tree t;
11620 int n;
11621 *inbranch_specified = false;
11623 n = args.length ();
11624 if (n > 0 && args.last () == void_type_node)
11625 n--;
11627 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11628 be cloned have a distinctive artificial label in addition to "omp
11629 declare simd". */
11630 bool cilk_clone
11631 = (flag_cilkplus
11632 && lookup_attribute ("cilk simd function",
11633 DECL_ATTRIBUTES (node->decl)));
11635 /* Allocate one more than needed just in case this is an in-branch
11636 clone which will require a mask argument. */
11637 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
11638 clone_info->nargs = n;
11639 clone_info->cilk_elemental = cilk_clone;
11641 if (!clauses)
11643 args.release ();
11644 return clone_info;
11646 clauses = TREE_VALUE (clauses);
11647 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
11648 return clone_info;
11650 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
11652 switch (OMP_CLAUSE_CODE (t))
11654 case OMP_CLAUSE_INBRANCH:
11655 clone_info->inbranch = 1;
11656 *inbranch_specified = true;
11657 break;
11658 case OMP_CLAUSE_NOTINBRANCH:
11659 clone_info->inbranch = 0;
11660 *inbranch_specified = true;
11661 break;
11662 case OMP_CLAUSE_SIMDLEN:
11663 clone_info->simdlen
11664 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
11665 break;
11666 case OMP_CLAUSE_LINEAR:
11668 tree decl = OMP_CLAUSE_DECL (t);
11669 tree step = OMP_CLAUSE_LINEAR_STEP (t);
11670 int argno = TREE_INT_CST_LOW (decl);
11671 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
11673 clone_info->args[argno].arg_type
11674 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
11675 clone_info->args[argno].linear_step = tree_to_shwi (step);
11676 gcc_assert (clone_info->args[argno].linear_step >= 0
11677 && clone_info->args[argno].linear_step < n);
11679 else
11681 if (POINTER_TYPE_P (args[argno]))
11682 step = fold_convert (ssizetype, step);
11683 if (!tree_fits_shwi_p (step))
11685 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11686 "ignoring large linear step");
11687 args.release ();
11688 return NULL;
11690 else if (integer_zerop (step))
11692 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11693 "ignoring zero linear step");
11694 args.release ();
11695 return NULL;
11697 else
11699 clone_info->args[argno].arg_type
11700 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
11701 clone_info->args[argno].linear_step = tree_to_shwi (step);
11704 break;
11706 case OMP_CLAUSE_UNIFORM:
11708 tree decl = OMP_CLAUSE_DECL (t);
11709 int argno = tree_to_uhwi (decl);
11710 clone_info->args[argno].arg_type
11711 = SIMD_CLONE_ARG_TYPE_UNIFORM;
11712 break;
11714 case OMP_CLAUSE_ALIGNED:
11716 tree decl = OMP_CLAUSE_DECL (t);
11717 int argno = tree_to_uhwi (decl);
11718 clone_info->args[argno].alignment
11719 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
11720 break;
11722 default:
11723 break;
11726 args.release ();
11727 return clone_info;
11730 /* Given a SIMD clone in NODE, calculate the characteristic data
11731 type and return the coresponding type. The characteristic data
11732 type is computed as described in the Intel Vector ABI. */
11734 static tree
11735 simd_clone_compute_base_data_type (struct cgraph_node *node,
11736 struct cgraph_simd_clone *clone_info)
11738 tree type = integer_type_node;
11739 tree fndecl = node->decl;
11741 /* a) For non-void function, the characteristic data type is the
11742 return type. */
11743 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
11744 type = TREE_TYPE (TREE_TYPE (fndecl));
11746 /* b) If the function has any non-uniform, non-linear parameters,
11747 then the characteristic data type is the type of the first
11748 such parameter. */
11749 else
11751 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
11752 for (unsigned int i = 0; i < clone_info->nargs; ++i)
11753 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
11755 type = map[i];
11756 break;
11758 map.release ();
11761 /* c) If the characteristic data type determined by a) or b) above
11762 is struct, union, or class type which is pass-by-value (except
11763 for the type that maps to the built-in complex data type), the
11764 characteristic data type is int. */
11765 if (RECORD_OR_UNION_TYPE_P (type)
11766 && !aggregate_value_p (type, NULL)
11767 && TREE_CODE (type) != COMPLEX_TYPE)
11768 return integer_type_node;
11770 /* d) If none of the above three classes is applicable, the
11771 characteristic data type is int. */
11773 return type;
11775 /* e) For Intel Xeon Phi native and offload compilation, if the
11776 resulting characteristic data type is 8-bit or 16-bit integer
11777 data type, the characteristic data type is int. */
11778 /* Well, we don't handle Xeon Phi yet. */
11781 static tree
11782 simd_clone_mangle (struct cgraph_node *node,
11783 struct cgraph_simd_clone *clone_info)
11785 char vecsize_mangle = clone_info->vecsize_mangle;
11786 char mask = clone_info->inbranch ? 'M' : 'N';
11787 unsigned int simdlen = clone_info->simdlen;
11788 unsigned int n;
11789 pretty_printer pp;
11791 gcc_assert (vecsize_mangle && simdlen);
11793 pp_string (&pp, "_ZGV");
11794 pp_character (&pp, vecsize_mangle);
11795 pp_character (&pp, mask);
11796 pp_decimal_int (&pp, simdlen);
11798 for (n = 0; n < clone_info->nargs; ++n)
11800 struct cgraph_simd_clone_arg arg = clone_info->args[n];
11802 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
11803 pp_character (&pp, 'u');
11804 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11806 gcc_assert (arg.linear_step != 0);
11807 pp_character (&pp, 'l');
11808 if (arg.linear_step > 1)
11809 pp_unsigned_wide_integer (&pp, arg.linear_step);
11810 else if (arg.linear_step < 0)
11812 pp_character (&pp, 'n');
11813 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
11814 arg.linear_step));
11817 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11819 pp_character (&pp, 's');
11820 pp_unsigned_wide_integer (&pp, arg.linear_step);
11822 else
11823 pp_character (&pp, 'v');
11824 if (arg.alignment)
11826 pp_character (&pp, 'a');
11827 pp_decimal_int (&pp, arg.alignment);
11831 pp_underscore (&pp);
11832 pp_string (&pp,
11833 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11834 const char *str = pp_formatted_text (&pp);
11836 /* If there already is a SIMD clone with the same mangled name, don't
11837 add another one. This can happen e.g. for
11838 #pragma omp declare simd
11839 #pragma omp declare simd simdlen(8)
11840 int foo (int, int);
11841 if the simdlen is assumed to be 8 for the first one, etc. */
11842 for (struct cgraph_node *clone = node->simd_clones; clone;
11843 clone = clone->simdclone->next_clone)
11844 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11845 str) == 0)
11846 return NULL_TREE;
11848 return get_identifier (str);
11851 /* Create a simd clone of OLD_NODE and return it. */
11853 static struct cgraph_node *
11854 simd_clone_create (struct cgraph_node *old_node)
11856 struct cgraph_node *new_node;
11857 if (old_node->definition)
11859 if (!cgraph_function_with_gimple_body_p (old_node))
11860 return NULL;
11861 cgraph_get_body (old_node);
11862 new_node = cgraph_function_versioning (old_node, vNULL, NULL, NULL,
11863 false, NULL, NULL, "simdclone");
11865 else
11867 tree old_decl = old_node->decl;
11868 tree new_decl = copy_node (old_node->decl);
11869 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11870 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11871 SET_DECL_RTL (new_decl, NULL);
11872 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11873 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11874 new_node
11875 = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL);
11876 cgraph_call_function_insertion_hooks (new_node);
11878 if (new_node == NULL)
11879 return new_node;
11881 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11883 /* The function cgraph_function_versioning () will force the new
11884 symbol local. Undo this, and inherit external visability from
11885 the old node. */
11886 new_node->local.local = old_node->local.local;
11887 new_node->externally_visible = old_node->externally_visible;
11889 return new_node;
11892 /* Adjust the return type of the given function to its appropriate
11893 vector counterpart. Returns a simd array to be used throughout the
11894 function as a return value. */
11896 static tree
11897 simd_clone_adjust_return_type (struct cgraph_node *node)
11899 tree fndecl = node->decl;
11900 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11901 unsigned int veclen;
11902 tree t;
11904 /* Adjust the function return type. */
11905 if (orig_rettype == void_type_node)
11906 return NULL_TREE;
11907 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11908 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11909 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11910 veclen = node->simdclone->vecsize_int;
11911 else
11912 veclen = node->simdclone->vecsize_float;
11913 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11914 if (veclen > node->simdclone->simdlen)
11915 veclen = node->simdclone->simdlen;
11916 if (veclen == node->simdclone->simdlen)
11917 TREE_TYPE (TREE_TYPE (fndecl))
11918 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11919 node->simdclone->simdlen);
11920 else
11922 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11923 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11924 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11926 if (!node->definition)
11927 return NULL_TREE;
11929 t = DECL_RESULT (fndecl);
11930 /* Adjust the DECL_RESULT. */
11931 gcc_assert (TREE_TYPE (t) != void_type_node);
11932 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11933 relayout_decl (t);
11935 tree atype = build_array_type_nelts (orig_rettype,
11936 node->simdclone->simdlen);
11937 if (veclen != node->simdclone->simdlen)
11938 return build1 (VIEW_CONVERT_EXPR, atype, t);
11940 /* Set up a SIMD array to use as the return value. */
11941 tree retval = create_tmp_var_raw (atype, "retval");
11942 gimple_add_tmp_var (retval);
11943 return retval;
11946 /* Each vector argument has a corresponding array to be used locally
11947 as part of the eventual loop. Create such temporary array and
11948 return it.
11950 PREFIX is the prefix to be used for the temporary.
11952 TYPE is the inner element type.
11954 SIMDLEN is the number of elements. */
11956 static tree
11957 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11959 tree atype = build_array_type_nelts (type, simdlen);
11960 tree avar = create_tmp_var_raw (atype, prefix);
11961 gimple_add_tmp_var (avar);
11962 return avar;
11965 /* Modify the function argument types to their corresponding vector
11966 counterparts if appropriate. Also, create one array for each simd
11967 argument to be used locally when using the function arguments as
11968 part of the loop.
11970 NODE is the function whose arguments are to be adjusted.
11972 Returns an adjustment vector that will be filled describing how the
11973 argument types will be adjusted. */
11975 static ipa_parm_adjustment_vec
11976 simd_clone_adjust_argument_types (struct cgraph_node *node)
11978 vec<tree> args;
11979 ipa_parm_adjustment_vec adjustments;
11981 if (node->definition)
11982 args = ipa_get_vector_of_formal_parms (node->decl);
11983 else
11984 args = simd_clone_vector_of_formal_parm_types (node->decl);
11985 adjustments.create (args.length ());
11986 unsigned i, j, veclen;
11987 struct ipa_parm_adjustment adj;
11988 for (i = 0; i < node->simdclone->nargs; ++i)
11990 memset (&adj, 0, sizeof (adj));
11991 tree parm = args[i];
11992 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11993 adj.base_index = i;
11994 adj.base = parm;
11996 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11997 node->simdclone->args[i].orig_type = parm_type;
11999 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12001 /* No adjustment necessary for scalar arguments. */
12002 adj.op = IPA_PARM_OP_COPY;
12004 else
12006 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12007 veclen = node->simdclone->vecsize_int;
12008 else
12009 veclen = node->simdclone->vecsize_float;
12010 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12011 if (veclen > node->simdclone->simdlen)
12012 veclen = node->simdclone->simdlen;
12013 adj.arg_prefix = "simd";
12014 adj.type = build_vector_type (parm_type, veclen);
12015 node->simdclone->args[i].vector_type = adj.type;
12016 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12018 adjustments.safe_push (adj);
12019 if (j == veclen)
12021 memset (&adj, 0, sizeof (adj));
12022 adj.op = IPA_PARM_OP_NEW;
12023 adj.arg_prefix = "simd";
12024 adj.base_index = i;
12025 adj.type = node->simdclone->args[i].vector_type;
12029 if (node->definition)
12030 node->simdclone->args[i].simd_array
12031 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12032 parm_type, node->simdclone->simdlen);
12034 adjustments.safe_push (adj);
12037 if (node->simdclone->inbranch)
12039 tree base_type
12040 = simd_clone_compute_base_data_type (node->simdclone->origin,
12041 node->simdclone);
12043 memset (&adj, 0, sizeof (adj));
12044 adj.op = IPA_PARM_OP_NEW;
12045 adj.arg_prefix = "mask";
12047 adj.base_index = i;
12048 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12049 veclen = node->simdclone->vecsize_int;
12050 else
12051 veclen = node->simdclone->vecsize_float;
12052 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12053 if (veclen > node->simdclone->simdlen)
12054 veclen = node->simdclone->simdlen;
12055 adj.type = build_vector_type (base_type, veclen);
12056 adjustments.safe_push (adj);
12058 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12059 adjustments.safe_push (adj);
12061 /* We have previously allocated one extra entry for the mask. Use
12062 it and fill it. */
12063 struct cgraph_simd_clone *sc = node->simdclone;
12064 sc->nargs++;
12065 if (node->definition)
12067 sc->args[i].orig_arg
12068 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12069 sc->args[i].simd_array
12070 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12072 sc->args[i].orig_type = base_type;
12073 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12076 if (node->definition)
12077 ipa_modify_formal_parameters (node->decl, adjustments);
12078 else
12080 tree new_arg_types = NULL_TREE, new_reversed;
12081 bool last_parm_void = false;
12082 if (args.length () > 0 && args.last () == void_type_node)
12083 last_parm_void = true;
12085 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12086 j = adjustments.length ();
12087 for (i = 0; i < j; i++)
12089 struct ipa_parm_adjustment *adj = &adjustments[i];
12090 tree ptype;
12091 if (adj->op == IPA_PARM_OP_COPY)
12092 ptype = args[adj->base_index];
12093 else
12094 ptype = adj->type;
12095 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12097 new_reversed = nreverse (new_arg_types);
12098 if (last_parm_void)
12100 if (new_reversed)
12101 TREE_CHAIN (new_arg_types) = void_list_node;
12102 else
12103 new_reversed = void_list_node;
12106 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
12107 TYPE_ARG_TYPES (new_type) = new_reversed;
12108 TREE_TYPE (node->decl) = new_type;
12110 adjustments.release ();
12112 args.release ();
12113 return adjustments;
12116 /* Initialize and copy the function arguments in NODE to their
12117 corresponding local simd arrays. Returns a fresh gimple_seq with
12118 the instruction sequence generated. */
12120 static gimple_seq
12121 simd_clone_init_simd_arrays (struct cgraph_node *node,
12122 ipa_parm_adjustment_vec adjustments)
12124 gimple_seq seq = NULL;
12125 unsigned i = 0, j = 0, k;
12127 for (tree arg = DECL_ARGUMENTS (node->decl);
12128 arg;
12129 arg = DECL_CHAIN (arg), i++, j++)
12131 if (adjustments[j].op == IPA_PARM_OP_COPY)
12132 continue;
12134 node->simdclone->args[i].vector_arg = arg;
12136 tree array = node->simdclone->args[i].simd_array;
12137 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
12139 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12140 tree ptr = build_fold_addr_expr (array);
12141 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
12142 build_int_cst (ptype, 0));
12143 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
12144 gimplify_and_add (t, &seq);
12146 else
12148 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
12149 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12150 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
12152 tree ptr = build_fold_addr_expr (array);
12153 int elemsize;
12154 if (k)
12156 arg = DECL_CHAIN (arg);
12157 j++;
12159 elemsize
12160 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
12161 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
12162 build_int_cst (ptype, k * elemsize));
12163 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
12164 gimplify_and_add (t, &seq);
12168 return seq;
12171 /* Callback info for ipa_simd_modify_stmt_ops below. */
12173 struct modify_stmt_info {
12174 ipa_parm_adjustment_vec adjustments;
12175 gimple stmt;
12176 /* True if the parent statement was modified by
12177 ipa_simd_modify_stmt_ops. */
12178 bool modified;
12181 /* Callback for walk_gimple_op.
12183 Adjust operands from a given statement as specified in the
12184 adjustments vector in the callback data. */
12186 static tree
12187 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
12189 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
12190 if (!SSA_VAR_P (*tp))
12192 /* Make sure we treat subtrees as a RHS. This makes sure that
12193 when examining the `*foo' in *foo=x, the `foo' get treated as
12194 a use properly. */
12195 wi->is_lhs = false;
12196 wi->val_only = true;
12197 if (TYPE_P (*tp))
12198 *walk_subtrees = 0;
12199 return NULL_TREE;
12201 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
12202 struct ipa_parm_adjustment *cand
12203 = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
12204 if (!cand)
12205 return NULL_TREE;
12207 tree t = *tp;
12208 tree repl = make_ssa_name (TREE_TYPE (t), NULL);
12210 gimple stmt;
12211 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
12212 if (wi->is_lhs)
12214 stmt = gimple_build_assign (unshare_expr (cand->new_decl), repl);
12215 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
12216 SSA_NAME_DEF_STMT (repl) = info->stmt;
12218 else
12220 /* You'd think we could skip the extra SSA variable when
12221 wi->val_only=true, but we may have `*var' which will get
12222 replaced into `*var_array[iter]' and will likely be something
12223 not gimple. */
12224 stmt = gimple_build_assign (repl, unshare_expr (cand->new_decl));
12225 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
12228 if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
12230 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
12231 *tp = vce;
12233 else
12234 *tp = repl;
12236 info->modified = true;
12237 wi->is_lhs = false;
12238 wi->val_only = true;
12239 return NULL_TREE;
12242 /* Traverse the function body and perform all modifications as
12243 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
12244 modified such that the replacement/reduction value will now be an
12245 offset into the corresponding simd_array.
12247 This function will replace all function argument uses with their
12248 corresponding simd array elements, and ajust the return values
12249 accordingly. */
12251 static void
12252 ipa_simd_modify_function_body (struct cgraph_node *node,
12253 ipa_parm_adjustment_vec adjustments,
12254 tree retval_array, tree iter)
12256 basic_block bb;
12257 unsigned int i, j;
12259 /* Re-use the adjustments array, but this time use it to replace
12260 every function argument use to an offset into the corresponding
12261 simd_array. */
12262 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
12264 if (!node->simdclone->args[i].vector_arg)
12265 continue;
12267 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
12268 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
12269 adjustments[j].new_decl
12270 = build4 (ARRAY_REF,
12271 basetype,
12272 node->simdclone->args[i].simd_array,
12273 iter,
12274 NULL_TREE, NULL_TREE);
12275 if (adjustments[j].op == IPA_PARM_OP_NONE
12276 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
12277 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
12280 struct modify_stmt_info info;
12281 info.adjustments = adjustments;
12283 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
12285 gimple_stmt_iterator gsi;
12287 gsi = gsi_start_bb (bb);
12288 while (!gsi_end_p (gsi))
12290 gimple stmt = gsi_stmt (gsi);
12291 info.stmt = stmt;
12292 struct walk_stmt_info wi;
12294 memset (&wi, 0, sizeof (wi));
12295 info.modified = false;
12296 wi.info = &info;
12297 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
12299 if (gimple_code (stmt) == GIMPLE_RETURN)
12301 tree retval = gimple_return_retval (stmt);
12302 if (!retval)
12304 gsi_remove (&gsi, true);
12305 continue;
12308 /* Replace `return foo' with `retval_array[iter] = foo'. */
12309 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
12310 retval_array, iter, NULL, NULL);
12311 stmt = gimple_build_assign (ref, retval);
12312 gsi_replace (&gsi, stmt, true);
12313 info.modified = true;
12316 if (info.modified)
12318 update_stmt (stmt);
12319 if (maybe_clean_eh_stmt (stmt))
12320 gimple_purge_dead_eh_edges (gimple_bb (stmt));
12322 gsi_next (&gsi);
12327 /* Adjust the argument types in NODE to their appropriate vector
12328 counterparts. */
12330 static void
12331 simd_clone_adjust (struct cgraph_node *node)
12333 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
12335 targetm.simd_clone.adjust (node);
12337 tree retval = simd_clone_adjust_return_type (node);
12338 ipa_parm_adjustment_vec adjustments
12339 = simd_clone_adjust_argument_types (node);
12341 push_gimplify_context ();
12343 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
12345 /* Adjust all uses of vector arguments accordingly. Adjust all
12346 return values accordingly. */
12347 tree iter = create_tmp_var (unsigned_type_node, "iter");
12348 tree iter1 = make_ssa_name (iter, NULL);
12349 tree iter2 = make_ssa_name (iter, NULL);
12350 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
12352 /* Initialize the iteration variable. */
12353 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12354 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
12355 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
12356 /* Insert the SIMD array and iv initialization at function
12357 entry. */
12358 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
12360 pop_gimplify_context (NULL);
12362 /* Create a new BB right before the original exit BB, to hold the
12363 iteration increment and the condition/branch. */
12364 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
12365 basic_block incr_bb = create_empty_bb (orig_exit);
12366 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
12367 flag. Set it now to be a FALLTHRU_EDGE. */
12368 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
12369 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
12370 for (unsigned i = 0;
12371 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
12373 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
12374 redirect_edge_succ (e, incr_bb);
12376 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
12377 e->probability = REG_BR_PROB_BASE;
12378 gsi = gsi_last_bb (incr_bb);
12379 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
12380 build_int_cst (unsigned_type_node,
12381 1));
12382 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12384 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12385 struct loop *loop = alloc_loop ();
12386 cfun->has_force_vect_loops = true;
12387 loop->safelen = node->simdclone->simdlen;
12388 loop->force_vect = true;
12389 loop->header = body_bb;
12390 add_bb_to_loop (incr_bb, loop);
12392 /* Branch around the body if the mask applies. */
12393 if (node->simdclone->inbranch)
12395 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
12396 tree mask_array
12397 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
12398 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
12399 tree aref = build4 (ARRAY_REF,
12400 TREE_TYPE (TREE_TYPE (mask_array)),
12401 mask_array, iter1,
12402 NULL, NULL);
12403 g = gimple_build_assign (mask, aref);
12404 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12405 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
12406 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
12408 aref = build1 (VIEW_CONVERT_EXPR,
12409 build_nonstandard_integer_type (bitsize, 0), mask);
12410 mask = make_ssa_name (TREE_TYPE (aref), NULL);
12411 g = gimple_build_assign (mask, aref);
12412 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12415 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
12416 NULL, NULL);
12417 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12418 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
12419 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
12422 /* Generate the condition. */
12423 g = gimple_build_cond (LT_EXPR,
12424 iter2,
12425 build_int_cst (unsigned_type_node,
12426 node->simdclone->simdlen),
12427 NULL, NULL);
12428 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12429 e = split_block (incr_bb, gsi_stmt (gsi));
12430 basic_block latch_bb = e->dest;
12431 basic_block new_exit_bb = e->dest;
12432 new_exit_bb = split_block (latch_bb, NULL)->dest;
12433 loop->latch = latch_bb;
12435 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
12437 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
12438 /* The successor of incr_bb is already pointing to latch_bb; just
12439 change the flags.
12440 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12441 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
12443 gimple phi = create_phi_node (iter1, body_bb);
12444 edge preheader_edge = find_edge (entry_bb, body_bb);
12445 edge latch_edge = single_succ_edge (latch_bb);
12446 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
12447 UNKNOWN_LOCATION);
12448 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12450 /* Generate the new return. */
12451 gsi = gsi_last_bb (new_exit_bb);
12452 if (retval
12453 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
12454 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
12455 retval = TREE_OPERAND (retval, 0);
12456 else if (retval)
12458 retval = build1 (VIEW_CONVERT_EXPR,
12459 TREE_TYPE (TREE_TYPE (node->decl)),
12460 retval);
12461 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
12462 false, GSI_CONTINUE_LINKING);
12464 g = gimple_build_return (retval);
12465 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12467 /* Handle aligned clauses by replacing default defs of the aligned
12468 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12469 lhs. Handle linear by adding PHIs. */
12470 for (unsigned i = 0; i < node->simdclone->nargs; i++)
12471 if (node->simdclone->args[i].alignment
12472 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
12473 && (node->simdclone->args[i].alignment
12474 & (node->simdclone->args[i].alignment - 1)) == 0
12475 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
12476 == POINTER_TYPE)
12478 unsigned int alignment = node->simdclone->args[i].alignment;
12479 tree orig_arg = node->simdclone->args[i].orig_arg;
12480 tree def = ssa_default_def (cfun, orig_arg);
12481 if (def && !has_zero_uses (def))
12483 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
12484 gimple_seq seq = NULL;
12485 bool need_cvt = false;
12486 gimple call
12487 = gimple_build_call (fn, 2, def, size_int (alignment));
12488 g = call;
12489 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
12490 ptr_type_node))
12491 need_cvt = true;
12492 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
12493 gimple_call_set_lhs (g, t);
12494 gimple_seq_add_stmt_without_update (&seq, g);
12495 if (need_cvt)
12497 t = make_ssa_name (orig_arg, NULL);
12498 g = gimple_build_assign_with_ops (NOP_EXPR, t,
12499 gimple_call_lhs (g),
12500 NULL_TREE);
12501 gimple_seq_add_stmt_without_update (&seq, g);
12503 gsi_insert_seq_on_edge_immediate
12504 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
12506 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12507 int freq = compute_call_stmt_bb_frequency (current_function_decl,
12508 entry_bb);
12509 cgraph_create_edge (node, cgraph_get_create_node (fn),
12510 call, entry_bb->count, freq);
12512 imm_use_iterator iter;
12513 use_operand_p use_p;
12514 gimple use_stmt;
12515 tree repl = gimple_get_lhs (g);
12516 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12517 if (is_gimple_debug (use_stmt) || use_stmt == call)
12518 continue;
12519 else
12520 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12521 SET_USE (use_p, repl);
12524 else if (node->simdclone->args[i].arg_type
12525 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12527 tree orig_arg = node->simdclone->args[i].orig_arg;
12528 tree def = ssa_default_def (cfun, orig_arg);
12529 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12530 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
12531 if (def && !has_zero_uses (def))
12533 iter1 = make_ssa_name (orig_arg, NULL);
12534 iter2 = make_ssa_name (orig_arg, NULL);
12535 phi = create_phi_node (iter1, body_bb);
12536 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
12537 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12538 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12539 ? PLUS_EXPR : POINTER_PLUS_EXPR;
12540 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12541 ? TREE_TYPE (orig_arg) : sizetype;
12542 tree addcst
12543 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
12544 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
12545 gsi = gsi_last_bb (incr_bb);
12546 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12548 imm_use_iterator iter;
12549 use_operand_p use_p;
12550 gimple use_stmt;
12551 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12552 if (use_stmt == phi)
12553 continue;
12554 else
12555 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12556 SET_USE (use_p, iter1);
12560 calculate_dominance_info (CDI_DOMINATORS);
12561 add_loop (loop, loop->header->loop_father);
12562 update_ssa (TODO_update_ssa);
12564 pop_cfun ();
12567 /* If the function in NODE is tagged as an elemental SIMD function,
12568 create the appropriate SIMD clones. */
12570 static void
12571 expand_simd_clones (struct cgraph_node *node)
12573 tree attr = lookup_attribute ("omp declare simd",
12574 DECL_ATTRIBUTES (node->decl));
12575 if (attr == NULL_TREE
12576 || node->global.inlined_to
12577 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
12578 return;
12580 /* Ignore
12581 #pragma omp declare simd
12582 extern int foo ();
12583 in C, there we don't know the argument types at all. */
12584 if (!node->definition
12585 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
12586 return;
12590 /* Start with parsing the "omp declare simd" attribute(s). */
12591 bool inbranch_clause_specified;
12592 struct cgraph_simd_clone *clone_info
12593 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
12594 &inbranch_clause_specified);
12595 if (clone_info == NULL)
12596 continue;
12598 int orig_simdlen = clone_info->simdlen;
12599 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
12600 /* The target can return 0 (no simd clones should be created),
12601 1 (just one ISA of simd clones should be created) or higher
12602 count of ISA variants. In that case, clone_info is initialized
12603 for the first ISA variant. */
12604 int count
12605 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
12606 base_type, 0);
12607 if (count == 0)
12608 continue;
12610 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12611 also create one inbranch and one !inbranch clone of it. */
12612 for (int i = 0; i < count * 2; i++)
12614 struct cgraph_simd_clone *clone = clone_info;
12615 if (inbranch_clause_specified && (i & 1) != 0)
12616 continue;
12618 if (i != 0)
12620 clone = simd_clone_struct_alloc (clone_info->nargs
12621 + ((i & 1) != 0));
12622 simd_clone_struct_copy (clone, clone_info);
12623 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12624 and simd_clone_adjust_argument_types did to the first
12625 clone's info. */
12626 clone->nargs -= clone_info->inbranch;
12627 clone->simdlen = orig_simdlen;
12628 /* And call the target hook again to get the right ISA. */
12629 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
12630 base_type,
12631 i / 2);
12632 if ((i & 1) != 0)
12633 clone->inbranch = 1;
12636 /* simd_clone_mangle might fail if such a clone has been created
12637 already. */
12638 tree id = simd_clone_mangle (node, clone);
12639 if (id == NULL_TREE)
12640 continue;
12642 /* Only when we are sure we want to create the clone actually
12643 clone the function (or definitions) or create another
12644 extern FUNCTION_DECL (for prototypes without definitions). */
12645 struct cgraph_node *n = simd_clone_create (node);
12646 if (n == NULL)
12647 continue;
12649 n->simdclone = clone;
12650 clone->origin = node;
12651 clone->next_clone = NULL;
12652 if (node->simd_clones == NULL)
12654 clone->prev_clone = n;
12655 node->simd_clones = n;
12657 else
12659 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
12660 clone->prev_clone->simdclone->next_clone = n;
12661 node->simd_clones->simdclone->prev_clone = n;
12663 change_decl_assembler_name (n->decl, id);
12664 /* And finally adjust the return type, parameters and for
12665 definitions also function body. */
12666 if (node->definition)
12667 simd_clone_adjust (n);
12668 else
12670 simd_clone_adjust_return_type (n);
12671 simd_clone_adjust_argument_types (n);
12675 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
12678 /* Entry point for IPA simd clone creation pass. */
12680 static unsigned int
12681 ipa_omp_simd_clone (void)
12683 struct cgraph_node *node;
12684 FOR_EACH_FUNCTION (node)
12685 expand_simd_clones (node);
12686 return 0;
12689 namespace {
12691 const pass_data pass_data_omp_simd_clone =
12693 SIMPLE_IPA_PASS, /* type */
12694 "simdclone", /* name */
12695 OPTGROUP_NONE, /* optinfo_flags */
12696 true, /* has_gate */
12697 true, /* has_execute */
12698 TV_NONE, /* tv_id */
12699 ( PROP_ssa | PROP_cfg ), /* properties_required */
12700 0, /* properties_provided */
12701 0, /* properties_destroyed */
12702 0, /* todo_flags_start */
12703 0, /* todo_flags_finish */
12706 class pass_omp_simd_clone : public simple_ipa_opt_pass
12708 public:
12709 pass_omp_simd_clone(gcc::context *ctxt)
12710 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
12713 /* opt_pass methods: */
12714 bool gate () { return ((flag_openmp || flag_openmp_simd
12715 || flag_cilkplus || (in_lto_p && !flag_wpa))
12716 && (targetm.simd_clone.compute_vecsize_and_simdlen
12717 != NULL)); }
12718 unsigned int execute () { return ipa_omp_simd_clone (); }
12721 } // anon namespace
12723 simple_ipa_opt_pass *
12724 make_pass_omp_simd_clone (gcc::context *ctxt)
12726 return new pass_omp_simd_clone (ctxt);
12729 #include "gt-omp-low.h"