* ChangeLog-2013: Correct an old entry.
[official-gcc.git] / gcc / omp-low.c
blob129d513d12c7917b3b5294d0cddb559ed596a424
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_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 /* ??? Trivially accessible from anywhere. But why would we even
867 be passing an address in this case? Should we simply assert
868 this to be false, or should we have a cleanup pass that removes
869 these from the list of mappings? */
870 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
871 return true;
873 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
874 without analyzing the expression whether or not its location
875 is accessible to anyone else. In the case of nested parallel
876 regions it certainly may be. */
877 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
878 return true;
880 /* Do not use copy-in/copy-out for variables that have their
881 address taken. */
882 if (TREE_ADDRESSABLE (decl))
883 return true;
885 /* lower_send_shared_vars only uses copy-in, but not copy-out
886 for these. */
887 if (TREE_READONLY (decl)
888 || ((TREE_CODE (decl) == RESULT_DECL
889 || TREE_CODE (decl) == PARM_DECL)
890 && DECL_BY_REFERENCE (decl)))
891 return false;
893 /* Disallow copy-in/out in nested parallel if
894 decl is shared in outer parallel, otherwise
895 each thread could store the shared variable
896 in its own copy-in location, making the
897 variable no longer really shared. */
898 if (shared_ctx->is_nested)
900 omp_context *up;
902 for (up = shared_ctx->outer; up; up = up->outer)
903 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
904 break;
906 if (up)
908 tree c;
910 for (c = gimple_omp_taskreg_clauses (up->stmt);
911 c; c = OMP_CLAUSE_CHAIN (c))
912 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
913 && OMP_CLAUSE_DECL (c) == decl)
914 break;
916 if (c)
917 goto maybe_mark_addressable_and_ret;
921 /* For tasks avoid using copy-in/out. As tasks can be
922 deferred or executed in different thread, when GOMP_task
923 returns, the task hasn't necessarily terminated. */
924 if (is_task_ctx (shared_ctx))
926 tree outer;
927 maybe_mark_addressable_and_ret:
928 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
929 if (is_gimple_reg (outer))
931 /* Taking address of OUTER in lower_send_shared_vars
932 might need regimplification of everything that uses the
933 variable. */
934 if (!task_shared_vars)
935 task_shared_vars = BITMAP_ALLOC (NULL);
936 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
937 TREE_ADDRESSABLE (outer) = 1;
939 return true;
943 return false;
946 /* Construct a new automatic decl similar to VAR. */
948 static tree
949 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
951 tree copy = copy_var_decl (var, name, type);
953 DECL_CONTEXT (copy) = current_function_decl;
954 DECL_CHAIN (copy) = ctx->block_vars;
955 ctx->block_vars = copy;
957 return copy;
960 static tree
961 omp_copy_decl_1 (tree var, omp_context *ctx)
963 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
966 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
967 as appropriate. */
968 static tree
969 omp_build_component_ref (tree obj, tree field)
971 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
972 if (TREE_THIS_VOLATILE (field))
973 TREE_THIS_VOLATILE (ret) |= 1;
974 if (TREE_READONLY (field))
975 TREE_READONLY (ret) |= 1;
976 return ret;
979 /* Build tree nodes to access the field for VAR on the receiver side. */
981 static tree
982 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
984 tree x, field = lookup_field (var, ctx);
986 /* If the receiver record type was remapped in the child function,
987 remap the field into the new record type. */
988 x = maybe_lookup_field (field, ctx);
989 if (x != NULL)
990 field = x;
992 x = build_simple_mem_ref (ctx->receiver_decl);
993 x = omp_build_component_ref (x, field);
994 if (by_ref)
995 x = build_simple_mem_ref (x);
997 return x;
1000 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1001 of a parallel, this is a component reference; for workshare constructs
1002 this is some variable. */
1004 static tree
1005 build_outer_var_ref (tree var, omp_context *ctx)
1007 tree x;
1009 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1010 x = var;
1011 else if (is_variable_sized (var))
1013 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1014 x = build_outer_var_ref (x, ctx);
1015 x = build_simple_mem_ref (x);
1017 else if (is_taskreg_ctx (ctx))
1019 bool by_ref = use_pointer_for_field (var, NULL);
1020 x = build_receiver_ref (var, by_ref, ctx);
1022 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1023 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1025 /* #pragma omp simd isn't a worksharing construct, and can reference even
1026 private vars in its linear etc. clauses. */
1027 x = NULL_TREE;
1028 if (ctx->outer && is_taskreg_ctx (ctx))
1029 x = lookup_decl (var, ctx->outer);
1030 else if (ctx->outer)
1031 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1032 if (x == NULL_TREE)
1033 x = var;
1035 else if (ctx->outer)
1036 x = lookup_decl (var, ctx->outer);
1037 else if (is_reference (var))
1038 /* This can happen with orphaned constructs. If var is reference, it is
1039 possible it is shared and as such valid. */
1040 x = var;
1041 else
1042 gcc_unreachable ();
1044 if (is_reference (var))
1045 x = build_simple_mem_ref (x);
1047 return x;
1050 /* Build tree nodes to access the field for VAR on the sender side. */
1052 static tree
1053 build_sender_ref (tree var, omp_context *ctx)
1055 tree field = lookup_sfield (var, ctx);
1056 return omp_build_component_ref (ctx->sender_decl, field);
1059 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1061 static void
1062 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1064 tree field, type, sfield = NULL_TREE;
1066 gcc_assert ((mask & 1) == 0
1067 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1068 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1069 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1071 type = TREE_TYPE (var);
1072 if (mask & 4)
1074 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1075 type = build_pointer_type (build_pointer_type (type));
1077 else if (by_ref)
1078 type = build_pointer_type (type);
1079 else if ((mask & 3) == 1 && is_reference (var))
1080 type = TREE_TYPE (type);
1082 field = build_decl (DECL_SOURCE_LOCATION (var),
1083 FIELD_DECL, DECL_NAME (var), type);
1085 /* Remember what variable this field was created for. This does have a
1086 side effect of making dwarf2out ignore this member, so for helpful
1087 debugging we clear it later in delete_omp_context. */
1088 DECL_ABSTRACT_ORIGIN (field) = var;
1089 if (type == TREE_TYPE (var))
1091 DECL_ALIGN (field) = DECL_ALIGN (var);
1092 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1093 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1095 else
1096 DECL_ALIGN (field) = TYPE_ALIGN (type);
1098 if ((mask & 3) == 3)
1100 insert_field_into_struct (ctx->record_type, field);
1101 if (ctx->srecord_type)
1103 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1104 FIELD_DECL, DECL_NAME (var), type);
1105 DECL_ABSTRACT_ORIGIN (sfield) = var;
1106 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1107 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1108 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1109 insert_field_into_struct (ctx->srecord_type, sfield);
1112 else
1114 if (ctx->srecord_type == NULL_TREE)
1116 tree t;
1118 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1119 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1120 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1122 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1123 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1124 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1125 insert_field_into_struct (ctx->srecord_type, sfield);
1126 splay_tree_insert (ctx->sfield_map,
1127 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1128 (splay_tree_value) sfield);
1131 sfield = field;
1132 insert_field_into_struct ((mask & 1) ? ctx->record_type
1133 : ctx->srecord_type, field);
1136 if (mask & 1)
1137 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1138 (splay_tree_value) field);
1139 if ((mask & 2) && ctx->sfield_map)
1140 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1141 (splay_tree_value) sfield);
1144 static tree
1145 install_var_local (tree var, omp_context *ctx)
1147 tree new_var = omp_copy_decl_1 (var, ctx);
1148 insert_decl_map (&ctx->cb, var, new_var);
1149 return new_var;
1152 /* Adjust the replacement for DECL in CTX for the new context. This means
1153 copying the DECL_VALUE_EXPR, and fixing up the type. */
1155 static void
1156 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1158 tree new_decl, size;
1160 new_decl = lookup_decl (decl, ctx);
1162 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1164 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1165 && DECL_HAS_VALUE_EXPR_P (decl))
1167 tree ve = DECL_VALUE_EXPR (decl);
1168 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1169 SET_DECL_VALUE_EXPR (new_decl, ve);
1170 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1173 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1175 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1176 if (size == error_mark_node)
1177 size = TYPE_SIZE (TREE_TYPE (new_decl));
1178 DECL_SIZE (new_decl) = size;
1180 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1181 if (size == error_mark_node)
1182 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1183 DECL_SIZE_UNIT (new_decl) = size;
1187 /* The callback for remap_decl. Search all containing contexts for a
1188 mapping of the variable; this avoids having to duplicate the splay
1189 tree ahead of time. We know a mapping doesn't already exist in the
1190 given context. Create new mappings to implement default semantics. */
1192 static tree
1193 omp_copy_decl (tree var, copy_body_data *cb)
1195 omp_context *ctx = (omp_context *) cb;
1196 tree new_var;
1198 if (TREE_CODE (var) == LABEL_DECL)
1200 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1201 DECL_CONTEXT (new_var) = current_function_decl;
1202 insert_decl_map (&ctx->cb, var, new_var);
1203 return new_var;
1206 while (!is_taskreg_ctx (ctx))
1208 ctx = ctx->outer;
1209 if (ctx == NULL)
1210 return var;
1211 new_var = maybe_lookup_decl (var, ctx);
1212 if (new_var)
1213 return new_var;
1216 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1217 return var;
1219 return error_mark_node;
1223 /* Debugging dumps for parallel regions. */
1224 void dump_omp_region (FILE *, struct omp_region *, int);
1225 void debug_omp_region (struct omp_region *);
1226 void debug_all_omp_regions (void);
1228 /* Dump the parallel region tree rooted at REGION. */
1230 void
1231 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1233 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1234 gimple_code_name[region->type]);
1236 if (region->inner)
1237 dump_omp_region (file, region->inner, indent + 4);
1239 if (region->cont)
1241 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1242 region->cont->index);
1245 if (region->exit)
1246 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1247 region->exit->index);
1248 else
1249 fprintf (file, "%*s[no exit marker]\n", indent, "");
1251 if (region->next)
1252 dump_omp_region (file, region->next, indent);
1255 DEBUG_FUNCTION void
1256 debug_omp_region (struct omp_region *region)
1258 dump_omp_region (stderr, region, 0);
1261 DEBUG_FUNCTION void
1262 debug_all_omp_regions (void)
1264 dump_omp_region (stderr, root_omp_region, 0);
1268 /* Create a new parallel region starting at STMT inside region PARENT. */
1270 static struct omp_region *
1271 new_omp_region (basic_block bb, enum gimple_code type,
1272 struct omp_region *parent)
1274 struct omp_region *region = XCNEW (struct omp_region);
1276 region->outer = parent;
1277 region->entry = bb;
1278 region->type = type;
1280 if (parent)
1282 /* This is a nested region. Add it to the list of inner
1283 regions in PARENT. */
1284 region->next = parent->inner;
1285 parent->inner = region;
1287 else
1289 /* This is a toplevel region. Add it to the list of toplevel
1290 regions in ROOT_OMP_REGION. */
1291 region->next = root_omp_region;
1292 root_omp_region = region;
1295 return region;
1298 /* Release the memory associated with the region tree rooted at REGION. */
1300 static void
1301 free_omp_region_1 (struct omp_region *region)
1303 struct omp_region *i, *n;
1305 for (i = region->inner; i ; i = n)
1307 n = i->next;
1308 free_omp_region_1 (i);
1311 free (region);
1314 /* Release the memory for the entire omp region tree. */
1316 void
1317 free_omp_regions (void)
1319 struct omp_region *r, *n;
1320 for (r = root_omp_region; r ; r = n)
1322 n = r->next;
1323 free_omp_region_1 (r);
1325 root_omp_region = NULL;
1329 /* Create a new context, with OUTER_CTX being the surrounding context. */
1331 static omp_context *
1332 new_omp_context (gimple stmt, omp_context *outer_ctx)
1334 omp_context *ctx = XCNEW (omp_context);
1336 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1337 (splay_tree_value) ctx);
1338 ctx->stmt = stmt;
1340 if (outer_ctx)
1342 ctx->outer = outer_ctx;
1343 ctx->cb = outer_ctx->cb;
1344 ctx->cb.block = NULL;
1345 ctx->depth = outer_ctx->depth + 1;
1347 else
1349 ctx->cb.src_fn = current_function_decl;
1350 ctx->cb.dst_fn = current_function_decl;
1351 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1352 gcc_checking_assert (ctx->cb.src_node);
1353 ctx->cb.dst_node = ctx->cb.src_node;
1354 ctx->cb.src_cfun = cfun;
1355 ctx->cb.copy_decl = omp_copy_decl;
1356 ctx->cb.eh_lp_nr = 0;
1357 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1358 ctx->depth = 1;
1361 ctx->cb.decl_map = pointer_map_create ();
1363 return ctx;
1366 static gimple_seq maybe_catch_exception (gimple_seq);
1368 /* Finalize task copyfn. */
1370 static void
1371 finalize_task_copyfn (gimple task_stmt)
1373 struct function *child_cfun;
1374 tree child_fn;
1375 gimple_seq seq = NULL, new_seq;
1376 gimple bind;
1378 child_fn = gimple_omp_task_copy_fn (task_stmt);
1379 if (child_fn == NULL_TREE)
1380 return;
1382 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1383 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1385 push_cfun (child_cfun);
1386 bind = gimplify_body (child_fn, false);
1387 gimple_seq_add_stmt (&seq, bind);
1388 new_seq = maybe_catch_exception (seq);
1389 if (new_seq != seq)
1391 bind = gimple_build_bind (NULL, new_seq, NULL);
1392 seq = NULL;
1393 gimple_seq_add_stmt (&seq, bind);
1395 gimple_set_body (child_fn, seq);
1396 pop_cfun ();
1398 /* Inform the callgraph about the new function. */
1399 cgraph_add_new_function (child_fn, false);
1402 /* Destroy a omp_context data structures. Called through the splay tree
1403 value delete callback. */
1405 static void
1406 delete_omp_context (splay_tree_value value)
1408 omp_context *ctx = (omp_context *) value;
1410 pointer_map_destroy (ctx->cb.decl_map);
1412 if (ctx->field_map)
1413 splay_tree_delete (ctx->field_map);
1414 if (ctx->sfield_map)
1415 splay_tree_delete (ctx->sfield_map);
1417 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1418 it produces corrupt debug information. */
1419 if (ctx->record_type)
1421 tree t;
1422 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1423 DECL_ABSTRACT_ORIGIN (t) = NULL;
1425 if (ctx->srecord_type)
1427 tree t;
1428 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1429 DECL_ABSTRACT_ORIGIN (t) = NULL;
1432 if (is_task_ctx (ctx))
1433 finalize_task_copyfn (ctx->stmt);
1435 XDELETE (ctx);
1438 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1439 context. */
1441 static void
1442 fixup_child_record_type (omp_context *ctx)
1444 tree f, type = ctx->record_type;
1446 /* ??? It isn't sufficient to just call remap_type here, because
1447 variably_modified_type_p doesn't work the way we expect for
1448 record types. Testing each field for whether it needs remapping
1449 and creating a new record by hand works, however. */
1450 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1451 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1452 break;
1453 if (f)
1455 tree name, new_fields = NULL;
1457 type = lang_hooks.types.make_type (RECORD_TYPE);
1458 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1459 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1460 TYPE_DECL, name, type);
1461 TYPE_NAME (type) = name;
1463 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1465 tree new_f = copy_node (f);
1466 DECL_CONTEXT (new_f) = type;
1467 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1468 DECL_CHAIN (new_f) = new_fields;
1469 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1470 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1471 &ctx->cb, NULL);
1472 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1473 &ctx->cb, NULL);
1474 new_fields = new_f;
1476 /* Arrange to be able to look up the receiver field
1477 given the sender field. */
1478 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1479 (splay_tree_value) new_f);
1481 TYPE_FIELDS (type) = nreverse (new_fields);
1482 layout_type (type);
1485 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1488 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1489 specified by CLAUSES. */
1491 static void
1492 scan_sharing_clauses (tree clauses, omp_context *ctx)
1494 tree c, decl;
1495 bool scan_array_reductions = false;
1497 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1499 bool by_ref;
1501 switch (OMP_CLAUSE_CODE (c))
1503 case OMP_CLAUSE_PRIVATE:
1504 decl = OMP_CLAUSE_DECL (c);
1505 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1506 goto do_private;
1507 else if (!is_variable_sized (decl))
1508 install_var_local (decl, ctx);
1509 break;
1511 case OMP_CLAUSE_SHARED:
1512 /* Ignore shared directives in teams construct. */
1513 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1514 break;
1515 gcc_assert (is_taskreg_ctx (ctx));
1516 decl = OMP_CLAUSE_DECL (c);
1517 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1518 || !is_variable_sized (decl));
1519 /* Global variables don't need to be copied,
1520 the receiver side will use them directly. */
1521 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1522 break;
1523 by_ref = use_pointer_for_field (decl, ctx);
1524 if (! TREE_READONLY (decl)
1525 || TREE_ADDRESSABLE (decl)
1526 || by_ref
1527 || is_reference (decl))
1529 install_var_field (decl, by_ref, 3, ctx);
1530 install_var_local (decl, ctx);
1531 break;
1533 /* We don't need to copy const scalar vars back. */
1534 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1535 goto do_private;
1537 case OMP_CLAUSE_LASTPRIVATE:
1538 /* Let the corresponding firstprivate clause create
1539 the variable. */
1540 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1541 break;
1542 /* FALLTHRU */
1544 case OMP_CLAUSE_FIRSTPRIVATE:
1545 case OMP_CLAUSE_REDUCTION:
1546 case OMP_CLAUSE_LINEAR:
1547 decl = OMP_CLAUSE_DECL (c);
1548 do_private:
1549 if (is_variable_sized (decl))
1551 if (is_task_ctx (ctx))
1552 install_var_field (decl, false, 1, ctx);
1553 break;
1555 else if (is_taskreg_ctx (ctx))
1557 bool global
1558 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1559 by_ref = use_pointer_for_field (decl, NULL);
1561 if (is_task_ctx (ctx)
1562 && (global || by_ref || is_reference (decl)))
1564 install_var_field (decl, false, 1, ctx);
1565 if (!global)
1566 install_var_field (decl, by_ref, 2, ctx);
1568 else if (!global)
1569 install_var_field (decl, by_ref, 3, ctx);
1571 install_var_local (decl, ctx);
1572 break;
1574 case OMP_CLAUSE__LOOPTEMP_:
1575 gcc_assert (is_parallel_ctx (ctx));
1576 decl = OMP_CLAUSE_DECL (c);
1577 install_var_field (decl, false, 3, ctx);
1578 install_var_local (decl, ctx);
1579 break;
1581 case OMP_CLAUSE_COPYPRIVATE:
1582 case OMP_CLAUSE_COPYIN:
1583 decl = OMP_CLAUSE_DECL (c);
1584 by_ref = use_pointer_for_field (decl, NULL);
1585 install_var_field (decl, by_ref, 3, ctx);
1586 break;
1588 case OMP_CLAUSE_DEFAULT:
1589 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1590 break;
1592 case OMP_CLAUSE_FINAL:
1593 case OMP_CLAUSE_IF:
1594 case OMP_CLAUSE_NUM_THREADS:
1595 case OMP_CLAUSE_NUM_TEAMS:
1596 case OMP_CLAUSE_THREAD_LIMIT:
1597 case OMP_CLAUSE_DEVICE:
1598 case OMP_CLAUSE_SCHEDULE:
1599 case OMP_CLAUSE_DIST_SCHEDULE:
1600 case OMP_CLAUSE_DEPEND:
1601 if (ctx->outer)
1602 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1603 break;
1605 case OMP_CLAUSE_TO:
1606 case OMP_CLAUSE_FROM:
1607 case OMP_CLAUSE_MAP:
1608 if (ctx->outer)
1609 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1610 decl = OMP_CLAUSE_DECL (c);
1611 /* Global variables with "omp declare target" attribute
1612 don't need to be copied, the receiver side will use them
1613 directly. */
1614 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1615 && DECL_P (decl)
1616 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1617 && lookup_attribute ("omp declare target",
1618 DECL_ATTRIBUTES (decl)))
1619 break;
1620 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1621 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1623 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1624 #pragma omp target data, there is nothing to map for
1625 those. */
1626 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1627 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1628 break;
1630 if (DECL_P (decl))
1632 if (DECL_SIZE (decl)
1633 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1635 tree decl2 = DECL_VALUE_EXPR (decl);
1636 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1637 decl2 = TREE_OPERAND (decl2, 0);
1638 gcc_assert (DECL_P (decl2));
1639 install_var_field (decl2, true, 3, ctx);
1640 install_var_local (decl2, ctx);
1641 install_var_local (decl, ctx);
1643 else
1645 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1646 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1647 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1648 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1649 install_var_field (decl, true, 7, ctx);
1650 else
1651 install_var_field (decl, true, 3, ctx);
1652 if (gimple_omp_target_kind (ctx->stmt)
1653 == GF_OMP_TARGET_KIND_REGION)
1654 install_var_local (decl, ctx);
1657 else
1659 tree base = get_base_address (decl);
1660 tree nc = OMP_CLAUSE_CHAIN (c);
1661 if (DECL_P (base)
1662 && nc != NULL_TREE
1663 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1664 && OMP_CLAUSE_DECL (nc) == base
1665 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1666 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1668 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1669 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1671 else
1673 gcc_assert (!splay_tree_lookup (ctx->field_map,
1674 (splay_tree_key) decl));
1675 tree field
1676 = build_decl (OMP_CLAUSE_LOCATION (c),
1677 FIELD_DECL, NULL_TREE, ptr_type_node);
1678 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1679 insert_field_into_struct (ctx->record_type, field);
1680 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1681 (splay_tree_value) field);
1684 break;
1686 case OMP_CLAUSE_NOWAIT:
1687 case OMP_CLAUSE_ORDERED:
1688 case OMP_CLAUSE_COLLAPSE:
1689 case OMP_CLAUSE_UNTIED:
1690 case OMP_CLAUSE_MERGEABLE:
1691 case OMP_CLAUSE_PROC_BIND:
1692 case OMP_CLAUSE_SAFELEN:
1693 break;
1695 case OMP_CLAUSE_ALIGNED:
1696 decl = OMP_CLAUSE_DECL (c);
1697 if (is_global_var (decl)
1698 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1699 install_var_local (decl, ctx);
1700 break;
1702 default:
1703 gcc_unreachable ();
1707 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1709 switch (OMP_CLAUSE_CODE (c))
1711 case OMP_CLAUSE_LASTPRIVATE:
1712 /* Let the corresponding firstprivate clause create
1713 the variable. */
1714 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1715 scan_array_reductions = true;
1716 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1717 break;
1718 /* FALLTHRU */
1720 case OMP_CLAUSE_PRIVATE:
1721 case OMP_CLAUSE_FIRSTPRIVATE:
1722 case OMP_CLAUSE_REDUCTION:
1723 case OMP_CLAUSE_LINEAR:
1724 decl = OMP_CLAUSE_DECL (c);
1725 if (is_variable_sized (decl))
1726 install_var_local (decl, ctx);
1727 fixup_remapped_decl (decl, ctx,
1728 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1729 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1730 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1731 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1732 scan_array_reductions = true;
1733 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1734 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1735 scan_array_reductions = true;
1736 break;
1738 case OMP_CLAUSE_SHARED:
1739 /* Ignore shared directives in teams construct. */
1740 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1741 break;
1742 decl = OMP_CLAUSE_DECL (c);
1743 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1744 fixup_remapped_decl (decl, ctx, false);
1745 break;
1747 case OMP_CLAUSE_MAP:
1748 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1749 break;
1750 decl = OMP_CLAUSE_DECL (c);
1751 if (DECL_P (decl)
1752 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1753 && lookup_attribute ("omp declare target",
1754 DECL_ATTRIBUTES (decl)))
1755 break;
1756 if (DECL_P (decl))
1758 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1759 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1760 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1762 tree new_decl = lookup_decl (decl, ctx);
1763 TREE_TYPE (new_decl)
1764 = remap_type (TREE_TYPE (decl), &ctx->cb);
1766 else if (DECL_SIZE (decl)
1767 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1769 tree decl2 = DECL_VALUE_EXPR (decl);
1770 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1771 decl2 = TREE_OPERAND (decl2, 0);
1772 gcc_assert (DECL_P (decl2));
1773 fixup_remapped_decl (decl2, ctx, false);
1774 fixup_remapped_decl (decl, ctx, true);
1776 else
1777 fixup_remapped_decl (decl, ctx, false);
1779 break;
1781 case OMP_CLAUSE_COPYPRIVATE:
1782 case OMP_CLAUSE_COPYIN:
1783 case OMP_CLAUSE_DEFAULT:
1784 case OMP_CLAUSE_IF:
1785 case OMP_CLAUSE_NUM_THREADS:
1786 case OMP_CLAUSE_NUM_TEAMS:
1787 case OMP_CLAUSE_THREAD_LIMIT:
1788 case OMP_CLAUSE_DEVICE:
1789 case OMP_CLAUSE_SCHEDULE:
1790 case OMP_CLAUSE_DIST_SCHEDULE:
1791 case OMP_CLAUSE_NOWAIT:
1792 case OMP_CLAUSE_ORDERED:
1793 case OMP_CLAUSE_COLLAPSE:
1794 case OMP_CLAUSE_UNTIED:
1795 case OMP_CLAUSE_FINAL:
1796 case OMP_CLAUSE_MERGEABLE:
1797 case OMP_CLAUSE_PROC_BIND:
1798 case OMP_CLAUSE_SAFELEN:
1799 case OMP_CLAUSE_ALIGNED:
1800 case OMP_CLAUSE_DEPEND:
1801 case OMP_CLAUSE__LOOPTEMP_:
1802 case OMP_CLAUSE_TO:
1803 case OMP_CLAUSE_FROM:
1804 break;
1806 default:
1807 gcc_unreachable ();
1811 if (scan_array_reductions)
1812 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1813 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1814 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1816 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1817 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1819 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1820 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1821 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1822 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1823 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1824 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1827 /* Create a new name for omp child function. Returns an identifier. */
1829 static tree
1830 create_omp_child_function_name (bool task_copy)
1832 return (clone_function_name (current_function_decl,
1833 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1836 /* Build a decl for the omp child function. It'll not contain a body
1837 yet, just the bare decl. */
1839 static void
1840 create_omp_child_function (omp_context *ctx, bool task_copy)
1842 tree decl, type, name, t;
1844 name = create_omp_child_function_name (task_copy);
1845 if (task_copy)
1846 type = build_function_type_list (void_type_node, ptr_type_node,
1847 ptr_type_node, NULL_TREE);
1848 else
1849 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1851 decl = build_decl (gimple_location (ctx->stmt),
1852 FUNCTION_DECL, name, type);
1854 if (!task_copy)
1855 ctx->cb.dst_fn = decl;
1856 else
1857 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1859 TREE_STATIC (decl) = 1;
1860 TREE_USED (decl) = 1;
1861 DECL_ARTIFICIAL (decl) = 1;
1862 DECL_NAMELESS (decl) = 1;
1863 DECL_IGNORED_P (decl) = 0;
1864 TREE_PUBLIC (decl) = 0;
1865 DECL_UNINLINABLE (decl) = 1;
1866 DECL_EXTERNAL (decl) = 0;
1867 DECL_CONTEXT (decl) = NULL_TREE;
1868 DECL_INITIAL (decl) = make_node (BLOCK);
1869 bool target_p = false;
1870 if (lookup_attribute ("omp declare target",
1871 DECL_ATTRIBUTES (current_function_decl)))
1872 target_p = true;
1873 else
1875 omp_context *octx;
1876 for (octx = ctx; octx; octx = octx->outer)
1877 if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
1878 && gimple_omp_target_kind (octx->stmt)
1879 == GF_OMP_TARGET_KIND_REGION)
1881 target_p = true;
1882 break;
1885 if (target_p)
1886 DECL_ATTRIBUTES (decl)
1887 = tree_cons (get_identifier ("omp declare target"),
1888 NULL_TREE, DECL_ATTRIBUTES (decl));
1890 t = build_decl (DECL_SOURCE_LOCATION (decl),
1891 RESULT_DECL, NULL_TREE, void_type_node);
1892 DECL_ARTIFICIAL (t) = 1;
1893 DECL_IGNORED_P (t) = 1;
1894 DECL_CONTEXT (t) = decl;
1895 DECL_RESULT (decl) = t;
1897 t = build_decl (DECL_SOURCE_LOCATION (decl),
1898 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1899 DECL_ARTIFICIAL (t) = 1;
1900 DECL_NAMELESS (t) = 1;
1901 DECL_ARG_TYPE (t) = ptr_type_node;
1902 DECL_CONTEXT (t) = current_function_decl;
1903 TREE_USED (t) = 1;
1904 DECL_ARGUMENTS (decl) = t;
1905 if (!task_copy)
1906 ctx->receiver_decl = t;
1907 else
1909 t = build_decl (DECL_SOURCE_LOCATION (decl),
1910 PARM_DECL, get_identifier (".omp_data_o"),
1911 ptr_type_node);
1912 DECL_ARTIFICIAL (t) = 1;
1913 DECL_NAMELESS (t) = 1;
1914 DECL_ARG_TYPE (t) = ptr_type_node;
1915 DECL_CONTEXT (t) = current_function_decl;
1916 TREE_USED (t) = 1;
1917 TREE_ADDRESSABLE (t) = 1;
1918 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1919 DECL_ARGUMENTS (decl) = t;
1922 /* Allocate memory for the function structure. The call to
1923 allocate_struct_function clobbers CFUN, so we need to restore
1924 it afterward. */
1925 push_struct_function (decl);
1926 cfun->function_end_locus = gimple_location (ctx->stmt);
1927 pop_cfun ();
1930 /* Callback for walk_gimple_seq. Check if combined parallel
1931 contains gimple_omp_for_combined_into_p OMP_FOR. */
1933 static tree
1934 find_combined_for (gimple_stmt_iterator *gsi_p,
1935 bool *handled_ops_p,
1936 struct walk_stmt_info *wi)
1938 gimple stmt = gsi_stmt (*gsi_p);
1940 *handled_ops_p = true;
1941 switch (gimple_code (stmt))
1943 WALK_SUBSTMTS;
1945 case GIMPLE_OMP_FOR:
1946 if (gimple_omp_for_combined_into_p (stmt)
1947 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
1949 wi->info = stmt;
1950 return integer_zero_node;
1952 break;
1953 default:
1954 break;
1956 return NULL;
1959 /* Scan an OpenMP parallel directive. */
1961 static void
1962 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1964 omp_context *ctx;
1965 tree name;
1966 gimple stmt = gsi_stmt (*gsi);
1968 /* Ignore parallel directives with empty bodies, unless there
1969 are copyin clauses. */
1970 if (optimize > 0
1971 && empty_body_p (gimple_omp_body (stmt))
1972 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1973 OMP_CLAUSE_COPYIN) == NULL)
1975 gsi_replace (gsi, gimple_build_nop (), false);
1976 return;
1979 if (gimple_omp_parallel_combined_p (stmt))
1981 gimple for_stmt;
1982 struct walk_stmt_info wi;
1984 memset (&wi, 0, sizeof (wi));
1985 wi.val_only = true;
1986 walk_gimple_seq (gimple_omp_body (stmt),
1987 find_combined_for, NULL, &wi);
1988 for_stmt = (gimple) wi.info;
1989 if (for_stmt)
1991 struct omp_for_data fd;
1992 extract_omp_for_data (for_stmt, &fd, NULL);
1993 /* We need two temporaries with fd.loop.v type (istart/iend)
1994 and then (fd.collapse - 1) temporaries with the same
1995 type for count2 ... countN-1 vars if not constant. */
1996 size_t count = 2, i;
1997 tree type = fd.iter_type;
1998 if (fd.collapse > 1
1999 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2000 count += fd.collapse - 1;
2001 for (i = 0; i < count; i++)
2003 tree temp = create_tmp_var (type, NULL);
2004 tree c = build_omp_clause (UNKNOWN_LOCATION,
2005 OMP_CLAUSE__LOOPTEMP_);
2006 OMP_CLAUSE_DECL (c) = temp;
2007 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2008 gimple_omp_parallel_set_clauses (stmt, c);
2013 ctx = new_omp_context (stmt, outer_ctx);
2014 if (taskreg_nesting_level > 1)
2015 ctx->is_nested = true;
2016 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2017 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2018 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2019 name = create_tmp_var_name (".omp_data_s");
2020 name = build_decl (gimple_location (stmt),
2021 TYPE_DECL, name, ctx->record_type);
2022 DECL_ARTIFICIAL (name) = 1;
2023 DECL_NAMELESS (name) = 1;
2024 TYPE_NAME (ctx->record_type) = name;
2025 create_omp_child_function (ctx, false);
2026 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2028 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2029 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2031 if (TYPE_FIELDS (ctx->record_type) == NULL)
2032 ctx->record_type = ctx->receiver_decl = NULL;
2033 else
2035 layout_type (ctx->record_type);
2036 fixup_child_record_type (ctx);
2040 /* Scan an OpenMP task directive. */
2042 static void
2043 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2045 omp_context *ctx;
2046 tree name, t;
2047 gimple stmt = gsi_stmt (*gsi);
2048 location_t loc = gimple_location (stmt);
2050 /* Ignore task directives with empty bodies. */
2051 if (optimize > 0
2052 && empty_body_p (gimple_omp_body (stmt)))
2054 gsi_replace (gsi, gimple_build_nop (), false);
2055 return;
2058 ctx = new_omp_context (stmt, outer_ctx);
2059 if (taskreg_nesting_level > 1)
2060 ctx->is_nested = true;
2061 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2062 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2063 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2064 name = create_tmp_var_name (".omp_data_s");
2065 name = build_decl (gimple_location (stmt),
2066 TYPE_DECL, name, ctx->record_type);
2067 DECL_ARTIFICIAL (name) = 1;
2068 DECL_NAMELESS (name) = 1;
2069 TYPE_NAME (ctx->record_type) = name;
2070 create_omp_child_function (ctx, false);
2071 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2073 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2075 if (ctx->srecord_type)
2077 name = create_tmp_var_name (".omp_data_a");
2078 name = build_decl (gimple_location (stmt),
2079 TYPE_DECL, name, ctx->srecord_type);
2080 DECL_ARTIFICIAL (name) = 1;
2081 DECL_NAMELESS (name) = 1;
2082 TYPE_NAME (ctx->srecord_type) = name;
2083 create_omp_child_function (ctx, true);
2086 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2088 if (TYPE_FIELDS (ctx->record_type) == NULL)
2090 ctx->record_type = ctx->receiver_decl = NULL;
2091 t = build_int_cst (long_integer_type_node, 0);
2092 gimple_omp_task_set_arg_size (stmt, t);
2093 t = build_int_cst (long_integer_type_node, 1);
2094 gimple_omp_task_set_arg_align (stmt, t);
2096 else
2098 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2099 /* Move VLA fields to the end. */
2100 p = &TYPE_FIELDS (ctx->record_type);
2101 while (*p)
2102 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2103 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2105 *q = *p;
2106 *p = TREE_CHAIN (*p);
2107 TREE_CHAIN (*q) = NULL_TREE;
2108 q = &TREE_CHAIN (*q);
2110 else
2111 p = &DECL_CHAIN (*p);
2112 *p = vla_fields;
2113 layout_type (ctx->record_type);
2114 fixup_child_record_type (ctx);
2115 if (ctx->srecord_type)
2116 layout_type (ctx->srecord_type);
2117 t = fold_convert_loc (loc, long_integer_type_node,
2118 TYPE_SIZE_UNIT (ctx->record_type));
2119 gimple_omp_task_set_arg_size (stmt, t);
2120 t = build_int_cst (long_integer_type_node,
2121 TYPE_ALIGN_UNIT (ctx->record_type));
2122 gimple_omp_task_set_arg_align (stmt, t);
2127 /* Scan an OpenMP loop directive. */
2129 static void
2130 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2132 omp_context *ctx;
2133 size_t i;
2135 ctx = new_omp_context (stmt, outer_ctx);
2137 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2139 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2140 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2142 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2143 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2144 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2145 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2147 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2150 /* Scan an OpenMP sections directive. */
2152 static void
2153 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2155 omp_context *ctx;
2157 ctx = new_omp_context (stmt, outer_ctx);
2158 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2159 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2162 /* Scan an OpenMP single directive. */
2164 static void
2165 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2167 omp_context *ctx;
2168 tree name;
2170 ctx = new_omp_context (stmt, outer_ctx);
2171 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2172 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2173 name = create_tmp_var_name (".omp_copy_s");
2174 name = build_decl (gimple_location (stmt),
2175 TYPE_DECL, name, ctx->record_type);
2176 TYPE_NAME (ctx->record_type) = name;
2178 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2179 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2181 if (TYPE_FIELDS (ctx->record_type) == NULL)
2182 ctx->record_type = NULL;
2183 else
2184 layout_type (ctx->record_type);
2187 /* Scan an OpenMP target{, data, update} directive. */
2189 static void
2190 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2192 omp_context *ctx;
2193 tree name;
2194 int kind = gimple_omp_target_kind (stmt);
2196 ctx = new_omp_context (stmt, outer_ctx);
2197 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2198 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2199 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2200 name = create_tmp_var_name (".omp_data_t");
2201 name = build_decl (gimple_location (stmt),
2202 TYPE_DECL, name, ctx->record_type);
2203 DECL_ARTIFICIAL (name) = 1;
2204 DECL_NAMELESS (name) = 1;
2205 TYPE_NAME (ctx->record_type) = name;
2206 if (kind == GF_OMP_TARGET_KIND_REGION)
2208 create_omp_child_function (ctx, false);
2209 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2212 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2213 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2215 if (TYPE_FIELDS (ctx->record_type) == NULL)
2216 ctx->record_type = ctx->receiver_decl = NULL;
2217 else
2219 TYPE_FIELDS (ctx->record_type)
2220 = nreverse (TYPE_FIELDS (ctx->record_type));
2221 #ifdef ENABLE_CHECKING
2222 tree field;
2223 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2224 for (field = TYPE_FIELDS (ctx->record_type);
2225 field;
2226 field = DECL_CHAIN (field))
2227 gcc_assert (DECL_ALIGN (field) == align);
2228 #endif
2229 layout_type (ctx->record_type);
2230 if (kind == GF_OMP_TARGET_KIND_REGION)
2231 fixup_child_record_type (ctx);
2235 /* Scan an OpenMP teams directive. */
2237 static void
2238 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2240 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2241 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2242 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2245 /* Check OpenMP nesting restrictions. */
2246 static bool
2247 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2249 if (ctx != NULL)
2251 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2252 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2254 error_at (gimple_location (stmt),
2255 "OpenMP constructs may not be nested inside simd region");
2256 return false;
2258 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2260 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2261 || (gimple_omp_for_kind (stmt)
2262 != GF_OMP_FOR_KIND_DISTRIBUTE))
2263 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2265 error_at (gimple_location (stmt),
2266 "only distribute or parallel constructs are allowed to "
2267 "be closely nested inside teams construct");
2268 return false;
2272 switch (gimple_code (stmt))
2274 case GIMPLE_OMP_FOR:
2275 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2276 return true;
2277 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2279 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2281 error_at (gimple_location (stmt),
2282 "distribute construct must be closely nested inside "
2283 "teams construct");
2284 return false;
2286 return true;
2288 /* FALLTHRU */
2289 case GIMPLE_CALL:
2290 if (is_gimple_call (stmt)
2291 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2292 == BUILT_IN_GOMP_CANCEL
2293 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2294 == BUILT_IN_GOMP_CANCELLATION_POINT))
2296 const char *bad = NULL;
2297 const char *kind = NULL;
2298 if (ctx == NULL)
2300 error_at (gimple_location (stmt), "orphaned %qs construct",
2301 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2302 == BUILT_IN_GOMP_CANCEL
2303 ? "#pragma omp cancel"
2304 : "#pragma omp cancellation point");
2305 return false;
2307 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2308 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2309 : 0)
2311 case 1:
2312 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2313 bad = "#pragma omp parallel";
2314 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2315 == BUILT_IN_GOMP_CANCEL
2316 && !integer_zerop (gimple_call_arg (stmt, 1)))
2317 ctx->cancellable = true;
2318 kind = "parallel";
2319 break;
2320 case 2:
2321 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2322 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2323 bad = "#pragma omp for";
2324 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2325 == BUILT_IN_GOMP_CANCEL
2326 && !integer_zerop (gimple_call_arg (stmt, 1)))
2328 ctx->cancellable = true;
2329 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2330 OMP_CLAUSE_NOWAIT))
2331 warning_at (gimple_location (stmt), 0,
2332 "%<#pragma omp cancel for%> inside "
2333 "%<nowait%> for construct");
2334 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2335 OMP_CLAUSE_ORDERED))
2336 warning_at (gimple_location (stmt), 0,
2337 "%<#pragma omp cancel for%> inside "
2338 "%<ordered%> for construct");
2340 kind = "for";
2341 break;
2342 case 4:
2343 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2344 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2345 bad = "#pragma omp sections";
2346 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2347 == BUILT_IN_GOMP_CANCEL
2348 && !integer_zerop (gimple_call_arg (stmt, 1)))
2350 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2352 ctx->cancellable = true;
2353 if (find_omp_clause (gimple_omp_sections_clauses
2354 (ctx->stmt),
2355 OMP_CLAUSE_NOWAIT))
2356 warning_at (gimple_location (stmt), 0,
2357 "%<#pragma omp cancel sections%> inside "
2358 "%<nowait%> sections construct");
2360 else
2362 gcc_assert (ctx->outer
2363 && gimple_code (ctx->outer->stmt)
2364 == GIMPLE_OMP_SECTIONS);
2365 ctx->outer->cancellable = true;
2366 if (find_omp_clause (gimple_omp_sections_clauses
2367 (ctx->outer->stmt),
2368 OMP_CLAUSE_NOWAIT))
2369 warning_at (gimple_location (stmt), 0,
2370 "%<#pragma omp cancel sections%> inside "
2371 "%<nowait%> sections construct");
2374 kind = "sections";
2375 break;
2376 case 8:
2377 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2378 bad = "#pragma omp task";
2379 else
2380 ctx->cancellable = true;
2381 kind = "taskgroup";
2382 break;
2383 default:
2384 error_at (gimple_location (stmt), "invalid arguments");
2385 return false;
2387 if (bad)
2389 error_at (gimple_location (stmt),
2390 "%<%s %s%> construct not closely nested inside of %qs",
2391 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2392 == BUILT_IN_GOMP_CANCEL
2393 ? "#pragma omp cancel"
2394 : "#pragma omp cancellation point", kind, bad);
2395 return false;
2398 /* FALLTHRU */
2399 case GIMPLE_OMP_SECTIONS:
2400 case GIMPLE_OMP_SINGLE:
2401 for (; ctx != NULL; ctx = ctx->outer)
2402 switch (gimple_code (ctx->stmt))
2404 case GIMPLE_OMP_FOR:
2405 case GIMPLE_OMP_SECTIONS:
2406 case GIMPLE_OMP_SINGLE:
2407 case GIMPLE_OMP_ORDERED:
2408 case GIMPLE_OMP_MASTER:
2409 case GIMPLE_OMP_TASK:
2410 case GIMPLE_OMP_CRITICAL:
2411 if (is_gimple_call (stmt))
2413 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2414 != BUILT_IN_GOMP_BARRIER)
2415 return true;
2416 error_at (gimple_location (stmt),
2417 "barrier region may not be closely nested inside "
2418 "of work-sharing, critical, ordered, master or "
2419 "explicit task region");
2420 return false;
2422 error_at (gimple_location (stmt),
2423 "work-sharing region may not be closely nested inside "
2424 "of work-sharing, critical, ordered, master or explicit "
2425 "task region");
2426 return false;
2427 case GIMPLE_OMP_PARALLEL:
2428 return true;
2429 default:
2430 break;
2432 break;
2433 case GIMPLE_OMP_MASTER:
2434 for (; ctx != NULL; ctx = ctx->outer)
2435 switch (gimple_code (ctx->stmt))
2437 case GIMPLE_OMP_FOR:
2438 case GIMPLE_OMP_SECTIONS:
2439 case GIMPLE_OMP_SINGLE:
2440 case GIMPLE_OMP_TASK:
2441 error_at (gimple_location (stmt),
2442 "master region may not be closely nested inside "
2443 "of work-sharing or explicit task region");
2444 return false;
2445 case GIMPLE_OMP_PARALLEL:
2446 return true;
2447 default:
2448 break;
2450 break;
2451 case GIMPLE_OMP_ORDERED:
2452 for (; ctx != NULL; ctx = ctx->outer)
2453 switch (gimple_code (ctx->stmt))
2455 case GIMPLE_OMP_CRITICAL:
2456 case GIMPLE_OMP_TASK:
2457 error_at (gimple_location (stmt),
2458 "ordered region may not be closely nested inside "
2459 "of critical or explicit task region");
2460 return false;
2461 case GIMPLE_OMP_FOR:
2462 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2463 OMP_CLAUSE_ORDERED) == NULL)
2465 error_at (gimple_location (stmt),
2466 "ordered region must be closely nested inside "
2467 "a loop region with an ordered clause");
2468 return false;
2470 return true;
2471 case GIMPLE_OMP_PARALLEL:
2472 error_at (gimple_location (stmt),
2473 "ordered region must be closely nested inside "
2474 "a loop region with an ordered clause");
2475 return false;
2476 default:
2477 break;
2479 break;
2480 case GIMPLE_OMP_CRITICAL:
2481 for (; ctx != NULL; ctx = ctx->outer)
2482 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2483 && (gimple_omp_critical_name (stmt)
2484 == gimple_omp_critical_name (ctx->stmt)))
2486 error_at (gimple_location (stmt),
2487 "critical region may not be nested inside a critical "
2488 "region with the same name");
2489 return false;
2491 break;
2492 case GIMPLE_OMP_TEAMS:
2493 if (ctx == NULL
2494 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2495 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2497 error_at (gimple_location (stmt),
2498 "teams construct not closely nested inside of target "
2499 "region");
2500 return false;
2502 break;
2503 default:
2504 break;
2506 return true;
2510 /* Helper function scan_omp.
2512 Callback for walk_tree or operators in walk_gimple_stmt used to
2513 scan for OpenMP directives in TP. */
2515 static tree
2516 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2518 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2519 omp_context *ctx = (omp_context *) wi->info;
2520 tree t = *tp;
2522 switch (TREE_CODE (t))
2524 case VAR_DECL:
2525 case PARM_DECL:
2526 case LABEL_DECL:
2527 case RESULT_DECL:
2528 if (ctx)
2529 *tp = remap_decl (t, &ctx->cb);
2530 break;
2532 default:
2533 if (ctx && TYPE_P (t))
2534 *tp = remap_type (t, &ctx->cb);
2535 else if (!DECL_P (t))
2537 *walk_subtrees = 1;
2538 if (ctx)
2540 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2541 if (tem != TREE_TYPE (t))
2543 if (TREE_CODE (t) == INTEGER_CST)
2544 *tp = wide_int_to_tree (tem, t);
2545 else
2546 TREE_TYPE (t) = tem;
2550 break;
2553 return NULL_TREE;
2556 /* Return true if FNDECL is a setjmp or a longjmp. */
2558 static bool
2559 setjmp_or_longjmp_p (const_tree fndecl)
2561 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2562 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2563 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2564 return true;
2566 tree declname = DECL_NAME (fndecl);
2567 if (!declname)
2568 return false;
2569 const char *name = IDENTIFIER_POINTER (declname);
2570 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2574 /* Helper function for scan_omp.
2576 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2577 the current statement in GSI. */
2579 static tree
2580 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2581 struct walk_stmt_info *wi)
2583 gimple stmt = gsi_stmt (*gsi);
2584 omp_context *ctx = (omp_context *) wi->info;
2586 if (gimple_has_location (stmt))
2587 input_location = gimple_location (stmt);
2589 /* Check the OpenMP nesting restrictions. */
2590 bool remove = false;
2591 if (is_gimple_omp (stmt))
2592 remove = !check_omp_nesting_restrictions (stmt, ctx);
2593 else if (is_gimple_call (stmt))
2595 tree fndecl = gimple_call_fndecl (stmt);
2596 if (fndecl)
2598 if (setjmp_or_longjmp_p (fndecl)
2599 && ctx
2600 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2601 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2603 remove = true;
2604 error_at (gimple_location (stmt),
2605 "setjmp/longjmp inside simd construct");
2607 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2608 switch (DECL_FUNCTION_CODE (fndecl))
2610 case BUILT_IN_GOMP_BARRIER:
2611 case BUILT_IN_GOMP_CANCEL:
2612 case BUILT_IN_GOMP_CANCELLATION_POINT:
2613 case BUILT_IN_GOMP_TASKYIELD:
2614 case BUILT_IN_GOMP_TASKWAIT:
2615 case BUILT_IN_GOMP_TASKGROUP_START:
2616 case BUILT_IN_GOMP_TASKGROUP_END:
2617 remove = !check_omp_nesting_restrictions (stmt, ctx);
2618 break;
2619 default:
2620 break;
2624 if (remove)
2626 stmt = gimple_build_nop ();
2627 gsi_replace (gsi, stmt, false);
2630 *handled_ops_p = true;
2632 switch (gimple_code (stmt))
2634 case GIMPLE_OMP_PARALLEL:
2635 taskreg_nesting_level++;
2636 scan_omp_parallel (gsi, ctx);
2637 taskreg_nesting_level--;
2638 break;
2640 case GIMPLE_OMP_TASK:
2641 taskreg_nesting_level++;
2642 scan_omp_task (gsi, ctx);
2643 taskreg_nesting_level--;
2644 break;
2646 case GIMPLE_OMP_FOR:
2647 scan_omp_for (stmt, ctx);
2648 break;
2650 case GIMPLE_OMP_SECTIONS:
2651 scan_omp_sections (stmt, ctx);
2652 break;
2654 case GIMPLE_OMP_SINGLE:
2655 scan_omp_single (stmt, ctx);
2656 break;
2658 case GIMPLE_OMP_SECTION:
2659 case GIMPLE_OMP_MASTER:
2660 case GIMPLE_OMP_TASKGROUP:
2661 case GIMPLE_OMP_ORDERED:
2662 case GIMPLE_OMP_CRITICAL:
2663 ctx = new_omp_context (stmt, ctx);
2664 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2665 break;
2667 case GIMPLE_OMP_TARGET:
2668 scan_omp_target (stmt, ctx);
2669 break;
2671 case GIMPLE_OMP_TEAMS:
2672 scan_omp_teams (stmt, ctx);
2673 break;
2675 case GIMPLE_BIND:
2677 tree var;
2679 *handled_ops_p = false;
2680 if (ctx)
2681 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2682 insert_decl_map (&ctx->cb, var, var);
2684 break;
2685 default:
2686 *handled_ops_p = false;
2687 break;
2690 return NULL_TREE;
2694 /* Scan all the statements starting at the current statement. CTX
2695 contains context information about the OpenMP directives and
2696 clauses found during the scan. */
2698 static void
2699 scan_omp (gimple_seq *body_p, omp_context *ctx)
2701 location_t saved_location;
2702 struct walk_stmt_info wi;
2704 memset (&wi, 0, sizeof (wi));
2705 wi.info = ctx;
2706 wi.want_locations = true;
2708 saved_location = input_location;
2709 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2710 input_location = saved_location;
2713 /* Re-gimplification and code generation routines. */
2715 /* Build a call to GOMP_barrier. */
2717 static gimple
2718 build_omp_barrier (tree lhs)
2720 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2721 : BUILT_IN_GOMP_BARRIER);
2722 gimple g = gimple_build_call (fndecl, 0);
2723 if (lhs)
2724 gimple_call_set_lhs (g, lhs);
2725 return g;
2728 /* If a context was created for STMT when it was scanned, return it. */
2730 static omp_context *
2731 maybe_lookup_ctx (gimple stmt)
2733 splay_tree_node n;
2734 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2735 return n ? (omp_context *) n->value : NULL;
2739 /* Find the mapping for DECL in CTX or the immediately enclosing
2740 context that has a mapping for DECL.
2742 If CTX is a nested parallel directive, we may have to use the decl
2743 mappings created in CTX's parent context. Suppose that we have the
2744 following parallel nesting (variable UIDs showed for clarity):
2746 iD.1562 = 0;
2747 #omp parallel shared(iD.1562) -> outer parallel
2748 iD.1562 = iD.1562 + 1;
2750 #omp parallel shared (iD.1562) -> inner parallel
2751 iD.1562 = iD.1562 - 1;
2753 Each parallel structure will create a distinct .omp_data_s structure
2754 for copying iD.1562 in/out of the directive:
2756 outer parallel .omp_data_s.1.i -> iD.1562
2757 inner parallel .omp_data_s.2.i -> iD.1562
2759 A shared variable mapping will produce a copy-out operation before
2760 the parallel directive and a copy-in operation after it. So, in
2761 this case we would have:
2763 iD.1562 = 0;
2764 .omp_data_o.1.i = iD.1562;
2765 #omp parallel shared(iD.1562) -> outer parallel
2766 .omp_data_i.1 = &.omp_data_o.1
2767 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2769 .omp_data_o.2.i = iD.1562; -> **
2770 #omp parallel shared(iD.1562) -> inner parallel
2771 .omp_data_i.2 = &.omp_data_o.2
2772 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2775 ** This is a problem. The symbol iD.1562 cannot be referenced
2776 inside the body of the outer parallel region. But since we are
2777 emitting this copy operation while expanding the inner parallel
2778 directive, we need to access the CTX structure of the outer
2779 parallel directive to get the correct mapping:
2781 .omp_data_o.2.i = .omp_data_i.1->i
2783 Since there may be other workshare or parallel directives enclosing
2784 the parallel directive, it may be necessary to walk up the context
2785 parent chain. This is not a problem in general because nested
2786 parallelism happens only rarely. */
2788 static tree
2789 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2791 tree t;
2792 omp_context *up;
2794 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2795 t = maybe_lookup_decl (decl, up);
2797 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2799 return t ? t : decl;
2803 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2804 in outer contexts. */
2806 static tree
2807 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2809 tree t = NULL;
2810 omp_context *up;
2812 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2813 t = maybe_lookup_decl (decl, up);
2815 return t ? t : decl;
2819 /* Construct the initialization value for reduction CLAUSE. */
2821 tree
2822 omp_reduction_init (tree clause, tree type)
2824 location_t loc = OMP_CLAUSE_LOCATION (clause);
2825 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2827 case PLUS_EXPR:
2828 case MINUS_EXPR:
2829 case BIT_IOR_EXPR:
2830 case BIT_XOR_EXPR:
2831 case TRUTH_OR_EXPR:
2832 case TRUTH_ORIF_EXPR:
2833 case TRUTH_XOR_EXPR:
2834 case NE_EXPR:
2835 return build_zero_cst (type);
2837 case MULT_EXPR:
2838 case TRUTH_AND_EXPR:
2839 case TRUTH_ANDIF_EXPR:
2840 case EQ_EXPR:
2841 return fold_convert_loc (loc, type, integer_one_node);
2843 case BIT_AND_EXPR:
2844 return fold_convert_loc (loc, type, integer_minus_one_node);
2846 case MAX_EXPR:
2847 if (SCALAR_FLOAT_TYPE_P (type))
2849 REAL_VALUE_TYPE max, min;
2850 if (HONOR_INFINITIES (TYPE_MODE (type)))
2852 real_inf (&max);
2853 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2855 else
2856 real_maxval (&min, 1, TYPE_MODE (type));
2857 return build_real (type, min);
2859 else
2861 gcc_assert (INTEGRAL_TYPE_P (type));
2862 return TYPE_MIN_VALUE (type);
2865 case MIN_EXPR:
2866 if (SCALAR_FLOAT_TYPE_P (type))
2868 REAL_VALUE_TYPE max;
2869 if (HONOR_INFINITIES (TYPE_MODE (type)))
2870 real_inf (&max);
2871 else
2872 real_maxval (&max, 0, TYPE_MODE (type));
2873 return build_real (type, max);
2875 else
2877 gcc_assert (INTEGRAL_TYPE_P (type));
2878 return TYPE_MAX_VALUE (type);
2881 default:
2882 gcc_unreachable ();
2886 /* Return alignment to be assumed for var in CLAUSE, which should be
2887 OMP_CLAUSE_ALIGNED. */
2889 static tree
2890 omp_clause_aligned_alignment (tree clause)
2892 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
2893 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
2895 /* Otherwise return implementation defined alignment. */
2896 unsigned int al = 1;
2897 enum machine_mode mode, vmode;
2898 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2899 if (vs)
2900 vs = 1 << floor_log2 (vs);
2901 static enum mode_class classes[]
2902 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
2903 for (int i = 0; i < 4; i += 2)
2904 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
2905 mode != VOIDmode;
2906 mode = GET_MODE_WIDER_MODE (mode))
2908 vmode = targetm.vectorize.preferred_simd_mode (mode);
2909 if (GET_MODE_CLASS (vmode) != classes[i + 1])
2910 continue;
2911 while (vs
2912 && GET_MODE_SIZE (vmode) < vs
2913 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
2914 vmode = GET_MODE_2XWIDER_MODE (vmode);
2916 tree type = lang_hooks.types.type_for_mode (mode, 1);
2917 if (type == NULL_TREE || TYPE_MODE (type) != mode)
2918 continue;
2919 type = build_vector_type (type, GET_MODE_SIZE (vmode)
2920 / GET_MODE_SIZE (mode));
2921 if (TYPE_MODE (type) != vmode)
2922 continue;
2923 if (TYPE_ALIGN_UNIT (type) > al)
2924 al = TYPE_ALIGN_UNIT (type);
2926 return build_int_cst (integer_type_node, al);
2929 /* Return maximum possible vectorization factor for the target. */
2931 static int
2932 omp_max_vf (void)
2934 if (!optimize
2935 || optimize_debug
2936 || !flag_tree_loop_optimize
2937 || (!flag_tree_loop_vectorize
2938 && (global_options_set.x_flag_tree_loop_vectorize
2939 || global_options_set.x_flag_tree_vectorize)))
2940 return 1;
2942 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2943 if (vs)
2945 vs = 1 << floor_log2 (vs);
2946 return vs;
2948 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
2949 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
2950 return GET_MODE_NUNITS (vqimode);
2951 return 1;
2954 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2955 privatization. */
2957 static bool
2958 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
2959 tree &idx, tree &lane, tree &ivar, tree &lvar)
2961 if (max_vf == 0)
2963 max_vf = omp_max_vf ();
2964 if (max_vf > 1)
2966 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2967 OMP_CLAUSE_SAFELEN);
2968 if (c
2969 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
2970 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
2972 if (max_vf > 1)
2974 idx = create_tmp_var (unsigned_type_node, NULL);
2975 lane = create_tmp_var (unsigned_type_node, NULL);
2978 if (max_vf == 1)
2979 return false;
2981 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
2982 tree avar = create_tmp_var_raw (atype, NULL);
2983 if (TREE_ADDRESSABLE (new_var))
2984 TREE_ADDRESSABLE (avar) = 1;
2985 DECL_ATTRIBUTES (avar)
2986 = tree_cons (get_identifier ("omp simd array"), NULL,
2987 DECL_ATTRIBUTES (avar));
2988 gimple_add_tmp_var (avar);
2989 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
2990 NULL_TREE, NULL_TREE);
2991 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
2992 NULL_TREE, NULL_TREE);
2993 if (DECL_P (new_var))
2995 SET_DECL_VALUE_EXPR (new_var, lvar);
2996 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2998 return true;
3001 /* Helper function of lower_rec_input_clauses. For a reference
3002 in simd reduction, add an underlying variable it will reference. */
3004 static void
3005 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3007 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3008 if (TREE_CONSTANT (z))
3010 const char *name = NULL;
3011 if (DECL_NAME (new_vard))
3012 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3014 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3015 gimple_add_tmp_var (z);
3016 TREE_ADDRESSABLE (z) = 1;
3017 z = build_fold_addr_expr_loc (loc, z);
3018 gimplify_assign (new_vard, z, ilist);
3022 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3023 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3024 private variables. Initialization statements go in ILIST, while calls
3025 to destructors go in DLIST. */
3027 static void
3028 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3029 omp_context *ctx, struct omp_for_data *fd)
3031 tree c, dtor, copyin_seq, x, ptr;
3032 bool copyin_by_ref = false;
3033 bool lastprivate_firstprivate = false;
3034 bool reduction_omp_orig_ref = false;
3035 int pass;
3036 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3037 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3038 int max_vf = 0;
3039 tree lane = NULL_TREE, idx = NULL_TREE;
3040 tree ivar = NULL_TREE, lvar = NULL_TREE;
3041 gimple_seq llist[2] = { NULL, NULL };
3043 copyin_seq = NULL;
3045 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3046 with data sharing clauses referencing variable sized vars. That
3047 is unnecessarily hard to support and very unlikely to result in
3048 vectorized code anyway. */
3049 if (is_simd)
3050 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3051 switch (OMP_CLAUSE_CODE (c))
3053 case OMP_CLAUSE_REDUCTION:
3054 case OMP_CLAUSE_PRIVATE:
3055 case OMP_CLAUSE_FIRSTPRIVATE:
3056 case OMP_CLAUSE_LASTPRIVATE:
3057 case OMP_CLAUSE_LINEAR:
3058 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3059 max_vf = 1;
3060 break;
3061 default:
3062 continue;
3065 /* Do all the fixed sized types in the first pass, and the variable sized
3066 types in the second pass. This makes sure that the scalar arguments to
3067 the variable sized types are processed before we use them in the
3068 variable sized operations. */
3069 for (pass = 0; pass < 2; ++pass)
3071 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3073 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3074 tree var, new_var;
3075 bool by_ref;
3076 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3078 switch (c_kind)
3080 case OMP_CLAUSE_PRIVATE:
3081 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3082 continue;
3083 break;
3084 case OMP_CLAUSE_SHARED:
3085 /* Ignore shared directives in teams construct. */
3086 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3087 continue;
3088 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3090 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3091 continue;
3093 case OMP_CLAUSE_FIRSTPRIVATE:
3094 case OMP_CLAUSE_COPYIN:
3095 case OMP_CLAUSE_LINEAR:
3096 break;
3097 case OMP_CLAUSE_REDUCTION:
3098 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3099 reduction_omp_orig_ref = true;
3100 break;
3101 case OMP_CLAUSE__LOOPTEMP_:
3102 /* Handle _looptemp_ clauses only on parallel. */
3103 if (fd)
3104 continue;
3105 break;
3106 case OMP_CLAUSE_LASTPRIVATE:
3107 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3109 lastprivate_firstprivate = true;
3110 if (pass != 0)
3111 continue;
3113 break;
3114 case OMP_CLAUSE_ALIGNED:
3115 if (pass == 0)
3116 continue;
3117 var = OMP_CLAUSE_DECL (c);
3118 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3119 && !is_global_var (var))
3121 new_var = maybe_lookup_decl (var, ctx);
3122 if (new_var == NULL_TREE)
3123 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3124 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3125 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3126 omp_clause_aligned_alignment (c));
3127 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3128 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3129 gimplify_and_add (x, ilist);
3131 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3132 && is_global_var (var))
3134 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3135 new_var = lookup_decl (var, ctx);
3136 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3137 t = build_fold_addr_expr_loc (clause_loc, t);
3138 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3139 t = build_call_expr_loc (clause_loc, t2, 2, t,
3140 omp_clause_aligned_alignment (c));
3141 t = fold_convert_loc (clause_loc, ptype, t);
3142 x = create_tmp_var (ptype, NULL);
3143 t = build2 (MODIFY_EXPR, ptype, x, t);
3144 gimplify_and_add (t, ilist);
3145 t = build_simple_mem_ref_loc (clause_loc, x);
3146 SET_DECL_VALUE_EXPR (new_var, t);
3147 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3149 continue;
3150 default:
3151 continue;
3154 new_var = var = OMP_CLAUSE_DECL (c);
3155 if (c_kind != OMP_CLAUSE_COPYIN)
3156 new_var = lookup_decl (var, ctx);
3158 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3160 if (pass != 0)
3161 continue;
3163 else if (is_variable_sized (var))
3165 /* For variable sized types, we need to allocate the
3166 actual storage here. Call alloca and store the
3167 result in the pointer decl that we created elsewhere. */
3168 if (pass == 0)
3169 continue;
3171 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3173 gimple stmt;
3174 tree tmp, atmp;
3176 ptr = DECL_VALUE_EXPR (new_var);
3177 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3178 ptr = TREE_OPERAND (ptr, 0);
3179 gcc_assert (DECL_P (ptr));
3180 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3182 /* void *tmp = __builtin_alloca */
3183 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3184 stmt = gimple_build_call (atmp, 1, x);
3185 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3186 gimple_add_tmp_var (tmp);
3187 gimple_call_set_lhs (stmt, tmp);
3189 gimple_seq_add_stmt (ilist, stmt);
3191 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3192 gimplify_assign (ptr, x, ilist);
3195 else if (is_reference (var))
3197 /* For references that are being privatized for Fortran,
3198 allocate new backing storage for the new pointer
3199 variable. This allows us to avoid changing all the
3200 code that expects a pointer to something that expects
3201 a direct variable. */
3202 if (pass == 0)
3203 continue;
3205 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3206 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3208 x = build_receiver_ref (var, false, ctx);
3209 x = build_fold_addr_expr_loc (clause_loc, x);
3211 else if (TREE_CONSTANT (x))
3213 /* For reduction in SIMD loop, defer adding the
3214 initialization of the reference, because if we decide
3215 to use SIMD array for it, the initilization could cause
3216 expansion ICE. */
3217 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3218 x = NULL_TREE;
3219 else
3221 const char *name = NULL;
3222 if (DECL_NAME (var))
3223 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3225 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3226 name);
3227 gimple_add_tmp_var (x);
3228 TREE_ADDRESSABLE (x) = 1;
3229 x = build_fold_addr_expr_loc (clause_loc, x);
3232 else
3234 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3235 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3238 if (x)
3240 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3241 gimplify_assign (new_var, x, ilist);
3244 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3246 else if (c_kind == OMP_CLAUSE_REDUCTION
3247 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3249 if (pass == 0)
3250 continue;
3252 else if (pass != 0)
3253 continue;
3255 switch (OMP_CLAUSE_CODE (c))
3257 case OMP_CLAUSE_SHARED:
3258 /* Ignore shared directives in teams construct. */
3259 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3260 continue;
3261 /* Shared global vars are just accessed directly. */
3262 if (is_global_var (new_var))
3263 break;
3264 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3265 needs to be delayed until after fixup_child_record_type so
3266 that we get the correct type during the dereference. */
3267 by_ref = use_pointer_for_field (var, ctx);
3268 x = build_receiver_ref (var, by_ref, ctx);
3269 SET_DECL_VALUE_EXPR (new_var, x);
3270 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3272 /* ??? If VAR is not passed by reference, and the variable
3273 hasn't been initialized yet, then we'll get a warning for
3274 the store into the omp_data_s structure. Ideally, we'd be
3275 able to notice this and not store anything at all, but
3276 we're generating code too early. Suppress the warning. */
3277 if (!by_ref)
3278 TREE_NO_WARNING (var) = 1;
3279 break;
3281 case OMP_CLAUSE_LASTPRIVATE:
3282 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3283 break;
3284 /* FALLTHRU */
3286 case OMP_CLAUSE_PRIVATE:
3287 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3288 x = build_outer_var_ref (var, ctx);
3289 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3291 if (is_task_ctx (ctx))
3292 x = build_receiver_ref (var, false, ctx);
3293 else
3294 x = build_outer_var_ref (var, ctx);
3296 else
3297 x = NULL;
3298 do_private:
3299 tree nx;
3300 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3301 if (is_simd)
3303 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3304 if ((TREE_ADDRESSABLE (new_var) || nx || y
3305 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3306 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3307 idx, lane, ivar, lvar))
3309 if (nx)
3310 x = lang_hooks.decls.omp_clause_default_ctor
3311 (c, unshare_expr (ivar), x);
3312 if (nx && x)
3313 gimplify_and_add (x, &llist[0]);
3314 if (y)
3316 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3317 if (y)
3319 gimple_seq tseq = NULL;
3321 dtor = y;
3322 gimplify_stmt (&dtor, &tseq);
3323 gimple_seq_add_seq (&llist[1], tseq);
3326 break;
3329 if (nx)
3330 gimplify_and_add (nx, ilist);
3331 /* FALLTHRU */
3333 do_dtor:
3334 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3335 if (x)
3337 gimple_seq tseq = NULL;
3339 dtor = x;
3340 gimplify_stmt (&dtor, &tseq);
3341 gimple_seq_add_seq (dlist, tseq);
3343 break;
3345 case OMP_CLAUSE_LINEAR:
3346 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3347 goto do_firstprivate;
3348 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3349 x = NULL;
3350 else
3351 x = build_outer_var_ref (var, ctx);
3352 goto do_private;
3354 case OMP_CLAUSE_FIRSTPRIVATE:
3355 if (is_task_ctx (ctx))
3357 if (is_reference (var) || is_variable_sized (var))
3358 goto do_dtor;
3359 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3360 ctx))
3361 || use_pointer_for_field (var, NULL))
3363 x = build_receiver_ref (var, false, ctx);
3364 SET_DECL_VALUE_EXPR (new_var, x);
3365 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3366 goto do_dtor;
3369 do_firstprivate:
3370 x = build_outer_var_ref (var, ctx);
3371 if (is_simd)
3373 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3374 && gimple_omp_for_combined_into_p (ctx->stmt))
3376 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3377 ? sizetype : TREE_TYPE (x);
3378 tree t = fold_convert (stept,
3379 OMP_CLAUSE_LINEAR_STEP (c));
3380 tree c = find_omp_clause (clauses,
3381 OMP_CLAUSE__LOOPTEMP_);
3382 gcc_assert (c);
3383 tree l = OMP_CLAUSE_DECL (c);
3384 if (fd->collapse == 1)
3386 tree n1 = fd->loop.n1;
3387 tree step = fd->loop.step;
3388 tree itype = TREE_TYPE (l);
3389 if (POINTER_TYPE_P (itype))
3390 itype = signed_type_for (itype);
3391 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3392 if (TYPE_UNSIGNED (itype)
3393 && fd->loop.cond_code == GT_EXPR)
3394 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3395 fold_build1 (NEGATE_EXPR,
3396 itype, l),
3397 fold_build1 (NEGATE_EXPR,
3398 itype, step));
3399 else
3400 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3402 t = fold_build2 (MULT_EXPR, stept,
3403 fold_convert (stept, l), t);
3404 if (POINTER_TYPE_P (TREE_TYPE (x)))
3405 x = fold_build2 (POINTER_PLUS_EXPR,
3406 TREE_TYPE (x), x, t);
3407 else
3408 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3411 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3412 || TREE_ADDRESSABLE (new_var))
3413 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3414 idx, lane, ivar, lvar))
3416 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3418 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3419 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3420 gimplify_and_add (x, ilist);
3421 gimple_stmt_iterator gsi
3422 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3423 gimple g
3424 = gimple_build_assign (unshare_expr (lvar), iv);
3425 gsi_insert_before_without_update (&gsi, g,
3426 GSI_SAME_STMT);
3427 tree stept = POINTER_TYPE_P (TREE_TYPE (iv))
3428 ? sizetype : TREE_TYPE (iv);
3429 tree t = fold_convert (stept,
3430 OMP_CLAUSE_LINEAR_STEP (c));
3431 enum tree_code code = PLUS_EXPR;
3432 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3433 code = POINTER_PLUS_EXPR;
3434 g = gimple_build_assign_with_ops (code, iv, iv, t);
3435 gsi_insert_before_without_update (&gsi, g,
3436 GSI_SAME_STMT);
3437 break;
3439 x = lang_hooks.decls.omp_clause_copy_ctor
3440 (c, unshare_expr (ivar), x);
3441 gimplify_and_add (x, &llist[0]);
3442 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3443 if (x)
3445 gimple_seq tseq = NULL;
3447 dtor = x;
3448 gimplify_stmt (&dtor, &tseq);
3449 gimple_seq_add_seq (&llist[1], tseq);
3451 break;
3454 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3455 gimplify_and_add (x, ilist);
3456 goto do_dtor;
3458 case OMP_CLAUSE__LOOPTEMP_:
3459 gcc_assert (is_parallel_ctx (ctx));
3460 x = build_outer_var_ref (var, ctx);
3461 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3462 gimplify_and_add (x, ilist);
3463 break;
3465 case OMP_CLAUSE_COPYIN:
3466 by_ref = use_pointer_for_field (var, NULL);
3467 x = build_receiver_ref (var, by_ref, ctx);
3468 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3469 append_to_statement_list (x, &copyin_seq);
3470 copyin_by_ref |= by_ref;
3471 break;
3473 case OMP_CLAUSE_REDUCTION:
3474 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3476 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3477 gimple tseq;
3478 x = build_outer_var_ref (var, ctx);
3480 if (is_reference (var)
3481 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3482 TREE_TYPE (x)))
3483 x = build_fold_addr_expr_loc (clause_loc, x);
3484 SET_DECL_VALUE_EXPR (placeholder, x);
3485 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3486 tree new_vard = new_var;
3487 if (is_reference (var))
3489 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3490 new_vard = TREE_OPERAND (new_var, 0);
3491 gcc_assert (DECL_P (new_vard));
3493 if (is_simd
3494 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3495 idx, lane, ivar, lvar))
3497 if (new_vard == new_var)
3499 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3500 SET_DECL_VALUE_EXPR (new_var, ivar);
3502 else
3504 SET_DECL_VALUE_EXPR (new_vard,
3505 build_fold_addr_expr (ivar));
3506 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3508 x = lang_hooks.decls.omp_clause_default_ctor
3509 (c, unshare_expr (ivar),
3510 build_outer_var_ref (var, ctx));
3511 if (x)
3512 gimplify_and_add (x, &llist[0]);
3513 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3515 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3516 lower_omp (&tseq, ctx);
3517 gimple_seq_add_seq (&llist[0], tseq);
3519 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3520 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3521 lower_omp (&tseq, ctx);
3522 gimple_seq_add_seq (&llist[1], tseq);
3523 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3524 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3525 if (new_vard == new_var)
3526 SET_DECL_VALUE_EXPR (new_var, lvar);
3527 else
3528 SET_DECL_VALUE_EXPR (new_vard,
3529 build_fold_addr_expr (lvar));
3530 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3531 if (x)
3533 tseq = NULL;
3534 dtor = x;
3535 gimplify_stmt (&dtor, &tseq);
3536 gimple_seq_add_seq (&llist[1], tseq);
3538 break;
3540 /* If this is a reference to constant size reduction var
3541 with placeholder, we haven't emitted the initializer
3542 for it because it is undesirable if SIMD arrays are used.
3543 But if they aren't used, we need to emit the deferred
3544 initialization now. */
3545 else if (is_reference (var) && is_simd)
3546 handle_simd_reference (clause_loc, new_vard, ilist);
3547 x = lang_hooks.decls.omp_clause_default_ctor
3548 (c, new_var, unshare_expr (x));
3549 if (x)
3550 gimplify_and_add (x, ilist);
3551 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3553 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3554 lower_omp (&tseq, ctx);
3555 gimple_seq_add_seq (ilist, tseq);
3557 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3558 if (is_simd)
3560 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3561 lower_omp (&tseq, ctx);
3562 gimple_seq_add_seq (dlist, tseq);
3563 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3565 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3566 goto do_dtor;
3568 else
3570 x = omp_reduction_init (c, TREE_TYPE (new_var));
3571 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3572 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3574 /* reduction(-:var) sums up the partial results, so it
3575 acts identically to reduction(+:var). */
3576 if (code == MINUS_EXPR)
3577 code = PLUS_EXPR;
3579 tree new_vard = new_var;
3580 if (is_simd && is_reference (var))
3582 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3583 new_vard = TREE_OPERAND (new_var, 0);
3584 gcc_assert (DECL_P (new_vard));
3586 if (is_simd
3587 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3588 idx, lane, ivar, lvar))
3590 tree ref = build_outer_var_ref (var, ctx);
3592 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3594 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3595 ref = build_outer_var_ref (var, ctx);
3596 gimplify_assign (ref, x, &llist[1]);
3598 if (new_vard != new_var)
3600 SET_DECL_VALUE_EXPR (new_vard,
3601 build_fold_addr_expr (lvar));
3602 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3605 else
3607 if (is_reference (var) && is_simd)
3608 handle_simd_reference (clause_loc, new_vard, ilist);
3609 gimplify_assign (new_var, x, ilist);
3610 if (is_simd)
3612 tree ref = build_outer_var_ref (var, ctx);
3614 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3615 ref = build_outer_var_ref (var, ctx);
3616 gimplify_assign (ref, x, dlist);
3620 break;
3622 default:
3623 gcc_unreachable ();
3628 if (lane)
3630 tree uid = create_tmp_var (ptr_type_node, "simduid");
3631 /* Don't want uninit warnings on simduid, it is always uninitialized,
3632 but we use it not for the value, but for the DECL_UID only. */
3633 TREE_NO_WARNING (uid) = 1;
3634 gimple g
3635 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3636 gimple_call_set_lhs (g, lane);
3637 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3638 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3639 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3640 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3641 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3642 gimple_omp_for_set_clauses (ctx->stmt, c);
3643 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3644 build_int_cst (unsigned_type_node, 0),
3645 NULL_TREE);
3646 gimple_seq_add_stmt (ilist, g);
3647 for (int i = 0; i < 2; i++)
3648 if (llist[i])
3650 tree vf = create_tmp_var (unsigned_type_node, NULL);
3651 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3652 gimple_call_set_lhs (g, vf);
3653 gimple_seq *seq = i == 0 ? ilist : dlist;
3654 gimple_seq_add_stmt (seq, g);
3655 tree t = build_int_cst (unsigned_type_node, 0);
3656 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3657 gimple_seq_add_stmt (seq, g);
3658 tree body = create_artificial_label (UNKNOWN_LOCATION);
3659 tree header = create_artificial_label (UNKNOWN_LOCATION);
3660 tree end = create_artificial_label (UNKNOWN_LOCATION);
3661 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3662 gimple_seq_add_stmt (seq, gimple_build_label (body));
3663 gimple_seq_add_seq (seq, llist[i]);
3664 t = build_int_cst (unsigned_type_node, 1);
3665 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3666 gimple_seq_add_stmt (seq, g);
3667 gimple_seq_add_stmt (seq, gimple_build_label (header));
3668 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3669 gimple_seq_add_stmt (seq, g);
3670 gimple_seq_add_stmt (seq, gimple_build_label (end));
3674 /* The copyin sequence is not to be executed by the main thread, since
3675 that would result in self-copies. Perhaps not visible to scalars,
3676 but it certainly is to C++ operator=. */
3677 if (copyin_seq)
3679 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3681 x = build2 (NE_EXPR, boolean_type_node, x,
3682 build_int_cst (TREE_TYPE (x), 0));
3683 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3684 gimplify_and_add (x, ilist);
3687 /* If any copyin variable is passed by reference, we must ensure the
3688 master thread doesn't modify it before it is copied over in all
3689 threads. Similarly for variables in both firstprivate and
3690 lastprivate clauses we need to ensure the lastprivate copying
3691 happens after firstprivate copying in all threads. And similarly
3692 for UDRs if initializer expression refers to omp_orig. */
3693 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3695 /* Don't add any barrier for #pragma omp simd or
3696 #pragma omp distribute. */
3697 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3698 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3699 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3702 /* If max_vf is non-zero, then we can use only a vectorization factor
3703 up to the max_vf we chose. So stick it into the safelen clause. */
3704 if (max_vf)
3706 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3707 OMP_CLAUSE_SAFELEN);
3708 if (c == NULL_TREE
3709 || compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3710 max_vf) == 1)
3712 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3713 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3714 max_vf);
3715 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3716 gimple_omp_for_set_clauses (ctx->stmt, c);
3722 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3723 both parallel and workshare constructs. PREDICATE may be NULL if it's
3724 always true. */
3726 static void
3727 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3728 omp_context *ctx)
3730 tree x, c, label = NULL, orig_clauses = clauses;
3731 bool par_clauses = false;
3732 tree simduid = NULL, lastlane = NULL;
3734 /* Early exit if there are no lastprivate or linear clauses. */
3735 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3736 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3737 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3738 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3739 break;
3740 if (clauses == NULL)
3742 /* If this was a workshare clause, see if it had been combined
3743 with its parallel. In that case, look for the clauses on the
3744 parallel statement itself. */
3745 if (is_parallel_ctx (ctx))
3746 return;
3748 ctx = ctx->outer;
3749 if (ctx == NULL || !is_parallel_ctx (ctx))
3750 return;
3752 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3753 OMP_CLAUSE_LASTPRIVATE);
3754 if (clauses == NULL)
3755 return;
3756 par_clauses = true;
3759 if (predicate)
3761 gimple stmt;
3762 tree label_true, arm1, arm2;
3764 label = create_artificial_label (UNKNOWN_LOCATION);
3765 label_true = create_artificial_label (UNKNOWN_LOCATION);
3766 arm1 = TREE_OPERAND (predicate, 0);
3767 arm2 = TREE_OPERAND (predicate, 1);
3768 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3769 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3770 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3771 label_true, label);
3772 gimple_seq_add_stmt (stmt_list, stmt);
3773 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3776 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3777 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3779 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3780 if (simduid)
3781 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3784 for (c = clauses; c ;)
3786 tree var, new_var;
3787 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3789 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3790 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3791 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3793 var = OMP_CLAUSE_DECL (c);
3794 new_var = lookup_decl (var, ctx);
3796 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3798 tree val = DECL_VALUE_EXPR (new_var);
3799 if (TREE_CODE (val) == ARRAY_REF
3800 && VAR_P (TREE_OPERAND (val, 0))
3801 && lookup_attribute ("omp simd array",
3802 DECL_ATTRIBUTES (TREE_OPERAND (val,
3803 0))))
3805 if (lastlane == NULL)
3807 lastlane = create_tmp_var (unsigned_type_node, NULL);
3808 gimple g
3809 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
3810 2, simduid,
3811 TREE_OPERAND (val, 1));
3812 gimple_call_set_lhs (g, lastlane);
3813 gimple_seq_add_stmt (stmt_list, g);
3815 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
3816 TREE_OPERAND (val, 0), lastlane,
3817 NULL_TREE, NULL_TREE);
3821 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3822 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
3824 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
3825 gimple_seq_add_seq (stmt_list,
3826 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3827 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
3829 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3830 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
3832 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
3833 gimple_seq_add_seq (stmt_list,
3834 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
3835 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
3838 x = build_outer_var_ref (var, ctx);
3839 if (is_reference (var))
3840 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3841 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
3842 gimplify_and_add (x, stmt_list);
3844 c = OMP_CLAUSE_CHAIN (c);
3845 if (c == NULL && !par_clauses)
3847 /* If this was a workshare clause, see if it had been combined
3848 with its parallel. In that case, continue looking for the
3849 clauses also on the parallel statement itself. */
3850 if (is_parallel_ctx (ctx))
3851 break;
3853 ctx = ctx->outer;
3854 if (ctx == NULL || !is_parallel_ctx (ctx))
3855 break;
3857 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3858 OMP_CLAUSE_LASTPRIVATE);
3859 par_clauses = true;
3863 if (label)
3864 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
3868 /* Generate code to implement the REDUCTION clauses. */
3870 static void
3871 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
3873 gimple_seq sub_seq = NULL;
3874 gimple stmt;
3875 tree x, c;
3876 int count = 0;
3878 /* SIMD reductions are handled in lower_rec_input_clauses. */
3879 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3880 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3881 return;
3883 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3884 update in that case, otherwise use a lock. */
3885 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
3886 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
3888 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3890 /* Never use OMP_ATOMIC for array reductions or UDRs. */
3891 count = -1;
3892 break;
3894 count++;
3897 if (count == 0)
3898 return;
3900 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3902 tree var, ref, new_var;
3903 enum tree_code code;
3904 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3906 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
3907 continue;
3909 var = OMP_CLAUSE_DECL (c);
3910 new_var = lookup_decl (var, ctx);
3911 if (is_reference (var))
3912 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3913 ref = build_outer_var_ref (var, ctx);
3914 code = OMP_CLAUSE_REDUCTION_CODE (c);
3916 /* reduction(-:var) sums up the partial results, so it acts
3917 identically to reduction(+:var). */
3918 if (code == MINUS_EXPR)
3919 code = PLUS_EXPR;
3921 if (count == 1)
3923 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
3925 addr = save_expr (addr);
3926 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
3927 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
3928 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
3929 gimplify_and_add (x, stmt_seqp);
3930 return;
3933 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3935 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3937 if (is_reference (var)
3938 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3939 TREE_TYPE (ref)))
3940 ref = build_fold_addr_expr_loc (clause_loc, ref);
3941 SET_DECL_VALUE_EXPR (placeholder, ref);
3942 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3943 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
3944 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
3945 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3946 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
3948 else
3950 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3951 ref = build_outer_var_ref (var, ctx);
3952 gimplify_assign (ref, x, &sub_seq);
3956 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
3958 gimple_seq_add_stmt (stmt_seqp, stmt);
3960 gimple_seq_add_seq (stmt_seqp, sub_seq);
3962 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
3964 gimple_seq_add_stmt (stmt_seqp, stmt);
3968 /* Generate code to implement the COPYPRIVATE clauses. */
3970 static void
3971 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
3972 omp_context *ctx)
3974 tree c;
3976 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3978 tree var, new_var, ref, x;
3979 bool by_ref;
3980 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3982 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
3983 continue;
3985 var = OMP_CLAUSE_DECL (c);
3986 by_ref = use_pointer_for_field (var, NULL);
3988 ref = build_sender_ref (var, ctx);
3989 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
3990 if (by_ref)
3992 x = build_fold_addr_expr_loc (clause_loc, new_var);
3993 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
3995 gimplify_assign (ref, x, slist);
3997 ref = build_receiver_ref (var, false, ctx);
3998 if (by_ref)
4000 ref = fold_convert_loc (clause_loc,
4001 build_pointer_type (TREE_TYPE (new_var)),
4002 ref);
4003 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4005 if (is_reference (var))
4007 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4008 ref = build_simple_mem_ref_loc (clause_loc, ref);
4009 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4011 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4012 gimplify_and_add (x, rlist);
4017 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4018 and REDUCTION from the sender (aka parent) side. */
4020 static void
4021 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4022 omp_context *ctx)
4024 tree c;
4026 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4028 tree val, ref, x, var;
4029 bool by_ref, do_in = false, do_out = false;
4030 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4032 switch (OMP_CLAUSE_CODE (c))
4034 case OMP_CLAUSE_PRIVATE:
4035 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4036 break;
4037 continue;
4038 case OMP_CLAUSE_FIRSTPRIVATE:
4039 case OMP_CLAUSE_COPYIN:
4040 case OMP_CLAUSE_LASTPRIVATE:
4041 case OMP_CLAUSE_REDUCTION:
4042 case OMP_CLAUSE__LOOPTEMP_:
4043 break;
4044 default:
4045 continue;
4048 val = OMP_CLAUSE_DECL (c);
4049 var = lookup_decl_in_outer_ctx (val, ctx);
4051 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4052 && is_global_var (var))
4053 continue;
4054 if (is_variable_sized (val))
4055 continue;
4056 by_ref = use_pointer_for_field (val, NULL);
4058 switch (OMP_CLAUSE_CODE (c))
4060 case OMP_CLAUSE_PRIVATE:
4061 case OMP_CLAUSE_FIRSTPRIVATE:
4062 case OMP_CLAUSE_COPYIN:
4063 case OMP_CLAUSE__LOOPTEMP_:
4064 do_in = true;
4065 break;
4067 case OMP_CLAUSE_LASTPRIVATE:
4068 if (by_ref || is_reference (val))
4070 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4071 continue;
4072 do_in = true;
4074 else
4076 do_out = true;
4077 if (lang_hooks.decls.omp_private_outer_ref (val))
4078 do_in = true;
4080 break;
4082 case OMP_CLAUSE_REDUCTION:
4083 do_in = true;
4084 do_out = !(by_ref || is_reference (val));
4085 break;
4087 default:
4088 gcc_unreachable ();
4091 if (do_in)
4093 ref = build_sender_ref (val, ctx);
4094 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4095 gimplify_assign (ref, x, ilist);
4096 if (is_task_ctx (ctx))
4097 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4100 if (do_out)
4102 ref = build_sender_ref (val, ctx);
4103 gimplify_assign (var, ref, olist);
4108 /* Generate code to implement SHARED from the sender (aka parent)
4109 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4110 list things that got automatically shared. */
4112 static void
4113 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4115 tree var, ovar, nvar, f, x, record_type;
4117 if (ctx->record_type == NULL)
4118 return;
4120 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4121 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4123 ovar = DECL_ABSTRACT_ORIGIN (f);
4124 nvar = maybe_lookup_decl (ovar, ctx);
4125 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4126 continue;
4128 /* If CTX is a nested parallel directive. Find the immediately
4129 enclosing parallel or workshare construct that contains a
4130 mapping for OVAR. */
4131 var = lookup_decl_in_outer_ctx (ovar, ctx);
4133 if (use_pointer_for_field (ovar, ctx))
4135 x = build_sender_ref (ovar, ctx);
4136 var = build_fold_addr_expr (var);
4137 gimplify_assign (x, var, ilist);
4139 else
4141 x = build_sender_ref (ovar, ctx);
4142 gimplify_assign (x, var, ilist);
4144 if (!TREE_READONLY (var)
4145 /* We don't need to receive a new reference to a result
4146 or parm decl. In fact we may not store to it as we will
4147 invalidate any pending RSO and generate wrong gimple
4148 during inlining. */
4149 && !((TREE_CODE (var) == RESULT_DECL
4150 || TREE_CODE (var) == PARM_DECL)
4151 && DECL_BY_REFERENCE (var)))
4153 x = build_sender_ref (ovar, ctx);
4154 gimplify_assign (var, x, olist);
4161 /* A convenience function to build an empty GIMPLE_COND with just the
4162 condition. */
4164 static gimple
4165 gimple_build_cond_empty (tree cond)
4167 enum tree_code pred_code;
4168 tree lhs, rhs;
4170 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4171 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4175 /* Build the function calls to GOMP_parallel_start etc to actually
4176 generate the parallel operation. REGION is the parallel region
4177 being expanded. BB is the block where to insert the code. WS_ARGS
4178 will be set if this is a call to a combined parallel+workshare
4179 construct, it contains the list of additional arguments needed by
4180 the workshare construct. */
4182 static void
4183 expand_parallel_call (struct omp_region *region, basic_block bb,
4184 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4186 tree t, t1, t2, val, cond, c, clauses, flags;
4187 gimple_stmt_iterator gsi;
4188 gimple stmt;
4189 enum built_in_function start_ix;
4190 int start_ix2;
4191 location_t clause_loc;
4192 vec<tree, va_gc> *args;
4194 clauses = gimple_omp_parallel_clauses (entry_stmt);
4196 /* Determine what flavor of GOMP_parallel we will be
4197 emitting. */
4198 start_ix = BUILT_IN_GOMP_PARALLEL;
4199 if (is_combined_parallel (region))
4201 switch (region->inner->type)
4203 case GIMPLE_OMP_FOR:
4204 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4205 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4206 + (region->inner->sched_kind
4207 == OMP_CLAUSE_SCHEDULE_RUNTIME
4208 ? 3 : region->inner->sched_kind));
4209 start_ix = (enum built_in_function)start_ix2;
4210 break;
4211 case GIMPLE_OMP_SECTIONS:
4212 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4213 break;
4214 default:
4215 gcc_unreachable ();
4219 /* By default, the value of NUM_THREADS is zero (selected at run time)
4220 and there is no conditional. */
4221 cond = NULL_TREE;
4222 val = build_int_cst (unsigned_type_node, 0);
4223 flags = build_int_cst (unsigned_type_node, 0);
4225 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4226 if (c)
4227 cond = OMP_CLAUSE_IF_EXPR (c);
4229 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4230 if (c)
4232 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4233 clause_loc = OMP_CLAUSE_LOCATION (c);
4235 else
4236 clause_loc = gimple_location (entry_stmt);
4238 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4239 if (c)
4240 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4242 /* Ensure 'val' is of the correct type. */
4243 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4245 /* If we found the clause 'if (cond)', build either
4246 (cond != 0) or (cond ? val : 1u). */
4247 if (cond)
4249 cond = gimple_boolify (cond);
4251 if (integer_zerop (val))
4252 val = fold_build2_loc (clause_loc,
4253 EQ_EXPR, unsigned_type_node, cond,
4254 build_int_cst (TREE_TYPE (cond), 0));
4255 else
4257 basic_block cond_bb, then_bb, else_bb;
4258 edge e, e_then, e_else;
4259 tree tmp_then, tmp_else, tmp_join, tmp_var;
4261 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4262 if (gimple_in_ssa_p (cfun))
4264 tmp_then = make_ssa_name (tmp_var, NULL);
4265 tmp_else = make_ssa_name (tmp_var, NULL);
4266 tmp_join = make_ssa_name (tmp_var, NULL);
4268 else
4270 tmp_then = tmp_var;
4271 tmp_else = tmp_var;
4272 tmp_join = tmp_var;
4275 e = split_block (bb, NULL);
4276 cond_bb = e->src;
4277 bb = e->dest;
4278 remove_edge (e);
4280 then_bb = create_empty_bb (cond_bb);
4281 else_bb = create_empty_bb (then_bb);
4282 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4283 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4285 stmt = gimple_build_cond_empty (cond);
4286 gsi = gsi_start_bb (cond_bb);
4287 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4289 gsi = gsi_start_bb (then_bb);
4290 stmt = gimple_build_assign (tmp_then, val);
4291 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4293 gsi = gsi_start_bb (else_bb);
4294 stmt = gimple_build_assign
4295 (tmp_else, build_int_cst (unsigned_type_node, 1));
4296 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4298 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4299 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4300 if (current_loops)
4302 add_bb_to_loop (then_bb, cond_bb->loop_father);
4303 add_bb_to_loop (else_bb, cond_bb->loop_father);
4305 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4306 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4308 if (gimple_in_ssa_p (cfun))
4310 gimple phi = create_phi_node (tmp_join, bb);
4311 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4312 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4315 val = tmp_join;
4318 gsi = gsi_start_bb (bb);
4319 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4320 false, GSI_CONTINUE_LINKING);
4323 gsi = gsi_last_bb (bb);
4324 t = gimple_omp_parallel_data_arg (entry_stmt);
4325 if (t == NULL)
4326 t1 = null_pointer_node;
4327 else
4328 t1 = build_fold_addr_expr (t);
4329 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4331 vec_alloc (args, 4 + vec_safe_length (ws_args));
4332 args->quick_push (t2);
4333 args->quick_push (t1);
4334 args->quick_push (val);
4335 if (ws_args)
4336 args->splice (*ws_args);
4337 args->quick_push (flags);
4339 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4340 builtin_decl_explicit (start_ix), args);
4342 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4343 false, GSI_CONTINUE_LINKING);
4347 /* Build the function call to GOMP_task to actually
4348 generate the task operation. BB is the block where to insert the code. */
4350 static void
4351 expand_task_call (basic_block bb, gimple entry_stmt)
4353 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4354 gimple_stmt_iterator gsi;
4355 location_t loc = gimple_location (entry_stmt);
4357 clauses = gimple_omp_task_clauses (entry_stmt);
4359 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4360 if (c)
4361 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4362 else
4363 cond = boolean_true_node;
4365 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4366 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4367 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4368 flags = build_int_cst (unsigned_type_node,
4369 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4371 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4372 if (c)
4374 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4375 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4376 build_int_cst (unsigned_type_node, 2),
4377 build_int_cst (unsigned_type_node, 0));
4378 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4380 if (depend)
4381 depend = OMP_CLAUSE_DECL (depend);
4382 else
4383 depend = build_int_cst (ptr_type_node, 0);
4385 gsi = gsi_last_bb (bb);
4386 t = gimple_omp_task_data_arg (entry_stmt);
4387 if (t == NULL)
4388 t2 = null_pointer_node;
4389 else
4390 t2 = build_fold_addr_expr_loc (loc, t);
4391 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4392 t = gimple_omp_task_copy_fn (entry_stmt);
4393 if (t == NULL)
4394 t3 = null_pointer_node;
4395 else
4396 t3 = build_fold_addr_expr_loc (loc, t);
4398 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4399 8, t1, t2, t3,
4400 gimple_omp_task_arg_size (entry_stmt),
4401 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4402 depend);
4404 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4405 false, GSI_CONTINUE_LINKING);
4409 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4410 catch handler and return it. This prevents programs from violating the
4411 structured block semantics with throws. */
4413 static gimple_seq
4414 maybe_catch_exception (gimple_seq body)
4416 gimple g;
4417 tree decl;
4419 if (!flag_exceptions)
4420 return body;
4422 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4423 decl = lang_hooks.eh_protect_cleanup_actions ();
4424 else
4425 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4427 g = gimple_build_eh_must_not_throw (decl);
4428 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4429 GIMPLE_TRY_CATCH);
4431 return gimple_seq_alloc_with_stmt (g);
4434 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4436 static tree
4437 vec2chain (vec<tree, va_gc> *v)
4439 tree chain = NULL_TREE, t;
4440 unsigned ix;
4442 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4444 DECL_CHAIN (t) = chain;
4445 chain = t;
4448 return chain;
4452 /* Remove barriers in REGION->EXIT's block. Note that this is only
4453 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4454 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4455 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4456 removed. */
4458 static void
4459 remove_exit_barrier (struct omp_region *region)
4461 gimple_stmt_iterator gsi;
4462 basic_block exit_bb;
4463 edge_iterator ei;
4464 edge e;
4465 gimple stmt;
4466 int any_addressable_vars = -1;
4468 exit_bb = region->exit;
4470 /* If the parallel region doesn't return, we don't have REGION->EXIT
4471 block at all. */
4472 if (! exit_bb)
4473 return;
4475 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4476 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4477 statements that can appear in between are extremely limited -- no
4478 memory operations at all. Here, we allow nothing at all, so the
4479 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4480 gsi = gsi_last_bb (exit_bb);
4481 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4482 gsi_prev (&gsi);
4483 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4484 return;
4486 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4488 gsi = gsi_last_bb (e->src);
4489 if (gsi_end_p (gsi))
4490 continue;
4491 stmt = gsi_stmt (gsi);
4492 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4493 && !gimple_omp_return_nowait_p (stmt))
4495 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4496 in many cases. If there could be tasks queued, the barrier
4497 might be needed to let the tasks run before some local
4498 variable of the parallel that the task uses as shared
4499 runs out of scope. The task can be spawned either
4500 from within current function (this would be easy to check)
4501 or from some function it calls and gets passed an address
4502 of such a variable. */
4503 if (any_addressable_vars < 0)
4505 gimple parallel_stmt = last_stmt (region->entry);
4506 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4507 tree local_decls, block, decl;
4508 unsigned ix;
4510 any_addressable_vars = 0;
4511 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4512 if (TREE_ADDRESSABLE (decl))
4514 any_addressable_vars = 1;
4515 break;
4517 for (block = gimple_block (stmt);
4518 !any_addressable_vars
4519 && block
4520 && TREE_CODE (block) == BLOCK;
4521 block = BLOCK_SUPERCONTEXT (block))
4523 for (local_decls = BLOCK_VARS (block);
4524 local_decls;
4525 local_decls = DECL_CHAIN (local_decls))
4526 if (TREE_ADDRESSABLE (local_decls))
4528 any_addressable_vars = 1;
4529 break;
4531 if (block == gimple_block (parallel_stmt))
4532 break;
4535 if (!any_addressable_vars)
4536 gimple_omp_return_set_nowait (stmt);
4541 static void
4542 remove_exit_barriers (struct omp_region *region)
4544 if (region->type == GIMPLE_OMP_PARALLEL)
4545 remove_exit_barrier (region);
4547 if (region->inner)
4549 region = region->inner;
4550 remove_exit_barriers (region);
4551 while (region->next)
4553 region = region->next;
4554 remove_exit_barriers (region);
4559 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4560 calls. These can't be declared as const functions, but
4561 within one parallel body they are constant, so they can be
4562 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4563 which are declared const. Similarly for task body, except
4564 that in untied task omp_get_thread_num () can change at any task
4565 scheduling point. */
4567 static void
4568 optimize_omp_library_calls (gimple entry_stmt)
4570 basic_block bb;
4571 gimple_stmt_iterator gsi;
4572 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4573 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4574 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4575 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4576 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4577 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4578 OMP_CLAUSE_UNTIED) != NULL);
4580 FOR_EACH_BB_FN (bb, cfun)
4581 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4583 gimple call = gsi_stmt (gsi);
4584 tree decl;
4586 if (is_gimple_call (call)
4587 && (decl = gimple_call_fndecl (call))
4588 && DECL_EXTERNAL (decl)
4589 && TREE_PUBLIC (decl)
4590 && DECL_INITIAL (decl) == NULL)
4592 tree built_in;
4594 if (DECL_NAME (decl) == thr_num_id)
4596 /* In #pragma omp task untied omp_get_thread_num () can change
4597 during the execution of the task region. */
4598 if (untied_task)
4599 continue;
4600 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4602 else if (DECL_NAME (decl) == num_thr_id)
4603 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4604 else
4605 continue;
4607 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4608 || gimple_call_num_args (call) != 0)
4609 continue;
4611 if (flag_exceptions && !TREE_NOTHROW (decl))
4612 continue;
4614 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4615 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4616 TREE_TYPE (TREE_TYPE (built_in))))
4617 continue;
4619 gimple_call_set_fndecl (call, built_in);
4624 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4625 regimplified. */
4627 static tree
4628 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4630 tree t = *tp;
4632 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4633 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4634 return t;
4636 if (TREE_CODE (t) == ADDR_EXPR)
4637 recompute_tree_invariant_for_addr_expr (t);
4639 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4640 return NULL_TREE;
4643 /* Prepend TO = FROM assignment before *GSI_P. */
4645 static void
4646 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4648 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4649 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4650 true, GSI_SAME_STMT);
4651 gimple stmt = gimple_build_assign (to, from);
4652 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4653 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4654 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4656 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4657 gimple_regimplify_operands (stmt, &gsi);
4661 /* Expand the OpenMP parallel or task directive starting at REGION. */
4663 static void
4664 expand_omp_taskreg (struct omp_region *region)
4666 basic_block entry_bb, exit_bb, new_bb;
4667 struct function *child_cfun;
4668 tree child_fn, block, t;
4669 gimple_stmt_iterator gsi;
4670 gimple entry_stmt, stmt;
4671 edge e;
4672 vec<tree, va_gc> *ws_args;
4674 entry_stmt = last_stmt (region->entry);
4675 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4676 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4678 entry_bb = region->entry;
4679 exit_bb = region->exit;
4681 if (is_combined_parallel (region))
4682 ws_args = region->ws_args;
4683 else
4684 ws_args = NULL;
4686 if (child_cfun->cfg)
4688 /* Due to inlining, it may happen that we have already outlined
4689 the region, in which case all we need to do is make the
4690 sub-graph unreachable and emit the parallel call. */
4691 edge entry_succ_e, exit_succ_e;
4693 entry_succ_e = single_succ_edge (entry_bb);
4695 gsi = gsi_last_bb (entry_bb);
4696 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4697 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4698 gsi_remove (&gsi, true);
4700 new_bb = entry_bb;
4701 if (exit_bb)
4703 exit_succ_e = single_succ_edge (exit_bb);
4704 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4706 remove_edge_and_dominated_blocks (entry_succ_e);
4708 else
4710 unsigned srcidx, dstidx, num;
4712 /* If the parallel region needs data sent from the parent
4713 function, then the very first statement (except possible
4714 tree profile counter updates) of the parallel body
4715 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4716 &.OMP_DATA_O is passed as an argument to the child function,
4717 we need to replace it with the argument as seen by the child
4718 function.
4720 In most cases, this will end up being the identity assignment
4721 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4722 a function call that has been inlined, the original PARM_DECL
4723 .OMP_DATA_I may have been converted into a different local
4724 variable. In which case, we need to keep the assignment. */
4725 if (gimple_omp_taskreg_data_arg (entry_stmt))
4727 basic_block entry_succ_bb = single_succ (entry_bb);
4728 tree arg, narg;
4729 gimple parcopy_stmt = NULL;
4731 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4733 gimple stmt;
4735 gcc_assert (!gsi_end_p (gsi));
4736 stmt = gsi_stmt (gsi);
4737 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4738 continue;
4740 if (gimple_num_ops (stmt) == 2)
4742 tree arg = gimple_assign_rhs1 (stmt);
4744 /* We're ignore the subcode because we're
4745 effectively doing a STRIP_NOPS. */
4747 if (TREE_CODE (arg) == ADDR_EXPR
4748 && TREE_OPERAND (arg, 0)
4749 == gimple_omp_taskreg_data_arg (entry_stmt))
4751 parcopy_stmt = stmt;
4752 break;
4757 gcc_assert (parcopy_stmt != NULL);
4758 arg = DECL_ARGUMENTS (child_fn);
4760 if (!gimple_in_ssa_p (cfun))
4762 if (gimple_assign_lhs (parcopy_stmt) == arg)
4763 gsi_remove (&gsi, true);
4764 else
4766 /* ?? Is setting the subcode really necessary ?? */
4767 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
4768 gimple_assign_set_rhs1 (parcopy_stmt, arg);
4771 else
4773 /* If we are in ssa form, we must load the value from the default
4774 definition of the argument. That should not be defined now,
4775 since the argument is not used uninitialized. */
4776 gcc_assert (ssa_default_def (cfun, arg) == NULL);
4777 narg = make_ssa_name (arg, gimple_build_nop ());
4778 set_ssa_default_def (cfun, arg, narg);
4779 /* ?? Is setting the subcode really necessary ?? */
4780 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
4781 gimple_assign_set_rhs1 (parcopy_stmt, narg);
4782 update_stmt (parcopy_stmt);
4786 /* Declare local variables needed in CHILD_CFUN. */
4787 block = DECL_INITIAL (child_fn);
4788 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4789 /* The gimplifier could record temporaries in parallel/task block
4790 rather than in containing function's local_decls chain,
4791 which would mean cgraph missed finalizing them. Do it now. */
4792 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4793 if (TREE_CODE (t) == VAR_DECL
4794 && TREE_STATIC (t)
4795 && !DECL_EXTERNAL (t))
4796 varpool_finalize_decl (t);
4797 DECL_SAVED_TREE (child_fn) = NULL;
4798 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4799 gimple_set_body (child_fn, NULL);
4800 TREE_USED (block) = 1;
4802 /* Reset DECL_CONTEXT on function arguments. */
4803 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
4804 DECL_CONTEXT (t) = child_fn;
4806 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
4807 so that it can be moved to the child function. */
4808 gsi = gsi_last_bb (entry_bb);
4809 stmt = gsi_stmt (gsi);
4810 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
4811 || gimple_code (stmt) == GIMPLE_OMP_TASK));
4812 gsi_remove (&gsi, true);
4813 e = split_block (entry_bb, stmt);
4814 entry_bb = e->dest;
4815 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4817 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4818 if (exit_bb)
4820 gsi = gsi_last_bb (exit_bb);
4821 gcc_assert (!gsi_end_p (gsi)
4822 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4823 stmt = gimple_build_return (NULL);
4824 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4825 gsi_remove (&gsi, true);
4828 /* Move the parallel region into CHILD_CFUN. */
4830 if (gimple_in_ssa_p (cfun))
4832 init_tree_ssa (child_cfun);
4833 init_ssa_operands (child_cfun);
4834 child_cfun->gimple_df->in_ssa_p = true;
4835 block = NULL_TREE;
4837 else
4838 block = gimple_block (entry_stmt);
4840 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
4841 if (exit_bb)
4842 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
4843 /* When the OMP expansion process cannot guarantee an up-to-date
4844 loop tree arrange for the child function to fixup loops. */
4845 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
4846 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
4848 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
4849 num = vec_safe_length (child_cfun->local_decls);
4850 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
4852 t = (*child_cfun->local_decls)[srcidx];
4853 if (DECL_CONTEXT (t) == cfun->decl)
4854 continue;
4855 if (srcidx != dstidx)
4856 (*child_cfun->local_decls)[dstidx] = t;
4857 dstidx++;
4859 if (dstidx != num)
4860 vec_safe_truncate (child_cfun->local_decls, dstidx);
4862 /* Inform the callgraph about the new function. */
4863 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
4864 cgraph_add_new_function (child_fn, true);
4866 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4867 fixed in a following pass. */
4868 push_cfun (child_cfun);
4869 if (optimize)
4870 optimize_omp_library_calls (entry_stmt);
4871 rebuild_cgraph_edges ();
4873 /* Some EH regions might become dead, see PR34608. If
4874 pass_cleanup_cfg isn't the first pass to happen with the
4875 new child, these dead EH edges might cause problems.
4876 Clean them up now. */
4877 if (flag_exceptions)
4879 basic_block bb;
4880 bool changed = false;
4882 FOR_EACH_BB_FN (bb, cfun)
4883 changed |= gimple_purge_dead_eh_edges (bb);
4884 if (changed)
4885 cleanup_tree_cfg ();
4887 if (gimple_in_ssa_p (cfun))
4888 update_ssa (TODO_update_ssa);
4889 pop_cfun ();
4892 /* Emit a library call to launch the children threads. */
4893 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
4894 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
4895 else
4896 expand_task_call (new_bb, entry_stmt);
4897 if (gimple_in_ssa_p (cfun))
4898 update_ssa (TODO_update_ssa_only_virtuals);
4902 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4903 of the combined collapse > 1 loop constructs, generate code like:
4904 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4905 if (cond3 is <)
4906 adj = STEP3 - 1;
4907 else
4908 adj = STEP3 + 1;
4909 count3 = (adj + N32 - N31) / STEP3;
4910 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4911 if (cond2 is <)
4912 adj = STEP2 - 1;
4913 else
4914 adj = STEP2 + 1;
4915 count2 = (adj + N22 - N21) / STEP2;
4916 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4917 if (cond1 is <)
4918 adj = STEP1 - 1;
4919 else
4920 adj = STEP1 + 1;
4921 count1 = (adj + N12 - N11) / STEP1;
4922 count = count1 * count2 * count3;
4923 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4924 count = 0;
4925 and set ZERO_ITER_BB to that bb. If this isn't the outermost
4926 of the combined loop constructs, just initialize COUNTS array
4927 from the _looptemp_ clauses. */
4929 /* NOTE: It *could* be better to moosh all of the BBs together,
4930 creating one larger BB with all the computation and the unexpected
4931 jump at the end. I.e.
4933 bool zero3, zero2, zero1, zero;
4935 zero3 = N32 c3 N31;
4936 count3 = (N32 - N31) /[cl] STEP3;
4937 zero2 = N22 c2 N21;
4938 count2 = (N22 - N21) /[cl] STEP2;
4939 zero1 = N12 c1 N11;
4940 count1 = (N12 - N11) /[cl] STEP1;
4941 zero = zero3 || zero2 || zero1;
4942 count = count1 * count2 * count3;
4943 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4945 After all, we expect the zero=false, and thus we expect to have to
4946 evaluate all of the comparison expressions, so short-circuiting
4947 oughtn't be a win. Since the condition isn't protecting a
4948 denominator, we're not concerned about divide-by-zero, so we can
4949 fully evaluate count even if a numerator turned out to be wrong.
4951 It seems like putting this all together would create much better
4952 scheduling opportunities, and less pressure on the chip's branch
4953 predictor. */
4955 static void
4956 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4957 basic_block &entry_bb, tree *counts,
4958 basic_block &zero_iter_bb, int &first_zero_iter,
4959 basic_block &l2_dom_bb)
4961 tree t, type = TREE_TYPE (fd->loop.v);
4962 gimple stmt;
4963 edge e, ne;
4964 int i;
4966 /* Collapsed loops need work for expansion into SSA form. */
4967 gcc_assert (!gimple_in_ssa_p (cfun));
4969 if (gimple_omp_for_combined_into_p (fd->for_stmt)
4970 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
4972 /* First two _looptemp_ clauses are for istart/iend, counts[0]
4973 isn't supposed to be handled, as the inner loop doesn't
4974 use it. */
4975 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
4976 OMP_CLAUSE__LOOPTEMP_);
4977 gcc_assert (innerc);
4978 for (i = 0; i < fd->collapse; i++)
4980 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
4981 OMP_CLAUSE__LOOPTEMP_);
4982 gcc_assert (innerc);
4983 if (i)
4984 counts[i] = OMP_CLAUSE_DECL (innerc);
4985 else
4986 counts[0] = NULL_TREE;
4988 return;
4991 for (i = 0; i < fd->collapse; i++)
4993 tree itype = TREE_TYPE (fd->loops[i].v);
4995 if (SSA_VAR_P (fd->loop.n2)
4996 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
4997 fold_convert (itype, fd->loops[i].n1),
4998 fold_convert (itype, fd->loops[i].n2)))
4999 == NULL_TREE || !integer_onep (t)))
5001 tree n1, n2;
5002 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5003 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5004 true, GSI_SAME_STMT);
5005 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5006 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5007 true, GSI_SAME_STMT);
5008 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5009 NULL_TREE, NULL_TREE);
5010 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5011 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5012 expand_omp_regimplify_p, NULL, NULL)
5013 || walk_tree (gimple_cond_rhs_ptr (stmt),
5014 expand_omp_regimplify_p, NULL, NULL))
5016 *gsi = gsi_for_stmt (stmt);
5017 gimple_regimplify_operands (stmt, gsi);
5019 e = split_block (entry_bb, stmt);
5020 if (zero_iter_bb == NULL)
5022 first_zero_iter = i;
5023 zero_iter_bb = create_empty_bb (entry_bb);
5024 if (current_loops)
5025 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5026 *gsi = gsi_after_labels (zero_iter_bb);
5027 stmt = gimple_build_assign (fd->loop.n2,
5028 build_zero_cst (type));
5029 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5030 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5031 entry_bb);
5033 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5034 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5035 e->flags = EDGE_TRUE_VALUE;
5036 e->probability = REG_BR_PROB_BASE - ne->probability;
5037 if (l2_dom_bb == NULL)
5038 l2_dom_bb = entry_bb;
5039 entry_bb = e->dest;
5040 *gsi = gsi_last_bb (entry_bb);
5043 if (POINTER_TYPE_P (itype))
5044 itype = signed_type_for (itype);
5045 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5046 ? -1 : 1));
5047 t = fold_build2 (PLUS_EXPR, itype,
5048 fold_convert (itype, fd->loops[i].step), t);
5049 t = fold_build2 (PLUS_EXPR, itype, t,
5050 fold_convert (itype, fd->loops[i].n2));
5051 t = fold_build2 (MINUS_EXPR, itype, t,
5052 fold_convert (itype, fd->loops[i].n1));
5053 /* ?? We could probably use CEIL_DIV_EXPR instead of
5054 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5055 generate the same code in the end because generically we
5056 don't know that the values involved must be negative for
5057 GT?? */
5058 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5059 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5060 fold_build1 (NEGATE_EXPR, itype, t),
5061 fold_build1 (NEGATE_EXPR, itype,
5062 fold_convert (itype,
5063 fd->loops[i].step)));
5064 else
5065 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5066 fold_convert (itype, fd->loops[i].step));
5067 t = fold_convert (type, t);
5068 if (TREE_CODE (t) == INTEGER_CST)
5069 counts[i] = t;
5070 else
5072 counts[i] = create_tmp_reg (type, ".count");
5073 expand_omp_build_assign (gsi, counts[i], t);
5075 if (SSA_VAR_P (fd->loop.n2))
5077 if (i == 0)
5078 t = counts[0];
5079 else
5080 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5081 expand_omp_build_assign (gsi, fd->loop.n2, t);
5087 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5088 T = V;
5089 V3 = N31 + (T % count3) * STEP3;
5090 T = T / count3;
5091 V2 = N21 + (T % count2) * STEP2;
5092 T = T / count2;
5093 V1 = N11 + T * STEP1;
5094 if this loop doesn't have an inner loop construct combined with it.
5095 If it does have an inner loop construct combined with it and the
5096 iteration count isn't known constant, store values from counts array
5097 into its _looptemp_ temporaries instead. */
5099 static void
5100 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5101 tree *counts, gimple inner_stmt, tree startvar)
5103 int i;
5104 if (gimple_omp_for_combined_p (fd->for_stmt))
5106 /* If fd->loop.n2 is constant, then no propagation of the counts
5107 is needed, they are constant. */
5108 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5109 return;
5111 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5112 ? gimple_omp_parallel_clauses (inner_stmt)
5113 : gimple_omp_for_clauses (inner_stmt);
5114 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5115 isn't supposed to be handled, as the inner loop doesn't
5116 use it. */
5117 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5118 gcc_assert (innerc);
5119 for (i = 0; i < fd->collapse; i++)
5121 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5122 OMP_CLAUSE__LOOPTEMP_);
5123 gcc_assert (innerc);
5124 if (i)
5126 tree tem = OMP_CLAUSE_DECL (innerc);
5127 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5128 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5129 false, GSI_CONTINUE_LINKING);
5130 gimple stmt = gimple_build_assign (tem, t);
5131 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5134 return;
5137 tree type = TREE_TYPE (fd->loop.v);
5138 tree tem = create_tmp_reg (type, ".tem");
5139 gimple stmt = gimple_build_assign (tem, startvar);
5140 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5142 for (i = fd->collapse - 1; i >= 0; i--)
5144 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5145 itype = vtype;
5146 if (POINTER_TYPE_P (vtype))
5147 itype = signed_type_for (vtype);
5148 if (i != 0)
5149 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5150 else
5151 t = tem;
5152 t = fold_convert (itype, t);
5153 t = fold_build2 (MULT_EXPR, itype, t,
5154 fold_convert (itype, fd->loops[i].step));
5155 if (POINTER_TYPE_P (vtype))
5156 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5157 else
5158 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5159 t = force_gimple_operand_gsi (gsi, t,
5160 DECL_P (fd->loops[i].v)
5161 && TREE_ADDRESSABLE (fd->loops[i].v),
5162 NULL_TREE, false,
5163 GSI_CONTINUE_LINKING);
5164 stmt = gimple_build_assign (fd->loops[i].v, t);
5165 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5166 if (i != 0)
5168 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5169 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5170 false, GSI_CONTINUE_LINKING);
5171 stmt = gimple_build_assign (tem, t);
5172 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5178 /* Helper function for expand_omp_for_*. Generate code like:
5179 L10:
5180 V3 += STEP3;
5181 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5182 L11:
5183 V3 = N31;
5184 V2 += STEP2;
5185 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5186 L12:
5187 V2 = N21;
5188 V1 += STEP1;
5189 goto BODY_BB; */
5191 static basic_block
5192 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5193 basic_block body_bb)
5195 basic_block last_bb, bb, collapse_bb = NULL;
5196 int i;
5197 gimple_stmt_iterator gsi;
5198 edge e;
5199 tree t;
5200 gimple stmt;
5202 last_bb = cont_bb;
5203 for (i = fd->collapse - 1; i >= 0; i--)
5205 tree vtype = TREE_TYPE (fd->loops[i].v);
5207 bb = create_empty_bb (last_bb);
5208 if (current_loops)
5209 add_bb_to_loop (bb, last_bb->loop_father);
5210 gsi = gsi_start_bb (bb);
5212 if (i < fd->collapse - 1)
5214 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5215 e->probability = REG_BR_PROB_BASE / 8;
5217 t = fd->loops[i + 1].n1;
5218 t = force_gimple_operand_gsi (&gsi, t,
5219 DECL_P (fd->loops[i + 1].v)
5220 && TREE_ADDRESSABLE (fd->loops[i
5221 + 1].v),
5222 NULL_TREE, false,
5223 GSI_CONTINUE_LINKING);
5224 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5225 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5227 else
5228 collapse_bb = bb;
5230 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5232 if (POINTER_TYPE_P (vtype))
5233 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5234 else
5235 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5236 t = force_gimple_operand_gsi (&gsi, t,
5237 DECL_P (fd->loops[i].v)
5238 && TREE_ADDRESSABLE (fd->loops[i].v),
5239 NULL_TREE, false, GSI_CONTINUE_LINKING);
5240 stmt = gimple_build_assign (fd->loops[i].v, t);
5241 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5243 if (i > 0)
5245 t = fd->loops[i].n2;
5246 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5247 false, GSI_CONTINUE_LINKING);
5248 tree v = fd->loops[i].v;
5249 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5250 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5251 false, GSI_CONTINUE_LINKING);
5252 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5253 stmt = gimple_build_cond_empty (t);
5254 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5255 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5256 e->probability = REG_BR_PROB_BASE * 7 / 8;
5258 else
5259 make_edge (bb, body_bb, EDGE_FALLTHRU);
5260 last_bb = bb;
5263 return collapse_bb;
5267 /* A subroutine of expand_omp_for. Generate code for a parallel
5268 loop with any schedule. Given parameters:
5270 for (V = N1; V cond N2; V += STEP) BODY;
5272 where COND is "<" or ">", we generate pseudocode
5274 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5275 if (more) goto L0; else goto L3;
5277 V = istart0;
5278 iend = iend0;
5280 BODY;
5281 V += STEP;
5282 if (V cond iend) goto L1; else goto L2;
5284 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5287 If this is a combined omp parallel loop, instead of the call to
5288 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5289 If this is gimple_omp_for_combined_p loop, then instead of assigning
5290 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5291 inner GIMPLE_OMP_FOR and V += STEP; and
5292 if (V cond iend) goto L1; else goto L2; are removed.
5294 For collapsed loops, given parameters:
5295 collapse(3)
5296 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5297 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5298 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5299 BODY;
5301 we generate pseudocode
5303 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5304 if (cond3 is <)
5305 adj = STEP3 - 1;
5306 else
5307 adj = STEP3 + 1;
5308 count3 = (adj + N32 - N31) / STEP3;
5309 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5310 if (cond2 is <)
5311 adj = STEP2 - 1;
5312 else
5313 adj = STEP2 + 1;
5314 count2 = (adj + N22 - N21) / STEP2;
5315 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5316 if (cond1 is <)
5317 adj = STEP1 - 1;
5318 else
5319 adj = STEP1 + 1;
5320 count1 = (adj + N12 - N11) / STEP1;
5321 count = count1 * count2 * count3;
5322 goto Z1;
5324 count = 0;
5326 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5327 if (more) goto L0; else goto L3;
5329 V = istart0;
5330 T = V;
5331 V3 = N31 + (T % count3) * STEP3;
5332 T = T / count3;
5333 V2 = N21 + (T % count2) * STEP2;
5334 T = T / count2;
5335 V1 = N11 + T * STEP1;
5336 iend = iend0;
5338 BODY;
5339 V += 1;
5340 if (V < iend) goto L10; else goto L2;
5341 L10:
5342 V3 += STEP3;
5343 if (V3 cond3 N32) goto L1; else goto L11;
5344 L11:
5345 V3 = N31;
5346 V2 += STEP2;
5347 if (V2 cond2 N22) goto L1; else goto L12;
5348 L12:
5349 V2 = N21;
5350 V1 += STEP1;
5351 goto L1;
5353 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5358 static void
5359 expand_omp_for_generic (struct omp_region *region,
5360 struct omp_for_data *fd,
5361 enum built_in_function start_fn,
5362 enum built_in_function next_fn,
5363 gimple inner_stmt)
5365 tree type, istart0, iend0, iend;
5366 tree t, vmain, vback, bias = NULL_TREE;
5367 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5368 basic_block l2_bb = NULL, l3_bb = NULL;
5369 gimple_stmt_iterator gsi;
5370 gimple stmt;
5371 bool in_combined_parallel = is_combined_parallel (region);
5372 bool broken_loop = region->cont == NULL;
5373 edge e, ne;
5374 tree *counts = NULL;
5375 int i;
5377 gcc_assert (!broken_loop || !in_combined_parallel);
5378 gcc_assert (fd->iter_type == long_integer_type_node
5379 || !in_combined_parallel);
5381 type = TREE_TYPE (fd->loop.v);
5382 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5383 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5384 TREE_ADDRESSABLE (istart0) = 1;
5385 TREE_ADDRESSABLE (iend0) = 1;
5387 /* See if we need to bias by LLONG_MIN. */
5388 if (fd->iter_type == long_long_unsigned_type_node
5389 && TREE_CODE (type) == INTEGER_TYPE
5390 && !TYPE_UNSIGNED (type))
5392 tree n1, n2;
5394 if (fd->loop.cond_code == LT_EXPR)
5396 n1 = fd->loop.n1;
5397 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5399 else
5401 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5402 n2 = fd->loop.n1;
5404 if (TREE_CODE (n1) != INTEGER_CST
5405 || TREE_CODE (n2) != INTEGER_CST
5406 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5407 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5410 entry_bb = region->entry;
5411 cont_bb = region->cont;
5412 collapse_bb = NULL;
5413 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5414 gcc_assert (broken_loop
5415 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5416 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5417 l1_bb = single_succ (l0_bb);
5418 if (!broken_loop)
5420 l2_bb = create_empty_bb (cont_bb);
5421 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5422 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5424 else
5425 l2_bb = NULL;
5426 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5427 exit_bb = region->exit;
5429 gsi = gsi_last_bb (entry_bb);
5431 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5432 if (fd->collapse > 1)
5434 int first_zero_iter = -1;
5435 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5437 counts = XALLOCAVEC (tree, fd->collapse);
5438 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5439 zero_iter_bb, first_zero_iter,
5440 l2_dom_bb);
5442 if (zero_iter_bb)
5444 /* Some counts[i] vars might be uninitialized if
5445 some loop has zero iterations. But the body shouldn't
5446 be executed in that case, so just avoid uninit warnings. */
5447 for (i = first_zero_iter; i < fd->collapse; i++)
5448 if (SSA_VAR_P (counts[i]))
5449 TREE_NO_WARNING (counts[i]) = 1;
5450 gsi_prev (&gsi);
5451 e = split_block (entry_bb, gsi_stmt (gsi));
5452 entry_bb = e->dest;
5453 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5454 gsi = gsi_last_bb (entry_bb);
5455 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5456 get_immediate_dominator (CDI_DOMINATORS,
5457 zero_iter_bb));
5460 if (in_combined_parallel)
5462 /* In a combined parallel loop, emit a call to
5463 GOMP_loop_foo_next. */
5464 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5465 build_fold_addr_expr (istart0),
5466 build_fold_addr_expr (iend0));
5468 else
5470 tree t0, t1, t2, t3, t4;
5471 /* If this is not a combined parallel loop, emit a call to
5472 GOMP_loop_foo_start in ENTRY_BB. */
5473 t4 = build_fold_addr_expr (iend0);
5474 t3 = build_fold_addr_expr (istart0);
5475 t2 = fold_convert (fd->iter_type, fd->loop.step);
5476 t1 = fd->loop.n2;
5477 t0 = fd->loop.n1;
5478 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5480 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5481 OMP_CLAUSE__LOOPTEMP_);
5482 gcc_assert (innerc);
5483 t0 = OMP_CLAUSE_DECL (innerc);
5484 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5485 OMP_CLAUSE__LOOPTEMP_);
5486 gcc_assert (innerc);
5487 t1 = OMP_CLAUSE_DECL (innerc);
5489 if (POINTER_TYPE_P (TREE_TYPE (t0))
5490 && TYPE_PRECISION (TREE_TYPE (t0))
5491 != TYPE_PRECISION (fd->iter_type))
5493 /* Avoid casting pointers to integer of a different size. */
5494 tree itype = signed_type_for (type);
5495 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5496 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5498 else
5500 t1 = fold_convert (fd->iter_type, t1);
5501 t0 = fold_convert (fd->iter_type, t0);
5503 if (bias)
5505 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5506 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5508 if (fd->iter_type == long_integer_type_node)
5510 if (fd->chunk_size)
5512 t = fold_convert (fd->iter_type, fd->chunk_size);
5513 t = build_call_expr (builtin_decl_explicit (start_fn),
5514 6, t0, t1, t2, t, t3, t4);
5516 else
5517 t = build_call_expr (builtin_decl_explicit (start_fn),
5518 5, t0, t1, t2, t3, t4);
5520 else
5522 tree t5;
5523 tree c_bool_type;
5524 tree bfn_decl;
5526 /* The GOMP_loop_ull_*start functions have additional boolean
5527 argument, true for < loops and false for > loops.
5528 In Fortran, the C bool type can be different from
5529 boolean_type_node. */
5530 bfn_decl = builtin_decl_explicit (start_fn);
5531 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5532 t5 = build_int_cst (c_bool_type,
5533 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5534 if (fd->chunk_size)
5536 tree bfn_decl = builtin_decl_explicit (start_fn);
5537 t = fold_convert (fd->iter_type, fd->chunk_size);
5538 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5540 else
5541 t = build_call_expr (builtin_decl_explicit (start_fn),
5542 6, t5, t0, t1, t2, t3, t4);
5545 if (TREE_TYPE (t) != boolean_type_node)
5546 t = fold_build2 (NE_EXPR, boolean_type_node,
5547 t, build_int_cst (TREE_TYPE (t), 0));
5548 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5549 true, GSI_SAME_STMT);
5550 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5552 /* Remove the GIMPLE_OMP_FOR statement. */
5553 gsi_remove (&gsi, true);
5555 /* Iteration setup for sequential loop goes in L0_BB. */
5556 tree startvar = fd->loop.v;
5557 tree endvar = NULL_TREE;
5559 if (gimple_omp_for_combined_p (fd->for_stmt))
5561 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5562 && gimple_omp_for_kind (inner_stmt)
5563 == GF_OMP_FOR_KIND_SIMD);
5564 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5565 OMP_CLAUSE__LOOPTEMP_);
5566 gcc_assert (innerc);
5567 startvar = OMP_CLAUSE_DECL (innerc);
5568 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5569 OMP_CLAUSE__LOOPTEMP_);
5570 gcc_assert (innerc);
5571 endvar = OMP_CLAUSE_DECL (innerc);
5574 gsi = gsi_start_bb (l0_bb);
5575 t = istart0;
5576 if (bias)
5577 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5578 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5579 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5580 t = fold_convert (TREE_TYPE (startvar), t);
5581 t = force_gimple_operand_gsi (&gsi, t,
5582 DECL_P (startvar)
5583 && TREE_ADDRESSABLE (startvar),
5584 NULL_TREE, false, GSI_CONTINUE_LINKING);
5585 stmt = gimple_build_assign (startvar, t);
5586 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5588 t = iend0;
5589 if (bias)
5590 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5591 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5592 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5593 t = fold_convert (TREE_TYPE (startvar), t);
5594 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5595 false, GSI_CONTINUE_LINKING);
5596 if (endvar)
5598 stmt = gimple_build_assign (endvar, iend);
5599 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5600 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
5601 stmt = gimple_build_assign (fd->loop.v, iend);
5602 else
5603 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend,
5604 NULL_TREE);
5605 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5607 if (fd->collapse > 1)
5608 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5610 if (!broken_loop)
5612 /* Code to control the increment and predicate for the sequential
5613 loop goes in the CONT_BB. */
5614 gsi = gsi_last_bb (cont_bb);
5615 stmt = gsi_stmt (gsi);
5616 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5617 vmain = gimple_omp_continue_control_use (stmt);
5618 vback = gimple_omp_continue_control_def (stmt);
5620 if (!gimple_omp_for_combined_p (fd->for_stmt))
5622 if (POINTER_TYPE_P (type))
5623 t = fold_build_pointer_plus (vmain, fd->loop.step);
5624 else
5625 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5626 t = force_gimple_operand_gsi (&gsi, t,
5627 DECL_P (vback)
5628 && TREE_ADDRESSABLE (vback),
5629 NULL_TREE, true, GSI_SAME_STMT);
5630 stmt = gimple_build_assign (vback, t);
5631 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5633 t = build2 (fd->loop.cond_code, boolean_type_node,
5634 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5635 iend);
5636 stmt = gimple_build_cond_empty (t);
5637 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5640 /* Remove GIMPLE_OMP_CONTINUE. */
5641 gsi_remove (&gsi, true);
5643 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5644 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5646 /* Emit code to get the next parallel iteration in L2_BB. */
5647 gsi = gsi_start_bb (l2_bb);
5649 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5650 build_fold_addr_expr (istart0),
5651 build_fold_addr_expr (iend0));
5652 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5653 false, GSI_CONTINUE_LINKING);
5654 if (TREE_TYPE (t) != boolean_type_node)
5655 t = fold_build2 (NE_EXPR, boolean_type_node,
5656 t, build_int_cst (TREE_TYPE (t), 0));
5657 stmt = gimple_build_cond_empty (t);
5658 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5661 /* Add the loop cleanup function. */
5662 gsi = gsi_last_bb (exit_bb);
5663 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5664 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5665 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5666 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5667 else
5668 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5669 stmt = gimple_build_call (t, 0);
5670 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5671 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5672 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5673 gsi_remove (&gsi, true);
5675 /* Connect the new blocks. */
5676 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5677 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5679 if (!broken_loop)
5681 gimple_seq phis;
5683 e = find_edge (cont_bb, l3_bb);
5684 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5686 phis = phi_nodes (l3_bb);
5687 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5689 gimple phi = gsi_stmt (gsi);
5690 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5691 PHI_ARG_DEF_FROM_EDGE (phi, e));
5693 remove_edge (e);
5695 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5696 if (current_loops)
5697 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5698 e = find_edge (cont_bb, l1_bb);
5699 if (gimple_omp_for_combined_p (fd->for_stmt))
5701 remove_edge (e);
5702 e = NULL;
5704 else if (fd->collapse > 1)
5706 remove_edge (e);
5707 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5709 else
5710 e->flags = EDGE_TRUE_VALUE;
5711 if (e)
5713 e->probability = REG_BR_PROB_BASE * 7 / 8;
5714 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5716 else
5718 e = find_edge (cont_bb, l2_bb);
5719 e->flags = EDGE_FALLTHRU;
5721 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5723 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5724 recompute_dominator (CDI_DOMINATORS, l2_bb));
5725 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5726 recompute_dominator (CDI_DOMINATORS, l3_bb));
5727 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5728 recompute_dominator (CDI_DOMINATORS, l0_bb));
5729 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5730 recompute_dominator (CDI_DOMINATORS, l1_bb));
5732 struct loop *outer_loop = alloc_loop ();
5733 outer_loop->header = l0_bb;
5734 outer_loop->latch = l2_bb;
5735 add_loop (outer_loop, l0_bb->loop_father);
5737 if (!gimple_omp_for_combined_p (fd->for_stmt))
5739 struct loop *loop = alloc_loop ();
5740 loop->header = l1_bb;
5741 /* The loop may have multiple latches. */
5742 add_loop (loop, outer_loop);
5748 /* A subroutine of expand_omp_for. Generate code for a parallel
5749 loop with static schedule and no specified chunk size. Given
5750 parameters:
5752 for (V = N1; V cond N2; V += STEP) BODY;
5754 where COND is "<" or ">", we generate pseudocode
5756 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5757 if (cond is <)
5758 adj = STEP - 1;
5759 else
5760 adj = STEP + 1;
5761 if ((__typeof (V)) -1 > 0 && cond is >)
5762 n = -(adj + N2 - N1) / -STEP;
5763 else
5764 n = (adj + N2 - N1) / STEP;
5765 q = n / nthreads;
5766 tt = n % nthreads;
5767 if (threadid < tt) goto L3; else goto L4;
5769 tt = 0;
5770 q = q + 1;
5772 s0 = q * threadid + tt;
5773 e0 = s0 + q;
5774 V = s0 * STEP + N1;
5775 if (s0 >= e0) goto L2; else goto L0;
5777 e = e0 * STEP + N1;
5779 BODY;
5780 V += STEP;
5781 if (V cond e) goto L1;
5785 static void
5786 expand_omp_for_static_nochunk (struct omp_region *region,
5787 struct omp_for_data *fd,
5788 gimple inner_stmt)
5790 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
5791 tree type, itype, vmain, vback;
5792 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
5793 basic_block body_bb, cont_bb, collapse_bb = NULL;
5794 basic_block fin_bb;
5795 gimple_stmt_iterator gsi;
5796 gimple stmt;
5797 edge ep;
5798 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
5799 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
5800 bool broken_loop = region->cont == NULL;
5801 tree *counts = NULL;
5802 tree n1, n2, step;
5804 itype = type = TREE_TYPE (fd->loop.v);
5805 if (POINTER_TYPE_P (type))
5806 itype = signed_type_for (type);
5808 entry_bb = region->entry;
5809 cont_bb = region->cont;
5810 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5811 fin_bb = BRANCH_EDGE (entry_bb)->dest;
5812 gcc_assert (broken_loop
5813 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
5814 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5815 body_bb = single_succ (seq_start_bb);
5816 if (!broken_loop)
5818 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
5819 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5821 exit_bb = region->exit;
5823 /* Iteration space partitioning goes in ENTRY_BB. */
5824 gsi = gsi_last_bb (entry_bb);
5825 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5827 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
5829 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
5830 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
5833 if (fd->collapse > 1)
5835 int first_zero_iter = -1;
5836 basic_block l2_dom_bb = NULL;
5838 counts = XALLOCAVEC (tree, fd->collapse);
5839 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5840 fin_bb, first_zero_iter,
5841 l2_dom_bb);
5842 t = NULL_TREE;
5844 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
5845 t = integer_one_node;
5846 else
5847 t = fold_binary (fd->loop.cond_code, boolean_type_node,
5848 fold_convert (type, fd->loop.n1),
5849 fold_convert (type, fd->loop.n2));
5850 if (fd->collapse == 1
5851 && TYPE_UNSIGNED (type)
5852 && (t == NULL_TREE || !integer_onep (t)))
5854 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5855 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5856 true, GSI_SAME_STMT);
5857 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5858 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5859 true, GSI_SAME_STMT);
5860 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
5861 NULL_TREE, NULL_TREE);
5862 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5863 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5864 expand_omp_regimplify_p, NULL, NULL)
5865 || walk_tree (gimple_cond_rhs_ptr (stmt),
5866 expand_omp_regimplify_p, NULL, NULL))
5868 gsi = gsi_for_stmt (stmt);
5869 gimple_regimplify_operands (stmt, &gsi);
5871 ep = split_block (entry_bb, stmt);
5872 ep->flags = EDGE_TRUE_VALUE;
5873 entry_bb = ep->dest;
5874 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
5875 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
5876 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
5877 if (gimple_in_ssa_p (cfun))
5879 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
5880 for (gsi = gsi_start_phis (fin_bb);
5881 !gsi_end_p (gsi); gsi_next (&gsi))
5883 gimple phi = gsi_stmt (gsi);
5884 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
5885 ep, UNKNOWN_LOCATION);
5888 gsi = gsi_last_bb (entry_bb);
5891 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
5892 t = fold_convert (itype, t);
5893 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5894 true, GSI_SAME_STMT);
5896 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
5897 t = fold_convert (itype, t);
5898 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5899 true, GSI_SAME_STMT);
5901 n1 = fd->loop.n1;
5902 n2 = fd->loop.n2;
5903 step = fd->loop.step;
5904 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5906 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5907 OMP_CLAUSE__LOOPTEMP_);
5908 gcc_assert (innerc);
5909 n1 = OMP_CLAUSE_DECL (innerc);
5910 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5911 OMP_CLAUSE__LOOPTEMP_);
5912 gcc_assert (innerc);
5913 n2 = OMP_CLAUSE_DECL (innerc);
5915 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
5916 true, NULL_TREE, true, GSI_SAME_STMT);
5917 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
5918 true, NULL_TREE, true, GSI_SAME_STMT);
5919 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
5920 true, NULL_TREE, true, GSI_SAME_STMT);
5922 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
5923 t = fold_build2 (PLUS_EXPR, itype, step, t);
5924 t = fold_build2 (PLUS_EXPR, itype, t, n2);
5925 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
5926 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
5927 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5928 fold_build1 (NEGATE_EXPR, itype, t),
5929 fold_build1 (NEGATE_EXPR, itype, step));
5930 else
5931 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
5932 t = fold_convert (itype, t);
5933 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5935 q = create_tmp_reg (itype, "q");
5936 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
5937 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5938 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
5940 tt = create_tmp_reg (itype, "tt");
5941 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
5942 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5943 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
5945 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
5946 stmt = gimple_build_cond_empty (t);
5947 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5949 second_bb = split_block (entry_bb, stmt)->dest;
5950 gsi = gsi_last_bb (second_bb);
5951 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5953 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
5954 GSI_SAME_STMT);
5955 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
5956 build_int_cst (itype, 1));
5957 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5959 third_bb = split_block (second_bb, stmt)->dest;
5960 gsi = gsi_last_bb (third_bb);
5961 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5963 t = build2 (MULT_EXPR, itype, q, threadid);
5964 t = build2 (PLUS_EXPR, itype, t, tt);
5965 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5967 t = fold_build2 (PLUS_EXPR, itype, s0, q);
5968 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5970 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
5971 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5973 /* Remove the GIMPLE_OMP_FOR statement. */
5974 gsi_remove (&gsi, true);
5976 /* Setup code for sequential iteration goes in SEQ_START_BB. */
5977 gsi = gsi_start_bb (seq_start_bb);
5979 tree startvar = fd->loop.v;
5980 tree endvar = NULL_TREE;
5982 if (gimple_omp_for_combined_p (fd->for_stmt))
5984 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5985 ? gimple_omp_parallel_clauses (inner_stmt)
5986 : gimple_omp_for_clauses (inner_stmt);
5987 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5988 gcc_assert (innerc);
5989 startvar = OMP_CLAUSE_DECL (innerc);
5990 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5991 OMP_CLAUSE__LOOPTEMP_);
5992 gcc_assert (innerc);
5993 endvar = OMP_CLAUSE_DECL (innerc);
5995 t = fold_convert (itype, s0);
5996 t = fold_build2 (MULT_EXPR, itype, t, step);
5997 if (POINTER_TYPE_P (type))
5998 t = fold_build_pointer_plus (n1, t);
5999 else
6000 t = fold_build2 (PLUS_EXPR, type, t, n1);
6001 t = fold_convert (TREE_TYPE (startvar), t);
6002 t = force_gimple_operand_gsi (&gsi, t,
6003 DECL_P (startvar)
6004 && TREE_ADDRESSABLE (startvar),
6005 NULL_TREE, false, GSI_CONTINUE_LINKING);
6006 stmt = gimple_build_assign (startvar, t);
6007 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6009 t = fold_convert (itype, e0);
6010 t = fold_build2 (MULT_EXPR, itype, t, step);
6011 if (POINTER_TYPE_P (type))
6012 t = fold_build_pointer_plus (n1, t);
6013 else
6014 t = fold_build2 (PLUS_EXPR, type, t, n1);
6015 t = fold_convert (TREE_TYPE (startvar), t);
6016 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6017 false, GSI_CONTINUE_LINKING);
6018 if (endvar)
6020 stmt = gimple_build_assign (endvar, e);
6021 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6022 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6023 stmt = gimple_build_assign (fd->loop.v, e);
6024 else
6025 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6026 NULL_TREE);
6027 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6029 if (fd->collapse > 1)
6030 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6032 if (!broken_loop)
6034 /* The code controlling the sequential loop replaces the
6035 GIMPLE_OMP_CONTINUE. */
6036 gsi = gsi_last_bb (cont_bb);
6037 stmt = gsi_stmt (gsi);
6038 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6039 vmain = gimple_omp_continue_control_use (stmt);
6040 vback = gimple_omp_continue_control_def (stmt);
6042 if (!gimple_omp_for_combined_p (fd->for_stmt))
6044 if (POINTER_TYPE_P (type))
6045 t = fold_build_pointer_plus (vmain, step);
6046 else
6047 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6048 t = force_gimple_operand_gsi (&gsi, t,
6049 DECL_P (vback)
6050 && TREE_ADDRESSABLE (vback),
6051 NULL_TREE, true, GSI_SAME_STMT);
6052 stmt = gimple_build_assign (vback, t);
6053 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6055 t = build2 (fd->loop.cond_code, boolean_type_node,
6056 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6057 ? t : vback, e);
6058 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6061 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6062 gsi_remove (&gsi, true);
6064 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6065 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6068 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6069 gsi = gsi_last_bb (exit_bb);
6070 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6072 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6073 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6075 gsi_remove (&gsi, true);
6077 /* Connect all the blocks. */
6078 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6079 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6080 ep = find_edge (entry_bb, second_bb);
6081 ep->flags = EDGE_TRUE_VALUE;
6082 ep->probability = REG_BR_PROB_BASE / 4;
6083 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6084 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6086 if (!broken_loop)
6088 ep = find_edge (cont_bb, body_bb);
6089 if (gimple_omp_for_combined_p (fd->for_stmt))
6091 remove_edge (ep);
6092 ep = NULL;
6094 else if (fd->collapse > 1)
6096 remove_edge (ep);
6097 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6099 else
6100 ep->flags = EDGE_TRUE_VALUE;
6101 find_edge (cont_bb, fin_bb)->flags
6102 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6105 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6106 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6107 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6109 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6110 recompute_dominator (CDI_DOMINATORS, body_bb));
6111 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6112 recompute_dominator (CDI_DOMINATORS, fin_bb));
6114 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6116 struct loop *loop = alloc_loop ();
6117 loop->header = body_bb;
6118 if (collapse_bb == NULL)
6119 loop->latch = cont_bb;
6120 add_loop (loop, body_bb->loop_father);
6125 /* A subroutine of expand_omp_for. Generate code for a parallel
6126 loop with static schedule and a specified chunk size. Given
6127 parameters:
6129 for (V = N1; V cond N2; V += STEP) BODY;
6131 where COND is "<" or ">", we generate pseudocode
6133 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6134 if (cond is <)
6135 adj = STEP - 1;
6136 else
6137 adj = STEP + 1;
6138 if ((__typeof (V)) -1 > 0 && cond is >)
6139 n = -(adj + N2 - N1) / -STEP;
6140 else
6141 n = (adj + N2 - N1) / STEP;
6142 trip = 0;
6143 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6144 here so that V is defined
6145 if the loop is not entered
6147 s0 = (trip * nthreads + threadid) * CHUNK;
6148 e0 = min(s0 + CHUNK, n);
6149 if (s0 < n) goto L1; else goto L4;
6151 V = s0 * STEP + N1;
6152 e = e0 * STEP + N1;
6154 BODY;
6155 V += STEP;
6156 if (V cond e) goto L2; else goto L3;
6158 trip += 1;
6159 goto L0;
6163 static void
6164 expand_omp_for_static_chunk (struct omp_region *region,
6165 struct omp_for_data *fd, gimple inner_stmt)
6167 tree n, s0, e0, e, t;
6168 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6169 tree type, itype, vmain, vback, vextra;
6170 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6171 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6172 gimple_stmt_iterator gsi;
6173 gimple stmt;
6174 edge se;
6175 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6176 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6177 bool broken_loop = region->cont == NULL;
6178 tree *counts = NULL;
6179 tree n1, n2, step;
6181 itype = type = TREE_TYPE (fd->loop.v);
6182 if (POINTER_TYPE_P (type))
6183 itype = signed_type_for (type);
6185 entry_bb = region->entry;
6186 se = split_block (entry_bb, last_stmt (entry_bb));
6187 entry_bb = se->src;
6188 iter_part_bb = se->dest;
6189 cont_bb = region->cont;
6190 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6191 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6192 gcc_assert (broken_loop
6193 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6194 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6195 body_bb = single_succ (seq_start_bb);
6196 if (!broken_loop)
6198 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6199 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6200 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6202 exit_bb = region->exit;
6204 /* Trip and adjustment setup goes in ENTRY_BB. */
6205 gsi = gsi_last_bb (entry_bb);
6206 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6208 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6210 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6211 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6214 if (fd->collapse > 1)
6216 int first_zero_iter = -1;
6217 basic_block l2_dom_bb = NULL;
6219 counts = XALLOCAVEC (tree, fd->collapse);
6220 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6221 fin_bb, first_zero_iter,
6222 l2_dom_bb);
6223 t = NULL_TREE;
6225 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6226 t = integer_one_node;
6227 else
6228 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6229 fold_convert (type, fd->loop.n1),
6230 fold_convert (type, fd->loop.n2));
6231 if (fd->collapse == 1
6232 && TYPE_UNSIGNED (type)
6233 && (t == NULL_TREE || !integer_onep (t)))
6235 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6236 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6237 true, GSI_SAME_STMT);
6238 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6239 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6240 true, GSI_SAME_STMT);
6241 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6242 NULL_TREE, NULL_TREE);
6243 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6244 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6245 expand_omp_regimplify_p, NULL, NULL)
6246 || walk_tree (gimple_cond_rhs_ptr (stmt),
6247 expand_omp_regimplify_p, NULL, NULL))
6249 gsi = gsi_for_stmt (stmt);
6250 gimple_regimplify_operands (stmt, &gsi);
6252 se = split_block (entry_bb, stmt);
6253 se->flags = EDGE_TRUE_VALUE;
6254 entry_bb = se->dest;
6255 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6256 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6257 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6258 if (gimple_in_ssa_p (cfun))
6260 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6261 for (gsi = gsi_start_phis (fin_bb);
6262 !gsi_end_p (gsi); gsi_next (&gsi))
6264 gimple phi = gsi_stmt (gsi);
6265 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6266 se, UNKNOWN_LOCATION);
6269 gsi = gsi_last_bb (entry_bb);
6272 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6273 t = fold_convert (itype, t);
6274 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6275 true, GSI_SAME_STMT);
6277 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6278 t = fold_convert (itype, t);
6279 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6280 true, GSI_SAME_STMT);
6282 n1 = fd->loop.n1;
6283 n2 = fd->loop.n2;
6284 step = fd->loop.step;
6285 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6287 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6288 OMP_CLAUSE__LOOPTEMP_);
6289 gcc_assert (innerc);
6290 n1 = OMP_CLAUSE_DECL (innerc);
6291 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6292 OMP_CLAUSE__LOOPTEMP_);
6293 gcc_assert (innerc);
6294 n2 = OMP_CLAUSE_DECL (innerc);
6296 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6297 true, NULL_TREE, true, GSI_SAME_STMT);
6298 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6299 true, NULL_TREE, true, GSI_SAME_STMT);
6300 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6301 true, NULL_TREE, true, GSI_SAME_STMT);
6302 fd->chunk_size
6303 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
6304 true, NULL_TREE, true, GSI_SAME_STMT);
6306 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6307 t = fold_build2 (PLUS_EXPR, itype, step, t);
6308 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6309 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6310 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6311 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6312 fold_build1 (NEGATE_EXPR, itype, t),
6313 fold_build1 (NEGATE_EXPR, itype, step));
6314 else
6315 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6316 t = fold_convert (itype, t);
6317 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6318 true, GSI_SAME_STMT);
6320 trip_var = create_tmp_reg (itype, ".trip");
6321 if (gimple_in_ssa_p (cfun))
6323 trip_init = make_ssa_name (trip_var, NULL);
6324 trip_main = make_ssa_name (trip_var, NULL);
6325 trip_back = make_ssa_name (trip_var, NULL);
6327 else
6329 trip_init = trip_var;
6330 trip_main = trip_var;
6331 trip_back = trip_var;
6334 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6335 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6337 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6338 t = fold_build2 (MULT_EXPR, itype, t, step);
6339 if (POINTER_TYPE_P (type))
6340 t = fold_build_pointer_plus (n1, t);
6341 else
6342 t = fold_build2 (PLUS_EXPR, type, t, n1);
6343 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6344 true, GSI_SAME_STMT);
6346 /* Remove the GIMPLE_OMP_FOR. */
6347 gsi_remove (&gsi, true);
6349 /* Iteration space partitioning goes in ITER_PART_BB. */
6350 gsi = gsi_last_bb (iter_part_bb);
6352 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6353 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6354 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6355 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6356 false, GSI_CONTINUE_LINKING);
6358 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6359 t = fold_build2 (MIN_EXPR, itype, t, n);
6360 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6361 false, GSI_CONTINUE_LINKING);
6363 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6364 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6366 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6367 gsi = gsi_start_bb (seq_start_bb);
6369 tree startvar = fd->loop.v;
6370 tree endvar = NULL_TREE;
6372 if (gimple_omp_for_combined_p (fd->for_stmt))
6374 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6375 ? gimple_omp_parallel_clauses (inner_stmt)
6376 : gimple_omp_for_clauses (inner_stmt);
6377 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6378 gcc_assert (innerc);
6379 startvar = OMP_CLAUSE_DECL (innerc);
6380 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6381 OMP_CLAUSE__LOOPTEMP_);
6382 gcc_assert (innerc);
6383 endvar = OMP_CLAUSE_DECL (innerc);
6386 t = fold_convert (itype, s0);
6387 t = fold_build2 (MULT_EXPR, itype, t, step);
6388 if (POINTER_TYPE_P (type))
6389 t = fold_build_pointer_plus (n1, t);
6390 else
6391 t = fold_build2 (PLUS_EXPR, type, t, n1);
6392 t = fold_convert (TREE_TYPE (startvar), t);
6393 t = force_gimple_operand_gsi (&gsi, t,
6394 DECL_P (startvar)
6395 && TREE_ADDRESSABLE (startvar),
6396 NULL_TREE, false, GSI_CONTINUE_LINKING);
6397 stmt = gimple_build_assign (startvar, t);
6398 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6400 t = fold_convert (itype, e0);
6401 t = fold_build2 (MULT_EXPR, itype, t, step);
6402 if (POINTER_TYPE_P (type))
6403 t = fold_build_pointer_plus (n1, t);
6404 else
6405 t = fold_build2 (PLUS_EXPR, type, t, n1);
6406 t = fold_convert (TREE_TYPE (startvar), t);
6407 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6408 false, GSI_CONTINUE_LINKING);
6409 if (endvar)
6411 stmt = gimple_build_assign (endvar, e);
6412 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6413 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6414 stmt = gimple_build_assign (fd->loop.v, e);
6415 else
6416 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6417 NULL_TREE);
6418 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6420 if (fd->collapse > 1)
6421 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6423 if (!broken_loop)
6425 /* The code controlling the sequential loop goes in CONT_BB,
6426 replacing the GIMPLE_OMP_CONTINUE. */
6427 gsi = gsi_last_bb (cont_bb);
6428 stmt = gsi_stmt (gsi);
6429 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6430 vmain = gimple_omp_continue_control_use (stmt);
6431 vback = gimple_omp_continue_control_def (stmt);
6433 if (!gimple_omp_for_combined_p (fd->for_stmt))
6435 if (POINTER_TYPE_P (type))
6436 t = fold_build_pointer_plus (vmain, step);
6437 else
6438 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6439 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
6440 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6441 true, GSI_SAME_STMT);
6442 stmt = gimple_build_assign (vback, t);
6443 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6445 t = build2 (fd->loop.cond_code, boolean_type_node,
6446 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6447 ? t : vback, e);
6448 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6451 /* Remove GIMPLE_OMP_CONTINUE. */
6452 gsi_remove (&gsi, true);
6454 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6455 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6457 /* Trip update code goes into TRIP_UPDATE_BB. */
6458 gsi = gsi_start_bb (trip_update_bb);
6460 t = build_int_cst (itype, 1);
6461 t = build2 (PLUS_EXPR, itype, trip_main, t);
6462 stmt = gimple_build_assign (trip_back, t);
6463 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6466 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6467 gsi = gsi_last_bb (exit_bb);
6468 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6470 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6471 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6473 gsi_remove (&gsi, true);
6475 /* Connect the new blocks. */
6476 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6477 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6479 if (!broken_loop)
6481 se = find_edge (cont_bb, body_bb);
6482 if (gimple_omp_for_combined_p (fd->for_stmt))
6484 remove_edge (se);
6485 se = NULL;
6487 else if (fd->collapse > 1)
6489 remove_edge (se);
6490 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6492 else
6493 se->flags = EDGE_TRUE_VALUE;
6494 find_edge (cont_bb, trip_update_bb)->flags
6495 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6497 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6500 if (gimple_in_ssa_p (cfun))
6502 gimple_stmt_iterator psi;
6503 gimple phi;
6504 edge re, ene;
6505 edge_var_map_vector *head;
6506 edge_var_map *vm;
6507 size_t i;
6509 gcc_assert (fd->collapse == 1 && !broken_loop);
6511 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6512 remove arguments of the phi nodes in fin_bb. We need to create
6513 appropriate phi nodes in iter_part_bb instead. */
6514 se = single_pred_edge (fin_bb);
6515 re = single_succ_edge (trip_update_bb);
6516 head = redirect_edge_var_map_vector (re);
6517 ene = single_succ_edge (entry_bb);
6519 psi = gsi_start_phis (fin_bb);
6520 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6521 gsi_next (&psi), ++i)
6523 gimple nphi;
6524 source_location locus;
6526 phi = gsi_stmt (psi);
6527 t = gimple_phi_result (phi);
6528 gcc_assert (t == redirect_edge_var_map_result (vm));
6529 nphi = create_phi_node (t, iter_part_bb);
6531 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6532 locus = gimple_phi_arg_location_from_edge (phi, se);
6534 /* A special case -- fd->loop.v is not yet computed in
6535 iter_part_bb, we need to use vextra instead. */
6536 if (t == fd->loop.v)
6537 t = vextra;
6538 add_phi_arg (nphi, t, ene, locus);
6539 locus = redirect_edge_var_map_location (vm);
6540 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6542 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6543 redirect_edge_var_map_clear (re);
6544 while (1)
6546 psi = gsi_start_phis (fin_bb);
6547 if (gsi_end_p (psi))
6548 break;
6549 remove_phi_node (&psi, false);
6552 /* Make phi node for trip. */
6553 phi = create_phi_node (trip_main, iter_part_bb);
6554 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6555 UNKNOWN_LOCATION);
6556 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6557 UNKNOWN_LOCATION);
6560 if (!broken_loop)
6561 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6562 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6563 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6564 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6565 recompute_dominator (CDI_DOMINATORS, fin_bb));
6566 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6567 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6568 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6569 recompute_dominator (CDI_DOMINATORS, body_bb));
6571 if (!broken_loop)
6573 struct loop *trip_loop = alloc_loop ();
6574 trip_loop->header = iter_part_bb;
6575 trip_loop->latch = trip_update_bb;
6576 add_loop (trip_loop, iter_part_bb->loop_father);
6578 if (!gimple_omp_for_combined_p (fd->for_stmt))
6580 struct loop *loop = alloc_loop ();
6581 loop->header = body_bb;
6582 if (collapse_bb == NULL)
6583 loop->latch = cont_bb;
6584 add_loop (loop, trip_loop);
6590 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6591 loop. Given parameters:
6593 for (V = N1; V cond N2; V += STEP) BODY;
6595 where COND is "<" or ">", we generate pseudocode
6597 V = N1;
6598 goto L1;
6600 BODY;
6601 V += STEP;
6603 if (V cond N2) goto L0; else goto L2;
6606 For collapsed loops, given parameters:
6607 collapse(3)
6608 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6609 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6610 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6611 BODY;
6613 we generate pseudocode
6615 if (cond3 is <)
6616 adj = STEP3 - 1;
6617 else
6618 adj = STEP3 + 1;
6619 count3 = (adj + N32 - N31) / STEP3;
6620 if (cond2 is <)
6621 adj = STEP2 - 1;
6622 else
6623 adj = STEP2 + 1;
6624 count2 = (adj + N22 - N21) / STEP2;
6625 if (cond1 is <)
6626 adj = STEP1 - 1;
6627 else
6628 adj = STEP1 + 1;
6629 count1 = (adj + N12 - N11) / STEP1;
6630 count = count1 * count2 * count3;
6631 V = 0;
6632 V1 = N11;
6633 V2 = N21;
6634 V3 = N31;
6635 goto L1;
6637 BODY;
6638 V += 1;
6639 V3 += STEP3;
6640 V2 += (V3 cond3 N32) ? 0 : STEP2;
6641 V3 = (V3 cond3 N32) ? V3 : N31;
6642 V1 += (V2 cond2 N22) ? 0 : STEP1;
6643 V2 = (V2 cond2 N22) ? V2 : N21;
6645 if (V < count) goto L0; else goto L2;
6650 static void
6651 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
6653 tree type, t;
6654 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
6655 gimple_stmt_iterator gsi;
6656 gimple stmt;
6657 bool broken_loop = region->cont == NULL;
6658 edge e, ne;
6659 tree *counts = NULL;
6660 int i;
6661 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6662 OMP_CLAUSE_SAFELEN);
6663 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6664 OMP_CLAUSE__SIMDUID_);
6665 tree n1, n2;
6667 type = TREE_TYPE (fd->loop.v);
6668 entry_bb = region->entry;
6669 cont_bb = region->cont;
6670 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6671 gcc_assert (broken_loop
6672 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6673 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6674 if (!broken_loop)
6676 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6677 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6678 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6679 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6681 else
6683 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6684 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6685 l2_bb = single_succ (l1_bb);
6687 exit_bb = region->exit;
6688 l2_dom_bb = NULL;
6690 gsi = gsi_last_bb (entry_bb);
6692 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6693 /* Not needed in SSA form right now. */
6694 gcc_assert (!gimple_in_ssa_p (cfun));
6695 if (fd->collapse > 1)
6697 int first_zero_iter = -1;
6698 basic_block zero_iter_bb = l2_bb;
6700 counts = XALLOCAVEC (tree, fd->collapse);
6701 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6702 zero_iter_bb, first_zero_iter,
6703 l2_dom_bb);
6705 if (l2_dom_bb == NULL)
6706 l2_dom_bb = l1_bb;
6708 n1 = fd->loop.n1;
6709 n2 = fd->loop.n2;
6710 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6712 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6713 OMP_CLAUSE__LOOPTEMP_);
6714 gcc_assert (innerc);
6715 n1 = OMP_CLAUSE_DECL (innerc);
6716 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6717 OMP_CLAUSE__LOOPTEMP_);
6718 gcc_assert (innerc);
6719 n2 = OMP_CLAUSE_DECL (innerc);
6720 expand_omp_build_assign (&gsi, fd->loop.v,
6721 fold_convert (type, n1));
6722 if (fd->collapse > 1)
6724 gsi_prev (&gsi);
6725 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
6726 gsi_next (&gsi);
6729 else
6731 expand_omp_build_assign (&gsi, fd->loop.v,
6732 fold_convert (type, fd->loop.n1));
6733 if (fd->collapse > 1)
6734 for (i = 0; i < fd->collapse; i++)
6736 tree itype = TREE_TYPE (fd->loops[i].v);
6737 if (POINTER_TYPE_P (itype))
6738 itype = signed_type_for (itype);
6739 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
6740 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6744 /* Remove the GIMPLE_OMP_FOR statement. */
6745 gsi_remove (&gsi, true);
6747 if (!broken_loop)
6749 /* Code to control the increment goes in the CONT_BB. */
6750 gsi = gsi_last_bb (cont_bb);
6751 stmt = gsi_stmt (gsi);
6752 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6754 if (POINTER_TYPE_P (type))
6755 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
6756 else
6757 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
6758 expand_omp_build_assign (&gsi, fd->loop.v, t);
6760 if (fd->collapse > 1)
6762 i = fd->collapse - 1;
6763 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
6765 t = fold_convert (sizetype, fd->loops[i].step);
6766 t = fold_build_pointer_plus (fd->loops[i].v, t);
6768 else
6770 t = fold_convert (TREE_TYPE (fd->loops[i].v),
6771 fd->loops[i].step);
6772 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
6773 fd->loops[i].v, t);
6775 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6777 for (i = fd->collapse - 1; i > 0; i--)
6779 tree itype = TREE_TYPE (fd->loops[i].v);
6780 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
6781 if (POINTER_TYPE_P (itype2))
6782 itype2 = signed_type_for (itype2);
6783 t = build3 (COND_EXPR, itype2,
6784 build2 (fd->loops[i].cond_code, boolean_type_node,
6785 fd->loops[i].v,
6786 fold_convert (itype, fd->loops[i].n2)),
6787 build_int_cst (itype2, 0),
6788 fold_convert (itype2, fd->loops[i - 1].step));
6789 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
6790 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
6791 else
6792 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
6793 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
6795 t = build3 (COND_EXPR, itype,
6796 build2 (fd->loops[i].cond_code, boolean_type_node,
6797 fd->loops[i].v,
6798 fold_convert (itype, fd->loops[i].n2)),
6799 fd->loops[i].v,
6800 fold_convert (itype, fd->loops[i].n1));
6801 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6805 /* Remove GIMPLE_OMP_CONTINUE. */
6806 gsi_remove (&gsi, true);
6809 /* Emit the condition in L1_BB. */
6810 gsi = gsi_start_bb (l1_bb);
6812 t = fold_convert (type, n2);
6813 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6814 false, GSI_CONTINUE_LINKING);
6815 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
6816 stmt = gimple_build_cond_empty (t);
6817 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6818 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
6819 NULL, NULL)
6820 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
6821 NULL, NULL))
6823 gsi = gsi_for_stmt (stmt);
6824 gimple_regimplify_operands (stmt, &gsi);
6827 /* Remove GIMPLE_OMP_RETURN. */
6828 gsi = gsi_last_bb (exit_bb);
6829 gsi_remove (&gsi, true);
6831 /* Connect the new blocks. */
6832 remove_edge (FALLTHRU_EDGE (entry_bb));
6834 if (!broken_loop)
6836 remove_edge (BRANCH_EDGE (entry_bb));
6837 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6839 e = BRANCH_EDGE (l1_bb);
6840 ne = FALLTHRU_EDGE (l1_bb);
6841 e->flags = EDGE_TRUE_VALUE;
6843 else
6845 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6847 ne = single_succ_edge (l1_bb);
6848 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6851 ne->flags = EDGE_FALSE_VALUE;
6852 e->probability = REG_BR_PROB_BASE * 7 / 8;
6853 ne->probability = REG_BR_PROB_BASE / 8;
6855 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6856 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6857 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6859 if (!broken_loop)
6861 struct loop *loop = alloc_loop ();
6862 loop->header = l1_bb;
6863 loop->latch = cont_bb;
6864 add_loop (loop, l1_bb->loop_father);
6865 if (safelen == NULL_TREE)
6866 loop->safelen = INT_MAX;
6867 else
6869 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
6870 if (!tree_fits_uhwi_p (safelen)
6871 || tree_to_uhwi (safelen) > INT_MAX)
6872 loop->safelen = INT_MAX;
6873 else
6874 loop->safelen = tree_to_uhwi (safelen);
6875 if (loop->safelen == 1)
6876 loop->safelen = 0;
6878 if (simduid)
6880 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
6881 cfun->has_simduid_loops = true;
6883 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
6884 the loop. */
6885 if ((flag_tree_loop_vectorize
6886 || (!global_options_set.x_flag_tree_loop_vectorize
6887 && !global_options_set.x_flag_tree_vectorize))
6888 && flag_tree_loop_optimize
6889 && loop->safelen > 1)
6891 loop->force_vectorize = true;
6892 cfun->has_force_vectorize_loops = true;
6898 /* Expand the OpenMP loop defined by REGION. */
6900 static void
6901 expand_omp_for (struct omp_region *region, gimple inner_stmt)
6903 struct omp_for_data fd;
6904 struct omp_for_data_loop *loops;
6906 loops
6907 = (struct omp_for_data_loop *)
6908 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
6909 * sizeof (struct omp_for_data_loop));
6910 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
6911 region->sched_kind = fd.sched_kind;
6913 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
6914 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6915 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6916 if (region->cont)
6918 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
6919 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6920 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6922 else
6923 /* If there isn't a continue then this is a degerate case where
6924 the introduction of abnormal edges during lowering will prevent
6925 original loops from being detected. Fix that up. */
6926 loops_state_set (LOOPS_NEED_FIXUP);
6928 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
6929 expand_omp_simd (region, &fd);
6930 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
6931 && !fd.have_ordered)
6933 if (fd.chunk_size == NULL)
6934 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
6935 else
6936 expand_omp_for_static_chunk (region, &fd, inner_stmt);
6938 else
6940 int fn_index, start_ix, next_ix;
6942 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
6943 == GF_OMP_FOR_KIND_FOR);
6944 if (fd.chunk_size == NULL
6945 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
6946 fd.chunk_size = integer_zero_node;
6947 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6948 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
6949 ? 3 : fd.sched_kind;
6950 fn_index += fd.have_ordered * 4;
6951 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
6952 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
6953 if (fd.iter_type == long_long_unsigned_type_node)
6955 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
6956 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
6957 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
6958 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
6960 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
6961 (enum built_in_function) next_ix, inner_stmt);
6964 if (gimple_in_ssa_p (cfun))
6965 update_ssa (TODO_update_ssa_only_virtuals);
6969 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
6971 v = GOMP_sections_start (n);
6973 switch (v)
6975 case 0:
6976 goto L2;
6977 case 1:
6978 section 1;
6979 goto L1;
6980 case 2:
6982 case n:
6984 default:
6985 abort ();
6988 v = GOMP_sections_next ();
6989 goto L0;
6991 reduction;
6993 If this is a combined parallel sections, replace the call to
6994 GOMP_sections_start with call to GOMP_sections_next. */
6996 static void
6997 expand_omp_sections (struct omp_region *region)
6999 tree t, u, vin = NULL, vmain, vnext, l2;
7000 unsigned len;
7001 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7002 gimple_stmt_iterator si, switch_si;
7003 gimple sections_stmt, stmt, cont;
7004 edge_iterator ei;
7005 edge e;
7006 struct omp_region *inner;
7007 unsigned i, casei;
7008 bool exit_reachable = region->cont != NULL;
7010 gcc_assert (region->exit != NULL);
7011 entry_bb = region->entry;
7012 l0_bb = single_succ (entry_bb);
7013 l1_bb = region->cont;
7014 l2_bb = region->exit;
7015 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7016 l2 = gimple_block_label (l2_bb);
7017 else
7019 /* This can happen if there are reductions. */
7020 len = EDGE_COUNT (l0_bb->succs);
7021 gcc_assert (len > 0);
7022 e = EDGE_SUCC (l0_bb, len - 1);
7023 si = gsi_last_bb (e->dest);
7024 l2 = NULL_TREE;
7025 if (gsi_end_p (si)
7026 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7027 l2 = gimple_block_label (e->dest);
7028 else
7029 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7031 si = gsi_last_bb (e->dest);
7032 if (gsi_end_p (si)
7033 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7035 l2 = gimple_block_label (e->dest);
7036 break;
7040 if (exit_reachable)
7041 default_bb = create_empty_bb (l1_bb->prev_bb);
7042 else
7043 default_bb = create_empty_bb (l0_bb);
7045 /* We will build a switch() with enough cases for all the
7046 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7047 and a default case to abort if something goes wrong. */
7048 len = EDGE_COUNT (l0_bb->succs);
7050 /* Use vec::quick_push on label_vec throughout, since we know the size
7051 in advance. */
7052 auto_vec<tree> label_vec (len);
7054 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7055 GIMPLE_OMP_SECTIONS statement. */
7056 si = gsi_last_bb (entry_bb);
7057 sections_stmt = gsi_stmt (si);
7058 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7059 vin = gimple_omp_sections_control (sections_stmt);
7060 if (!is_combined_parallel (region))
7062 /* If we are not inside a combined parallel+sections region,
7063 call GOMP_sections_start. */
7064 t = build_int_cst (unsigned_type_node, len - 1);
7065 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7066 stmt = gimple_build_call (u, 1, t);
7068 else
7070 /* Otherwise, call GOMP_sections_next. */
7071 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7072 stmt = gimple_build_call (u, 0);
7074 gimple_call_set_lhs (stmt, vin);
7075 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7076 gsi_remove (&si, true);
7078 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7079 L0_BB. */
7080 switch_si = gsi_last_bb (l0_bb);
7081 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7082 if (exit_reachable)
7084 cont = last_stmt (l1_bb);
7085 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7086 vmain = gimple_omp_continue_control_use (cont);
7087 vnext = gimple_omp_continue_control_def (cont);
7089 else
7091 vmain = vin;
7092 vnext = NULL_TREE;
7095 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7096 label_vec.quick_push (t);
7097 i = 1;
7099 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7100 for (inner = region->inner, casei = 1;
7101 inner;
7102 inner = inner->next, i++, casei++)
7104 basic_block s_entry_bb, s_exit_bb;
7106 /* Skip optional reduction region. */
7107 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7109 --i;
7110 --casei;
7111 continue;
7114 s_entry_bb = inner->entry;
7115 s_exit_bb = inner->exit;
7117 t = gimple_block_label (s_entry_bb);
7118 u = build_int_cst (unsigned_type_node, casei);
7119 u = build_case_label (u, NULL, t);
7120 label_vec.quick_push (u);
7122 si = gsi_last_bb (s_entry_bb);
7123 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7124 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7125 gsi_remove (&si, true);
7126 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7128 if (s_exit_bb == NULL)
7129 continue;
7131 si = gsi_last_bb (s_exit_bb);
7132 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7133 gsi_remove (&si, true);
7135 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7138 /* Error handling code goes in DEFAULT_BB. */
7139 t = gimple_block_label (default_bb);
7140 u = build_case_label (NULL, NULL, t);
7141 make_edge (l0_bb, default_bb, 0);
7142 if (current_loops)
7143 add_bb_to_loop (default_bb, current_loops->tree_root);
7145 stmt = gimple_build_switch (vmain, u, label_vec);
7146 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7147 gsi_remove (&switch_si, true);
7149 si = gsi_start_bb (default_bb);
7150 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7151 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7153 if (exit_reachable)
7155 tree bfn_decl;
7157 /* Code to get the next section goes in L1_BB. */
7158 si = gsi_last_bb (l1_bb);
7159 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7161 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7162 stmt = gimple_build_call (bfn_decl, 0);
7163 gimple_call_set_lhs (stmt, vnext);
7164 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7165 gsi_remove (&si, true);
7167 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7170 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7171 si = gsi_last_bb (l2_bb);
7172 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7173 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7174 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7175 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7176 else
7177 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7178 stmt = gimple_build_call (t, 0);
7179 if (gimple_omp_return_lhs (gsi_stmt (si)))
7180 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7181 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7182 gsi_remove (&si, true);
7184 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7188 /* Expand code for an OpenMP single directive. We've already expanded
7189 much of the code, here we simply place the GOMP_barrier call. */
7191 static void
7192 expand_omp_single (struct omp_region *region)
7194 basic_block entry_bb, exit_bb;
7195 gimple_stmt_iterator si;
7197 entry_bb = region->entry;
7198 exit_bb = region->exit;
7200 si = gsi_last_bb (entry_bb);
7201 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7202 gsi_remove (&si, true);
7203 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7205 si = gsi_last_bb (exit_bb);
7206 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7208 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7209 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7211 gsi_remove (&si, true);
7212 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7216 /* Generic expansion for OpenMP synchronization directives: master,
7217 ordered and critical. All we need to do here is remove the entry
7218 and exit markers for REGION. */
7220 static void
7221 expand_omp_synch (struct omp_region *region)
7223 basic_block entry_bb, exit_bb;
7224 gimple_stmt_iterator si;
7226 entry_bb = region->entry;
7227 exit_bb = region->exit;
7229 si = gsi_last_bb (entry_bb);
7230 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7231 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7232 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7233 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7234 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7235 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7236 gsi_remove (&si, true);
7237 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7239 if (exit_bb)
7241 si = gsi_last_bb (exit_bb);
7242 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7243 gsi_remove (&si, true);
7244 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7248 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7249 operation as a normal volatile load. */
7251 static bool
7252 expand_omp_atomic_load (basic_block load_bb, tree addr,
7253 tree loaded_val, int index)
7255 enum built_in_function tmpbase;
7256 gimple_stmt_iterator gsi;
7257 basic_block store_bb;
7258 location_t loc;
7259 gimple stmt;
7260 tree decl, call, type, itype;
7262 gsi = gsi_last_bb (load_bb);
7263 stmt = gsi_stmt (gsi);
7264 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7265 loc = gimple_location (stmt);
7267 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7268 is smaller than word size, then expand_atomic_load assumes that the load
7269 is atomic. We could avoid the builtin entirely in this case. */
7271 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7272 decl = builtin_decl_explicit (tmpbase);
7273 if (decl == NULL_TREE)
7274 return false;
7276 type = TREE_TYPE (loaded_val);
7277 itype = TREE_TYPE (TREE_TYPE (decl));
7279 call = build_call_expr_loc (loc, decl, 2, addr,
7280 build_int_cst (NULL,
7281 gimple_omp_atomic_seq_cst_p (stmt)
7282 ? MEMMODEL_SEQ_CST
7283 : MEMMODEL_RELAXED));
7284 if (!useless_type_conversion_p (type, itype))
7285 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7286 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7288 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7289 gsi_remove (&gsi, true);
7291 store_bb = single_succ (load_bb);
7292 gsi = gsi_last_bb (store_bb);
7293 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7294 gsi_remove (&gsi, true);
7296 if (gimple_in_ssa_p (cfun))
7297 update_ssa (TODO_update_ssa_no_phi);
7299 return true;
7302 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7303 operation as a normal volatile store. */
7305 static bool
7306 expand_omp_atomic_store (basic_block load_bb, tree addr,
7307 tree loaded_val, tree stored_val, int index)
7309 enum built_in_function tmpbase;
7310 gimple_stmt_iterator gsi;
7311 basic_block store_bb = single_succ (load_bb);
7312 location_t loc;
7313 gimple stmt;
7314 tree decl, call, type, itype;
7315 enum machine_mode imode;
7316 bool exchange;
7318 gsi = gsi_last_bb (load_bb);
7319 stmt = gsi_stmt (gsi);
7320 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7322 /* If the load value is needed, then this isn't a store but an exchange. */
7323 exchange = gimple_omp_atomic_need_value_p (stmt);
7325 gsi = gsi_last_bb (store_bb);
7326 stmt = gsi_stmt (gsi);
7327 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7328 loc = gimple_location (stmt);
7330 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7331 is smaller than word size, then expand_atomic_store assumes that the store
7332 is atomic. We could avoid the builtin entirely in this case. */
7334 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7335 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7336 decl = builtin_decl_explicit (tmpbase);
7337 if (decl == NULL_TREE)
7338 return false;
7340 type = TREE_TYPE (stored_val);
7342 /* Dig out the type of the function's second argument. */
7343 itype = TREE_TYPE (decl);
7344 itype = TYPE_ARG_TYPES (itype);
7345 itype = TREE_CHAIN (itype);
7346 itype = TREE_VALUE (itype);
7347 imode = TYPE_MODE (itype);
7349 if (exchange && !can_atomic_exchange_p (imode, true))
7350 return false;
7352 if (!useless_type_conversion_p (itype, type))
7353 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7354 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7355 build_int_cst (NULL,
7356 gimple_omp_atomic_seq_cst_p (stmt)
7357 ? MEMMODEL_SEQ_CST
7358 : MEMMODEL_RELAXED));
7359 if (exchange)
7361 if (!useless_type_conversion_p (type, itype))
7362 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7363 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7366 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7367 gsi_remove (&gsi, true);
7369 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7370 gsi = gsi_last_bb (load_bb);
7371 gsi_remove (&gsi, true);
7373 if (gimple_in_ssa_p (cfun))
7374 update_ssa (TODO_update_ssa_no_phi);
7376 return true;
7379 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7380 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7381 size of the data type, and thus usable to find the index of the builtin
7382 decl. Returns false if the expression is not of the proper form. */
7384 static bool
7385 expand_omp_atomic_fetch_op (basic_block load_bb,
7386 tree addr, tree loaded_val,
7387 tree stored_val, int index)
7389 enum built_in_function oldbase, newbase, tmpbase;
7390 tree decl, itype, call;
7391 tree lhs, rhs;
7392 basic_block store_bb = single_succ (load_bb);
7393 gimple_stmt_iterator gsi;
7394 gimple stmt;
7395 location_t loc;
7396 enum tree_code code;
7397 bool need_old, need_new;
7398 enum machine_mode imode;
7399 bool seq_cst;
7401 /* We expect to find the following sequences:
7403 load_bb:
7404 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7406 store_bb:
7407 val = tmp OP something; (or: something OP tmp)
7408 GIMPLE_OMP_STORE (val)
7410 ???FIXME: Allow a more flexible sequence.
7411 Perhaps use data flow to pick the statements.
7415 gsi = gsi_after_labels (store_bb);
7416 stmt = gsi_stmt (gsi);
7417 loc = gimple_location (stmt);
7418 if (!is_gimple_assign (stmt))
7419 return false;
7420 gsi_next (&gsi);
7421 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7422 return false;
7423 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7424 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7425 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7426 gcc_checking_assert (!need_old || !need_new);
7428 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7429 return false;
7431 /* Check for one of the supported fetch-op operations. */
7432 code = gimple_assign_rhs_code (stmt);
7433 switch (code)
7435 case PLUS_EXPR:
7436 case POINTER_PLUS_EXPR:
7437 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7438 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7439 break;
7440 case MINUS_EXPR:
7441 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7442 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7443 break;
7444 case BIT_AND_EXPR:
7445 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7446 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7447 break;
7448 case BIT_IOR_EXPR:
7449 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7450 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7451 break;
7452 case BIT_XOR_EXPR:
7453 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7454 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7455 break;
7456 default:
7457 return false;
7460 /* Make sure the expression is of the proper form. */
7461 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7462 rhs = gimple_assign_rhs2 (stmt);
7463 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7464 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7465 rhs = gimple_assign_rhs1 (stmt);
7466 else
7467 return false;
7469 tmpbase = ((enum built_in_function)
7470 ((need_new ? newbase : oldbase) + index + 1));
7471 decl = builtin_decl_explicit (tmpbase);
7472 if (decl == NULL_TREE)
7473 return false;
7474 itype = TREE_TYPE (TREE_TYPE (decl));
7475 imode = TYPE_MODE (itype);
7477 /* We could test all of the various optabs involved, but the fact of the
7478 matter is that (with the exception of i486 vs i586 and xadd) all targets
7479 that support any atomic operaton optab also implements compare-and-swap.
7480 Let optabs.c take care of expanding any compare-and-swap loop. */
7481 if (!can_compare_and_swap_p (imode, true))
7482 return false;
7484 gsi = gsi_last_bb (load_bb);
7485 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7487 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7488 It only requires that the operation happen atomically. Thus we can
7489 use the RELAXED memory model. */
7490 call = build_call_expr_loc (loc, decl, 3, addr,
7491 fold_convert_loc (loc, itype, rhs),
7492 build_int_cst (NULL,
7493 seq_cst ? MEMMODEL_SEQ_CST
7494 : MEMMODEL_RELAXED));
7496 if (need_old || need_new)
7498 lhs = need_old ? loaded_val : stored_val;
7499 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7500 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7502 else
7503 call = fold_convert_loc (loc, void_type_node, call);
7504 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7505 gsi_remove (&gsi, true);
7507 gsi = gsi_last_bb (store_bb);
7508 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7509 gsi_remove (&gsi, true);
7510 gsi = gsi_last_bb (store_bb);
7511 gsi_remove (&gsi, true);
7513 if (gimple_in_ssa_p (cfun))
7514 update_ssa (TODO_update_ssa_no_phi);
7516 return true;
7519 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7521 oldval = *addr;
7522 repeat:
7523 newval = rhs; // with oldval replacing *addr in rhs
7524 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7525 if (oldval != newval)
7526 goto repeat;
7528 INDEX is log2 of the size of the data type, and thus usable to find the
7529 index of the builtin decl. */
7531 static bool
7532 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7533 tree addr, tree loaded_val, tree stored_val,
7534 int index)
7536 tree loadedi, storedi, initial, new_storedi, old_vali;
7537 tree type, itype, cmpxchg, iaddr;
7538 gimple_stmt_iterator si;
7539 basic_block loop_header = single_succ (load_bb);
7540 gimple phi, stmt;
7541 edge e;
7542 enum built_in_function fncode;
7544 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7545 order to use the RELAXED memory model effectively. */
7546 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7547 + index + 1);
7548 cmpxchg = builtin_decl_explicit (fncode);
7549 if (cmpxchg == NULL_TREE)
7550 return false;
7551 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7552 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7554 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7555 return false;
7557 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7558 si = gsi_last_bb (load_bb);
7559 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7561 /* For floating-point values, we'll need to view-convert them to integers
7562 so that we can perform the atomic compare and swap. Simplify the
7563 following code by always setting up the "i"ntegral variables. */
7564 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7566 tree iaddr_val;
7568 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7569 true), NULL);
7570 iaddr_val
7571 = force_gimple_operand_gsi (&si,
7572 fold_convert (TREE_TYPE (iaddr), addr),
7573 false, NULL_TREE, true, GSI_SAME_STMT);
7574 stmt = gimple_build_assign (iaddr, iaddr_val);
7575 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7576 loadedi = create_tmp_var (itype, NULL);
7577 if (gimple_in_ssa_p (cfun))
7578 loadedi = make_ssa_name (loadedi, NULL);
7580 else
7582 iaddr = addr;
7583 loadedi = loaded_val;
7586 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7587 tree loaddecl = builtin_decl_explicit (fncode);
7588 if (loaddecl)
7589 initial
7590 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
7591 build_call_expr (loaddecl, 2, iaddr,
7592 build_int_cst (NULL_TREE,
7593 MEMMODEL_RELAXED)));
7594 else
7595 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
7596 build_int_cst (TREE_TYPE (iaddr), 0));
7598 initial
7599 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
7600 GSI_SAME_STMT);
7602 /* Move the value to the LOADEDI temporary. */
7603 if (gimple_in_ssa_p (cfun))
7605 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
7606 phi = create_phi_node (loadedi, loop_header);
7607 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
7608 initial);
7610 else
7611 gsi_insert_before (&si,
7612 gimple_build_assign (loadedi, initial),
7613 GSI_SAME_STMT);
7614 if (loadedi != loaded_val)
7616 gimple_stmt_iterator gsi2;
7617 tree x;
7619 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
7620 gsi2 = gsi_start_bb (loop_header);
7621 if (gimple_in_ssa_p (cfun))
7623 gimple stmt;
7624 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7625 true, GSI_SAME_STMT);
7626 stmt = gimple_build_assign (loaded_val, x);
7627 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
7629 else
7631 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
7632 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7633 true, GSI_SAME_STMT);
7636 gsi_remove (&si, true);
7638 si = gsi_last_bb (store_bb);
7639 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7641 if (iaddr == addr)
7642 storedi = stored_val;
7643 else
7644 storedi =
7645 force_gimple_operand_gsi (&si,
7646 build1 (VIEW_CONVERT_EXPR, itype,
7647 stored_val), true, NULL_TREE, true,
7648 GSI_SAME_STMT);
7650 /* Build the compare&swap statement. */
7651 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
7652 new_storedi = force_gimple_operand_gsi (&si,
7653 fold_convert (TREE_TYPE (loadedi),
7654 new_storedi),
7655 true, NULL_TREE,
7656 true, GSI_SAME_STMT);
7658 if (gimple_in_ssa_p (cfun))
7659 old_vali = loadedi;
7660 else
7662 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
7663 stmt = gimple_build_assign (old_vali, loadedi);
7664 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7666 stmt = gimple_build_assign (loadedi, new_storedi);
7667 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7670 /* Note that we always perform the comparison as an integer, even for
7671 floating point. This allows the atomic operation to properly
7672 succeed even with NaNs and -0.0. */
7673 stmt = gimple_build_cond_empty
7674 (build2 (NE_EXPR, boolean_type_node,
7675 new_storedi, old_vali));
7676 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7678 /* Update cfg. */
7679 e = single_succ_edge (store_bb);
7680 e->flags &= ~EDGE_FALLTHRU;
7681 e->flags |= EDGE_FALSE_VALUE;
7683 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
7685 /* Copy the new value to loadedi (we already did that before the condition
7686 if we are not in SSA). */
7687 if (gimple_in_ssa_p (cfun))
7689 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
7690 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
7693 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
7694 gsi_remove (&si, true);
7696 struct loop *loop = alloc_loop ();
7697 loop->header = loop_header;
7698 loop->latch = store_bb;
7699 add_loop (loop, loop_header->loop_father);
7701 if (gimple_in_ssa_p (cfun))
7702 update_ssa (TODO_update_ssa_no_phi);
7704 return true;
7707 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7709 GOMP_atomic_start ();
7710 *addr = rhs;
7711 GOMP_atomic_end ();
7713 The result is not globally atomic, but works so long as all parallel
7714 references are within #pragma omp atomic directives. According to
7715 responses received from omp@openmp.org, appears to be within spec.
7716 Which makes sense, since that's how several other compilers handle
7717 this situation as well.
7718 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
7719 expanding. STORED_VAL is the operand of the matching
7720 GIMPLE_OMP_ATOMIC_STORE.
7722 We replace
7723 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
7724 loaded_val = *addr;
7726 and replace
7727 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
7728 *addr = stored_val;
7731 static bool
7732 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
7733 tree addr, tree loaded_val, tree stored_val)
7735 gimple_stmt_iterator si;
7736 gimple stmt;
7737 tree t;
7739 si = gsi_last_bb (load_bb);
7740 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7742 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
7743 t = build_call_expr (t, 0);
7744 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7746 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
7747 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7748 gsi_remove (&si, true);
7750 si = gsi_last_bb (store_bb);
7751 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7753 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
7754 stored_val);
7755 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7757 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
7758 t = build_call_expr (t, 0);
7759 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7760 gsi_remove (&si, true);
7762 if (gimple_in_ssa_p (cfun))
7763 update_ssa (TODO_update_ssa_no_phi);
7764 return true;
7767 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
7768 using expand_omp_atomic_fetch_op. If it failed, we try to
7769 call expand_omp_atomic_pipeline, and if it fails too, the
7770 ultimate fallback is wrapping the operation in a mutex
7771 (expand_omp_atomic_mutex). REGION is the atomic region built
7772 by build_omp_regions_1(). */
7774 static void
7775 expand_omp_atomic (struct omp_region *region)
7777 basic_block load_bb = region->entry, store_bb = region->exit;
7778 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
7779 tree loaded_val = gimple_omp_atomic_load_lhs (load);
7780 tree addr = gimple_omp_atomic_load_rhs (load);
7781 tree stored_val = gimple_omp_atomic_store_val (store);
7782 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7783 HOST_WIDE_INT index;
7785 /* Make sure the type is one of the supported sizes. */
7786 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
7787 index = exact_log2 (index);
7788 if (index >= 0 && index <= 4)
7790 unsigned int align = TYPE_ALIGN_UNIT (type);
7792 /* __sync builtins require strict data alignment. */
7793 if (exact_log2 (align) >= index)
7795 /* Atomic load. */
7796 if (loaded_val == stored_val
7797 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7798 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7799 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7800 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
7801 return;
7803 /* Atomic store. */
7804 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7805 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7806 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7807 && store_bb == single_succ (load_bb)
7808 && first_stmt (store_bb) == store
7809 && expand_omp_atomic_store (load_bb, addr, loaded_val,
7810 stored_val, index))
7811 return;
7813 /* When possible, use specialized atomic update functions. */
7814 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
7815 && store_bb == single_succ (load_bb)
7816 && expand_omp_atomic_fetch_op (load_bb, addr,
7817 loaded_val, stored_val, index))
7818 return;
7820 /* If we don't have specialized __sync builtins, try and implement
7821 as a compare and swap loop. */
7822 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
7823 loaded_val, stored_val, index))
7824 return;
7828 /* The ultimate fallback is wrapping the operation in a mutex. */
7829 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
7833 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
7835 static void
7836 expand_omp_target (struct omp_region *region)
7838 basic_block entry_bb, exit_bb, new_bb;
7839 struct function *child_cfun = NULL;
7840 tree child_fn = NULL_TREE, block, t;
7841 gimple_stmt_iterator gsi;
7842 gimple entry_stmt, stmt;
7843 edge e;
7845 entry_stmt = last_stmt (region->entry);
7846 new_bb = region->entry;
7847 int kind = gimple_omp_target_kind (entry_stmt);
7848 if (kind == GF_OMP_TARGET_KIND_REGION)
7850 child_fn = gimple_omp_target_child_fn (entry_stmt);
7851 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7854 entry_bb = region->entry;
7855 exit_bb = region->exit;
7857 if (kind == GF_OMP_TARGET_KIND_REGION)
7859 unsigned srcidx, dstidx, num;
7861 /* If the target region needs data sent from the parent
7862 function, then the very first statement (except possible
7863 tree profile counter updates) of the parallel body
7864 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7865 &.OMP_DATA_O is passed as an argument to the child function,
7866 we need to replace it with the argument as seen by the child
7867 function.
7869 In most cases, this will end up being the identity assignment
7870 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7871 a function call that has been inlined, the original PARM_DECL
7872 .OMP_DATA_I may have been converted into a different local
7873 variable. In which case, we need to keep the assignment. */
7874 if (gimple_omp_target_data_arg (entry_stmt))
7876 basic_block entry_succ_bb = single_succ (entry_bb);
7877 gimple_stmt_iterator gsi;
7878 tree arg;
7879 gimple tgtcopy_stmt = NULL;
7880 tree sender
7881 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
7883 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7885 gcc_assert (!gsi_end_p (gsi));
7886 stmt = gsi_stmt (gsi);
7887 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7888 continue;
7890 if (gimple_num_ops (stmt) == 2)
7892 tree arg = gimple_assign_rhs1 (stmt);
7894 /* We're ignoring the subcode because we're
7895 effectively doing a STRIP_NOPS. */
7897 if (TREE_CODE (arg) == ADDR_EXPR
7898 && TREE_OPERAND (arg, 0) == sender)
7900 tgtcopy_stmt = stmt;
7901 break;
7906 gcc_assert (tgtcopy_stmt != NULL);
7907 arg = DECL_ARGUMENTS (child_fn);
7909 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
7910 gsi_remove (&gsi, true);
7913 /* Declare local variables needed in CHILD_CFUN. */
7914 block = DECL_INITIAL (child_fn);
7915 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7916 /* The gimplifier could record temporaries in target block
7917 rather than in containing function's local_decls chain,
7918 which would mean cgraph missed finalizing them. Do it now. */
7919 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7920 if (TREE_CODE (t) == VAR_DECL
7921 && TREE_STATIC (t)
7922 && !DECL_EXTERNAL (t))
7923 varpool_finalize_decl (t);
7924 DECL_SAVED_TREE (child_fn) = NULL;
7925 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7926 gimple_set_body (child_fn, NULL);
7927 TREE_USED (block) = 1;
7929 /* Reset DECL_CONTEXT on function arguments. */
7930 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7931 DECL_CONTEXT (t) = child_fn;
7933 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
7934 so that it can be moved to the child function. */
7935 gsi = gsi_last_bb (entry_bb);
7936 stmt = gsi_stmt (gsi);
7937 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
7938 && gimple_omp_target_kind (stmt)
7939 == GF_OMP_TARGET_KIND_REGION);
7940 gsi_remove (&gsi, true);
7941 e = split_block (entry_bb, stmt);
7942 entry_bb = e->dest;
7943 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7945 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
7946 if (exit_bb)
7948 gsi = gsi_last_bb (exit_bb);
7949 gcc_assert (!gsi_end_p (gsi)
7950 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7951 stmt = gimple_build_return (NULL);
7952 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7953 gsi_remove (&gsi, true);
7956 /* Move the target region into CHILD_CFUN. */
7958 block = gimple_block (entry_stmt);
7960 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7961 if (exit_bb)
7962 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7963 /* When the OMP expansion process cannot guarantee an up-to-date
7964 loop tree arrange for the child function to fixup loops. */
7965 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7966 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7968 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7969 num = vec_safe_length (child_cfun->local_decls);
7970 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7972 t = (*child_cfun->local_decls)[srcidx];
7973 if (DECL_CONTEXT (t) == cfun->decl)
7974 continue;
7975 if (srcidx != dstidx)
7976 (*child_cfun->local_decls)[dstidx] = t;
7977 dstidx++;
7979 if (dstidx != num)
7980 vec_safe_truncate (child_cfun->local_decls, dstidx);
7982 /* Inform the callgraph about the new function. */
7983 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
7984 cgraph_add_new_function (child_fn, true);
7986 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7987 fixed in a following pass. */
7988 push_cfun (child_cfun);
7989 rebuild_cgraph_edges ();
7991 /* Some EH regions might become dead, see PR34608. If
7992 pass_cleanup_cfg isn't the first pass to happen with the
7993 new child, these dead EH edges might cause problems.
7994 Clean them up now. */
7995 if (flag_exceptions)
7997 basic_block bb;
7998 bool changed = false;
8000 FOR_EACH_BB_FN (bb, cfun)
8001 changed |= gimple_purge_dead_eh_edges (bb);
8002 if (changed)
8003 cleanup_tree_cfg ();
8005 pop_cfun ();
8008 /* Emit a library call to launch the target region, or do data
8009 transfers. */
8010 tree t1, t2, t3, t4, device, cond, c, clauses;
8011 enum built_in_function start_ix;
8012 location_t clause_loc;
8014 clauses = gimple_omp_target_clauses (entry_stmt);
8016 if (kind == GF_OMP_TARGET_KIND_REGION)
8017 start_ix = BUILT_IN_GOMP_TARGET;
8018 else if (kind == GF_OMP_TARGET_KIND_DATA)
8019 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8020 else
8021 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8023 /* By default, the value of DEVICE is -1 (let runtime library choose)
8024 and there is no conditional. */
8025 cond = NULL_TREE;
8026 device = build_int_cst (integer_type_node, -1);
8028 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8029 if (c)
8030 cond = OMP_CLAUSE_IF_EXPR (c);
8032 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8033 if (c)
8035 device = OMP_CLAUSE_DEVICE_ID (c);
8036 clause_loc = OMP_CLAUSE_LOCATION (c);
8038 else
8039 clause_loc = gimple_location (entry_stmt);
8041 /* Ensure 'device' is of the correct type. */
8042 device = fold_convert_loc (clause_loc, integer_type_node, device);
8044 /* If we found the clause 'if (cond)', build
8045 (cond ? device : -2). */
8046 if (cond)
8048 cond = gimple_boolify (cond);
8050 basic_block cond_bb, then_bb, else_bb;
8051 edge e;
8052 tree tmp_var;
8054 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8055 if (kind != GF_OMP_TARGET_KIND_REGION)
8057 gsi = gsi_last_bb (new_bb);
8058 gsi_prev (&gsi);
8059 e = split_block (new_bb, gsi_stmt (gsi));
8061 else
8062 e = split_block (new_bb, NULL);
8063 cond_bb = e->src;
8064 new_bb = e->dest;
8065 remove_edge (e);
8067 then_bb = create_empty_bb (cond_bb);
8068 else_bb = create_empty_bb (then_bb);
8069 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8070 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8072 stmt = gimple_build_cond_empty (cond);
8073 gsi = gsi_last_bb (cond_bb);
8074 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8076 gsi = gsi_start_bb (then_bb);
8077 stmt = gimple_build_assign (tmp_var, device);
8078 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8080 gsi = gsi_start_bb (else_bb);
8081 stmt = gimple_build_assign (tmp_var,
8082 build_int_cst (integer_type_node, -2));
8083 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8085 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8086 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8087 if (current_loops)
8089 add_bb_to_loop (then_bb, cond_bb->loop_father);
8090 add_bb_to_loop (else_bb, cond_bb->loop_father);
8092 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8093 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8095 device = tmp_var;
8098 gsi = gsi_last_bb (new_bb);
8099 t = gimple_omp_target_data_arg (entry_stmt);
8100 if (t == NULL)
8102 t1 = size_zero_node;
8103 t2 = build_zero_cst (ptr_type_node);
8104 t3 = t2;
8105 t4 = t2;
8107 else
8109 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8110 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8111 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8112 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8113 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8116 gimple g;
8117 /* FIXME: This will be address of
8118 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8119 symbol, as soon as the linker plugin is able to create it for us. */
8120 tree openmp_target = build_zero_cst (ptr_type_node);
8121 if (kind == GF_OMP_TARGET_KIND_REGION)
8123 tree fnaddr = build_fold_addr_expr (child_fn);
8124 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8125 device, fnaddr, openmp_target, t1, t2, t3, t4);
8127 else
8128 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8129 device, openmp_target, t1, t2, t3, t4);
8130 gimple_set_location (g, gimple_location (entry_stmt));
8131 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8132 if (kind != GF_OMP_TARGET_KIND_REGION)
8134 g = gsi_stmt (gsi);
8135 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8136 gsi_remove (&gsi, true);
8138 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8140 gsi = gsi_last_bb (region->exit);
8141 g = gsi_stmt (gsi);
8142 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8143 gsi_remove (&gsi, true);
8148 /* Expand the parallel region tree rooted at REGION. Expansion
8149 proceeds in depth-first order. Innermost regions are expanded
8150 first. This way, parallel regions that require a new function to
8151 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8152 internal dependencies in their body. */
8154 static void
8155 expand_omp (struct omp_region *region)
8157 while (region)
8159 location_t saved_location;
8160 gimple inner_stmt = NULL;
8162 /* First, determine whether this is a combined parallel+workshare
8163 region. */
8164 if (region->type == GIMPLE_OMP_PARALLEL)
8165 determine_parallel_type (region);
8167 if (region->type == GIMPLE_OMP_FOR
8168 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8169 inner_stmt = last_stmt (region->inner->entry);
8171 if (region->inner)
8172 expand_omp (region->inner);
8174 saved_location = input_location;
8175 if (gimple_has_location (last_stmt (region->entry)))
8176 input_location = gimple_location (last_stmt (region->entry));
8178 switch (region->type)
8180 case GIMPLE_OMP_PARALLEL:
8181 case GIMPLE_OMP_TASK:
8182 expand_omp_taskreg (region);
8183 break;
8185 case GIMPLE_OMP_FOR:
8186 expand_omp_for (region, inner_stmt);
8187 break;
8189 case GIMPLE_OMP_SECTIONS:
8190 expand_omp_sections (region);
8191 break;
8193 case GIMPLE_OMP_SECTION:
8194 /* Individual omp sections are handled together with their
8195 parent GIMPLE_OMP_SECTIONS region. */
8196 break;
8198 case GIMPLE_OMP_SINGLE:
8199 expand_omp_single (region);
8200 break;
8202 case GIMPLE_OMP_MASTER:
8203 case GIMPLE_OMP_TASKGROUP:
8204 case GIMPLE_OMP_ORDERED:
8205 case GIMPLE_OMP_CRITICAL:
8206 case GIMPLE_OMP_TEAMS:
8207 expand_omp_synch (region);
8208 break;
8210 case GIMPLE_OMP_ATOMIC_LOAD:
8211 expand_omp_atomic (region);
8212 break;
8214 case GIMPLE_OMP_TARGET:
8215 expand_omp_target (region);
8216 break;
8218 default:
8219 gcc_unreachable ();
8222 input_location = saved_location;
8223 region = region->next;
8228 /* Helper for build_omp_regions. Scan the dominator tree starting at
8229 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8230 true, the function ends once a single tree is built (otherwise, whole
8231 forest of OMP constructs may be built). */
8233 static void
8234 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8235 bool single_tree)
8237 gimple_stmt_iterator gsi;
8238 gimple stmt;
8239 basic_block son;
8241 gsi = gsi_last_bb (bb);
8242 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8244 struct omp_region *region;
8245 enum gimple_code code;
8247 stmt = gsi_stmt (gsi);
8248 code = gimple_code (stmt);
8249 if (code == GIMPLE_OMP_RETURN)
8251 /* STMT is the return point out of region PARENT. Mark it
8252 as the exit point and make PARENT the immediately
8253 enclosing region. */
8254 gcc_assert (parent);
8255 region = parent;
8256 region->exit = bb;
8257 parent = parent->outer;
8259 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8261 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8262 GIMPLE_OMP_RETURN, but matches with
8263 GIMPLE_OMP_ATOMIC_LOAD. */
8264 gcc_assert (parent);
8265 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8266 region = parent;
8267 region->exit = bb;
8268 parent = parent->outer;
8271 else if (code == GIMPLE_OMP_CONTINUE)
8273 gcc_assert (parent);
8274 parent->cont = bb;
8276 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8278 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8279 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8282 else if (code == GIMPLE_OMP_TARGET
8283 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8284 new_omp_region (bb, code, parent);
8285 else
8287 /* Otherwise, this directive becomes the parent for a new
8288 region. */
8289 region = new_omp_region (bb, code, parent);
8290 parent = region;
8294 if (single_tree && !parent)
8295 return;
8297 for (son = first_dom_son (CDI_DOMINATORS, bb);
8298 son;
8299 son = next_dom_son (CDI_DOMINATORS, son))
8300 build_omp_regions_1 (son, parent, single_tree);
8303 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8304 root_omp_region. */
8306 static void
8307 build_omp_regions_root (basic_block root)
8309 gcc_assert (root_omp_region == NULL);
8310 build_omp_regions_1 (root, NULL, true);
8311 gcc_assert (root_omp_region != NULL);
8314 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8316 void
8317 omp_expand_local (basic_block head)
8319 build_omp_regions_root (head);
8320 if (dump_file && (dump_flags & TDF_DETAILS))
8322 fprintf (dump_file, "\nOMP region tree\n\n");
8323 dump_omp_region (dump_file, root_omp_region, 0);
8324 fprintf (dump_file, "\n");
8327 remove_exit_barriers (root_omp_region);
8328 expand_omp (root_omp_region);
8330 free_omp_regions ();
8333 /* Scan the CFG and build a tree of OMP regions. Return the root of
8334 the OMP region tree. */
8336 static void
8337 build_omp_regions (void)
8339 gcc_assert (root_omp_region == NULL);
8340 calculate_dominance_info (CDI_DOMINATORS);
8341 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8344 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8346 static unsigned int
8347 execute_expand_omp (void)
8349 build_omp_regions ();
8351 if (!root_omp_region)
8352 return 0;
8354 if (dump_file)
8356 fprintf (dump_file, "\nOMP region tree\n\n");
8357 dump_omp_region (dump_file, root_omp_region, 0);
8358 fprintf (dump_file, "\n");
8361 remove_exit_barriers (root_omp_region);
8363 expand_omp (root_omp_region);
8365 cleanup_tree_cfg ();
8367 free_omp_regions ();
8369 return 0;
8372 /* OMP expansion -- the default pass, run before creation of SSA form. */
8374 namespace {
8376 const pass_data pass_data_expand_omp =
8378 GIMPLE_PASS, /* type */
8379 "ompexp", /* name */
8380 OPTGROUP_NONE, /* optinfo_flags */
8381 true, /* has_execute */
8382 TV_NONE, /* tv_id */
8383 PROP_gimple_any, /* properties_required */
8384 0, /* properties_provided */
8385 0, /* properties_destroyed */
8386 0, /* todo_flags_start */
8387 0, /* todo_flags_finish */
8390 class pass_expand_omp : public gimple_opt_pass
8392 public:
8393 pass_expand_omp (gcc::context *ctxt)
8394 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8397 /* opt_pass methods: */
8398 virtual bool gate (function *)
8400 return ((flag_openmp != 0 || flag_openmp_simd != 0
8401 || flag_cilkplus != 0) && !seen_error ());
8404 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8406 }; // class pass_expand_omp
8408 } // anon namespace
8410 gimple_opt_pass *
8411 make_pass_expand_omp (gcc::context *ctxt)
8413 return new pass_expand_omp (ctxt);
8416 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8418 /* If ctx is a worksharing context inside of a cancellable parallel
8419 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8420 and conditional branch to parallel's cancel_label to handle
8421 cancellation in the implicit barrier. */
8423 static void
8424 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8426 gimple omp_return = gimple_seq_last_stmt (*body);
8427 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8428 if (gimple_omp_return_nowait_p (omp_return))
8429 return;
8430 if (ctx->outer
8431 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8432 && ctx->outer->cancellable)
8434 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8435 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8436 tree lhs = create_tmp_var (c_bool_type, NULL);
8437 gimple_omp_return_set_lhs (omp_return, lhs);
8438 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8439 gimple g = gimple_build_cond (NE_EXPR, lhs,
8440 fold_convert (c_bool_type,
8441 boolean_false_node),
8442 ctx->outer->cancel_label, fallthru_label);
8443 gimple_seq_add_stmt (body, g);
8444 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8448 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8449 CTX is the enclosing OMP context for the current statement. */
8451 static void
8452 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8454 tree block, control;
8455 gimple_stmt_iterator tgsi;
8456 gimple stmt, new_stmt, bind, t;
8457 gimple_seq ilist, dlist, olist, new_body;
8459 stmt = gsi_stmt (*gsi_p);
8461 push_gimplify_context ();
8463 dlist = NULL;
8464 ilist = NULL;
8465 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8466 &ilist, &dlist, ctx, NULL);
8468 new_body = gimple_omp_body (stmt);
8469 gimple_omp_set_body (stmt, NULL);
8470 tgsi = gsi_start (new_body);
8471 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8473 omp_context *sctx;
8474 gimple sec_start;
8476 sec_start = gsi_stmt (tgsi);
8477 sctx = maybe_lookup_ctx (sec_start);
8478 gcc_assert (sctx);
8480 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8481 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8482 GSI_CONTINUE_LINKING);
8483 gimple_omp_set_body (sec_start, NULL);
8485 if (gsi_one_before_end_p (tgsi))
8487 gimple_seq l = NULL;
8488 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8489 &l, ctx);
8490 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8491 gimple_omp_section_set_last (sec_start);
8494 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8495 GSI_CONTINUE_LINKING);
8498 block = make_node (BLOCK);
8499 bind = gimple_build_bind (NULL, new_body, block);
8501 olist = NULL;
8502 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8504 block = make_node (BLOCK);
8505 new_stmt = gimple_build_bind (NULL, NULL, block);
8506 gsi_replace (gsi_p, new_stmt, true);
8508 pop_gimplify_context (new_stmt);
8509 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8510 BLOCK_VARS (block) = gimple_bind_vars (bind);
8511 if (BLOCK_VARS (block))
8512 TREE_USED (block) = 1;
8514 new_body = NULL;
8515 gimple_seq_add_seq (&new_body, ilist);
8516 gimple_seq_add_stmt (&new_body, stmt);
8517 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8518 gimple_seq_add_stmt (&new_body, bind);
8520 control = create_tmp_var (unsigned_type_node, ".section");
8521 t = gimple_build_omp_continue (control, control);
8522 gimple_omp_sections_set_control (stmt, control);
8523 gimple_seq_add_stmt (&new_body, t);
8525 gimple_seq_add_seq (&new_body, olist);
8526 if (ctx->cancellable)
8527 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8528 gimple_seq_add_seq (&new_body, dlist);
8530 new_body = maybe_catch_exception (new_body);
8532 t = gimple_build_omp_return
8533 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8534 OMP_CLAUSE_NOWAIT));
8535 gimple_seq_add_stmt (&new_body, t);
8536 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8538 gimple_bind_set_body (new_stmt, new_body);
8542 /* A subroutine of lower_omp_single. Expand the simple form of
8543 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8545 if (GOMP_single_start ())
8546 BODY;
8547 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8549 FIXME. It may be better to delay expanding the logic of this until
8550 pass_expand_omp. The expanded logic may make the job more difficult
8551 to a synchronization analysis pass. */
8553 static void
8554 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8556 location_t loc = gimple_location (single_stmt);
8557 tree tlabel = create_artificial_label (loc);
8558 tree flabel = create_artificial_label (loc);
8559 gimple call, cond;
8560 tree lhs, decl;
8562 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8563 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8564 call = gimple_build_call (decl, 0);
8565 gimple_call_set_lhs (call, lhs);
8566 gimple_seq_add_stmt (pre_p, call);
8568 cond = gimple_build_cond (EQ_EXPR, lhs,
8569 fold_convert_loc (loc, TREE_TYPE (lhs),
8570 boolean_true_node),
8571 tlabel, flabel);
8572 gimple_seq_add_stmt (pre_p, cond);
8573 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8574 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8575 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8579 /* A subroutine of lower_omp_single. Expand the simple form of
8580 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8582 #pragma omp single copyprivate (a, b, c)
8584 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8587 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8589 BODY;
8590 copyout.a = a;
8591 copyout.b = b;
8592 copyout.c = c;
8593 GOMP_single_copy_end (&copyout);
8595 else
8597 a = copyout_p->a;
8598 b = copyout_p->b;
8599 c = copyout_p->c;
8601 GOMP_barrier ();
8604 FIXME. It may be better to delay expanding the logic of this until
8605 pass_expand_omp. The expanded logic may make the job more difficult
8606 to a synchronization analysis pass. */
8608 static void
8609 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
8611 tree ptr_type, t, l0, l1, l2, bfn_decl;
8612 gimple_seq copyin_seq;
8613 location_t loc = gimple_location (single_stmt);
8615 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8617 ptr_type = build_pointer_type (ctx->record_type);
8618 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8620 l0 = create_artificial_label (loc);
8621 l1 = create_artificial_label (loc);
8622 l2 = create_artificial_label (loc);
8624 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8625 t = build_call_expr_loc (loc, bfn_decl, 0);
8626 t = fold_convert_loc (loc, ptr_type, t);
8627 gimplify_assign (ctx->receiver_decl, t, pre_p);
8629 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8630 build_int_cst (ptr_type, 0));
8631 t = build3 (COND_EXPR, void_type_node, t,
8632 build_and_jump (&l0), build_and_jump (&l1));
8633 gimplify_and_add (t, pre_p);
8635 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8637 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8639 copyin_seq = NULL;
8640 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8641 &copyin_seq, ctx);
8643 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8644 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8645 t = build_call_expr_loc (loc, bfn_decl, 1, t);
8646 gimplify_and_add (t, pre_p);
8648 t = build_and_jump (&l2);
8649 gimplify_and_add (t, pre_p);
8651 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8653 gimple_seq_add_seq (pre_p, copyin_seq);
8655 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8659 /* Expand code for an OpenMP single directive. */
8661 static void
8662 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8664 tree block;
8665 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
8666 gimple_seq bind_body, bind_body_tail = NULL, dlist;
8668 push_gimplify_context ();
8670 block = make_node (BLOCK);
8671 bind = gimple_build_bind (NULL, NULL, block);
8672 gsi_replace (gsi_p, bind, true);
8673 bind_body = NULL;
8674 dlist = NULL;
8675 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8676 &bind_body, &dlist, ctx, NULL);
8677 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8679 gimple_seq_add_stmt (&bind_body, single_stmt);
8681 if (ctx->record_type)
8682 lower_omp_single_copy (single_stmt, &bind_body, ctx);
8683 else
8684 lower_omp_single_simple (single_stmt, &bind_body);
8686 gimple_omp_set_body (single_stmt, NULL);
8688 gimple_seq_add_seq (&bind_body, dlist);
8690 bind_body = maybe_catch_exception (bind_body);
8692 t = gimple_build_omp_return
8693 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
8694 OMP_CLAUSE_NOWAIT));
8695 gimple_seq_add_stmt (&bind_body_tail, t);
8696 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
8697 if (ctx->record_type)
8699 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8700 tree clobber = build_constructor (ctx->record_type, NULL);
8701 TREE_THIS_VOLATILE (clobber) = 1;
8702 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8703 clobber), GSI_SAME_STMT);
8705 gimple_seq_add_seq (&bind_body, bind_body_tail);
8706 gimple_bind_set_body (bind, bind_body);
8708 pop_gimplify_context (bind);
8710 gimple_bind_append_vars (bind, ctx->block_vars);
8711 BLOCK_VARS (block) = ctx->block_vars;
8712 if (BLOCK_VARS (block))
8713 TREE_USED (block) = 1;
8717 /* Expand code for an OpenMP master directive. */
8719 static void
8720 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8722 tree block, lab = NULL, x, bfn_decl;
8723 gimple stmt = gsi_stmt (*gsi_p), bind;
8724 location_t loc = gimple_location (stmt);
8725 gimple_seq tseq;
8727 push_gimplify_context ();
8729 block = make_node (BLOCK);
8730 bind = gimple_build_bind (NULL, NULL, block);
8731 gsi_replace (gsi_p, bind, true);
8732 gimple_bind_add_stmt (bind, stmt);
8734 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8735 x = build_call_expr_loc (loc, bfn_decl, 0);
8736 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
8737 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
8738 tseq = NULL;
8739 gimplify_and_add (x, &tseq);
8740 gimple_bind_add_seq (bind, tseq);
8742 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8743 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8744 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8745 gimple_omp_set_body (stmt, NULL);
8747 gimple_bind_add_stmt (bind, gimple_build_label (lab));
8749 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8751 pop_gimplify_context (bind);
8753 gimple_bind_append_vars (bind, ctx->block_vars);
8754 BLOCK_VARS (block) = ctx->block_vars;
8758 /* Expand code for an OpenMP taskgroup directive. */
8760 static void
8761 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8763 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8764 tree block = make_node (BLOCK);
8766 bind = gimple_build_bind (NULL, NULL, block);
8767 gsi_replace (gsi_p, bind, true);
8768 gimple_bind_add_stmt (bind, stmt);
8770 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
8772 gimple_bind_add_stmt (bind, x);
8774 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8775 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8776 gimple_omp_set_body (stmt, NULL);
8778 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8780 gimple_bind_append_vars (bind, ctx->block_vars);
8781 BLOCK_VARS (block) = ctx->block_vars;
8785 /* Expand code for an OpenMP ordered directive. */
8787 static void
8788 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8790 tree block;
8791 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8793 push_gimplify_context ();
8795 block = make_node (BLOCK);
8796 bind = gimple_build_bind (NULL, NULL, block);
8797 gsi_replace (gsi_p, bind, true);
8798 gimple_bind_add_stmt (bind, stmt);
8800 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
8802 gimple_bind_add_stmt (bind, x);
8804 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8805 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8806 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8807 gimple_omp_set_body (stmt, NULL);
8809 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
8810 gimple_bind_add_stmt (bind, x);
8812 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8814 pop_gimplify_context (bind);
8816 gimple_bind_append_vars (bind, ctx->block_vars);
8817 BLOCK_VARS (block) = gimple_bind_vars (bind);
8821 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
8822 substitution of a couple of function calls. But in the NAMED case,
8823 requires that languages coordinate a symbol name. It is therefore
8824 best put here in common code. */
8826 static GTY((param1_is (tree), param2_is (tree)))
8827 splay_tree critical_name_mutexes;
8829 static void
8830 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8832 tree block;
8833 tree name, lock, unlock;
8834 gimple stmt = gsi_stmt (*gsi_p), bind;
8835 location_t loc = gimple_location (stmt);
8836 gimple_seq tbody;
8838 name = gimple_omp_critical_name (stmt);
8839 if (name)
8841 tree decl;
8842 splay_tree_node n;
8844 if (!critical_name_mutexes)
8845 critical_name_mutexes
8846 = splay_tree_new_ggc (splay_tree_compare_pointers,
8847 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
8848 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
8850 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
8851 if (n == NULL)
8853 char *new_str;
8855 decl = create_tmp_var_raw (ptr_type_node, NULL);
8857 new_str = ACONCAT ((".gomp_critical_user_",
8858 IDENTIFIER_POINTER (name), NULL));
8859 DECL_NAME (decl) = get_identifier (new_str);
8860 TREE_PUBLIC (decl) = 1;
8861 TREE_STATIC (decl) = 1;
8862 DECL_COMMON (decl) = 1;
8863 DECL_ARTIFICIAL (decl) = 1;
8864 DECL_IGNORED_P (decl) = 1;
8865 varpool_finalize_decl (decl);
8867 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
8868 (splay_tree_value) decl);
8870 else
8871 decl = (tree) n->value;
8873 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
8874 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
8876 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
8877 unlock = build_call_expr_loc (loc, unlock, 1,
8878 build_fold_addr_expr_loc (loc, decl));
8880 else
8882 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
8883 lock = build_call_expr_loc (loc, lock, 0);
8885 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
8886 unlock = build_call_expr_loc (loc, unlock, 0);
8889 push_gimplify_context ();
8891 block = make_node (BLOCK);
8892 bind = gimple_build_bind (NULL, NULL, block);
8893 gsi_replace (gsi_p, bind, true);
8894 gimple_bind_add_stmt (bind, stmt);
8896 tbody = gimple_bind_body (bind);
8897 gimplify_and_add (lock, &tbody);
8898 gimple_bind_set_body (bind, tbody);
8900 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8901 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8902 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8903 gimple_omp_set_body (stmt, NULL);
8905 tbody = gimple_bind_body (bind);
8906 gimplify_and_add (unlock, &tbody);
8907 gimple_bind_set_body (bind, tbody);
8909 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8911 pop_gimplify_context (bind);
8912 gimple_bind_append_vars (bind, ctx->block_vars);
8913 BLOCK_VARS (block) = gimple_bind_vars (bind);
8917 /* A subroutine of lower_omp_for. Generate code to emit the predicate
8918 for a lastprivate clause. Given a loop control predicate of (V
8919 cond N2), we gate the clause on (!(V cond N2)). The lowered form
8920 is appended to *DLIST, iterator initialization is appended to
8921 *BODY_P. */
8923 static void
8924 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
8925 gimple_seq *dlist, struct omp_context *ctx)
8927 tree clauses, cond, vinit;
8928 enum tree_code cond_code;
8929 gimple_seq stmts;
8931 cond_code = fd->loop.cond_code;
8932 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
8934 /* When possible, use a strict equality expression. This can let VRP
8935 type optimizations deduce the value and remove a copy. */
8936 if (tree_fits_shwi_p (fd->loop.step))
8938 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
8939 if (step == 1 || step == -1)
8940 cond_code = EQ_EXPR;
8943 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
8945 clauses = gimple_omp_for_clauses (fd->for_stmt);
8946 stmts = NULL;
8947 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
8948 if (!gimple_seq_empty_p (stmts))
8950 gimple_seq_add_seq (&stmts, *dlist);
8951 *dlist = stmts;
8953 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
8954 vinit = fd->loop.n1;
8955 if (cond_code == EQ_EXPR
8956 && tree_fits_shwi_p (fd->loop.n2)
8957 && ! integer_zerop (fd->loop.n2))
8958 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
8959 else
8960 vinit = unshare_expr (vinit);
8962 /* Initialize the iterator variable, so that threads that don't execute
8963 any iterations don't execute the lastprivate clauses by accident. */
8964 gimplify_assign (fd->loop.v, vinit, body_p);
8969 /* Lower code for an OpenMP loop directive. */
8971 static void
8972 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8974 tree *rhs_p, block;
8975 struct omp_for_data fd, *fdp = NULL;
8976 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
8977 gimple_seq omp_for_body, body, dlist;
8978 size_t i;
8980 push_gimplify_context ();
8982 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
8984 block = make_node (BLOCK);
8985 new_stmt = gimple_build_bind (NULL, NULL, block);
8986 /* Replace at gsi right away, so that 'stmt' is no member
8987 of a sequence anymore as we're going to add to to a different
8988 one below. */
8989 gsi_replace (gsi_p, new_stmt, true);
8991 /* Move declaration of temporaries in the loop body before we make
8992 it go away. */
8993 omp_for_body = gimple_omp_body (stmt);
8994 if (!gimple_seq_empty_p (omp_for_body)
8995 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
8997 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
8998 tree vars = gimple_bind_vars (inner_bind);
8999 gimple_bind_append_vars (new_stmt, vars);
9000 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9001 keep them on the inner_bind and it's block. */
9002 gimple_bind_set_vars (inner_bind, NULL_TREE);
9003 if (gimple_bind_block (inner_bind))
9004 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9007 if (gimple_omp_for_combined_into_p (stmt))
9009 extract_omp_for_data (stmt, &fd, NULL);
9010 fdp = &fd;
9012 /* We need two temporaries with fd.loop.v type (istart/iend)
9013 and then (fd.collapse - 1) temporaries with the same
9014 type for count2 ... countN-1 vars if not constant. */
9015 size_t count = 2;
9016 tree type = fd.iter_type;
9017 if (fd.collapse > 1
9018 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9019 count += fd.collapse - 1;
9020 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9021 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9022 tree clauses = *pc;
9023 if (parallel_for)
9024 outerc
9025 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9026 OMP_CLAUSE__LOOPTEMP_);
9027 for (i = 0; i < count; i++)
9029 tree temp;
9030 if (parallel_for)
9032 gcc_assert (outerc);
9033 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9034 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9035 OMP_CLAUSE__LOOPTEMP_);
9037 else
9038 temp = create_tmp_var (type, NULL);
9039 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9040 OMP_CLAUSE_DECL (*pc) = temp;
9041 pc = &OMP_CLAUSE_CHAIN (*pc);
9043 *pc = clauses;
9046 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9047 dlist = NULL;
9048 body = NULL;
9049 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9050 fdp);
9051 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9053 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9055 /* Lower the header expressions. At this point, we can assume that
9056 the header is of the form:
9058 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9060 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9061 using the .omp_data_s mapping, if needed. */
9062 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9064 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9065 if (!is_gimple_min_invariant (*rhs_p))
9066 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9068 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9069 if (!is_gimple_min_invariant (*rhs_p))
9070 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9072 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9073 if (!is_gimple_min_invariant (*rhs_p))
9074 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9077 /* Once lowered, extract the bounds and clauses. */
9078 extract_omp_for_data (stmt, &fd, NULL);
9080 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9082 gimple_seq_add_stmt (&body, stmt);
9083 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9085 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9086 fd.loop.v));
9088 /* After the loop, add exit clauses. */
9089 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9091 if (ctx->cancellable)
9092 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9094 gimple_seq_add_seq (&body, dlist);
9096 body = maybe_catch_exception (body);
9098 /* Region exit marker goes at the end of the loop body. */
9099 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9100 maybe_add_implicit_barrier_cancel (ctx, &body);
9101 pop_gimplify_context (new_stmt);
9103 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9104 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9105 if (BLOCK_VARS (block))
9106 TREE_USED (block) = 1;
9108 gimple_bind_set_body (new_stmt, body);
9109 gimple_omp_set_body (stmt, NULL);
9110 gimple_omp_for_set_pre_body (stmt, NULL);
9113 /* Callback for walk_stmts. Check if the current statement only contains
9114 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9116 static tree
9117 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9118 bool *handled_ops_p,
9119 struct walk_stmt_info *wi)
9121 int *info = (int *) wi->info;
9122 gimple stmt = gsi_stmt (*gsi_p);
9124 *handled_ops_p = true;
9125 switch (gimple_code (stmt))
9127 WALK_SUBSTMTS;
9129 case GIMPLE_OMP_FOR:
9130 case GIMPLE_OMP_SECTIONS:
9131 *info = *info == 0 ? 1 : -1;
9132 break;
9133 default:
9134 *info = -1;
9135 break;
9137 return NULL;
9140 struct omp_taskcopy_context
9142 /* This field must be at the beginning, as we do "inheritance": Some
9143 callback functions for tree-inline.c (e.g., omp_copy_decl)
9144 receive a copy_body_data pointer that is up-casted to an
9145 omp_context pointer. */
9146 copy_body_data cb;
9147 omp_context *ctx;
9150 static tree
9151 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9153 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9155 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9156 return create_tmp_var (TREE_TYPE (var), NULL);
9158 return var;
9161 static tree
9162 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9164 tree name, new_fields = NULL, type, f;
9166 type = lang_hooks.types.make_type (RECORD_TYPE);
9167 name = DECL_NAME (TYPE_NAME (orig_type));
9168 name = build_decl (gimple_location (tcctx->ctx->stmt),
9169 TYPE_DECL, name, type);
9170 TYPE_NAME (type) = name;
9172 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9174 tree new_f = copy_node (f);
9175 DECL_CONTEXT (new_f) = type;
9176 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9177 TREE_CHAIN (new_f) = new_fields;
9178 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9179 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9180 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9181 &tcctx->cb, NULL);
9182 new_fields = new_f;
9183 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
9185 TYPE_FIELDS (type) = nreverse (new_fields);
9186 layout_type (type);
9187 return type;
9190 /* Create task copyfn. */
9192 static void
9193 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9195 struct function *child_cfun;
9196 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9197 tree record_type, srecord_type, bind, list;
9198 bool record_needs_remap = false, srecord_needs_remap = false;
9199 splay_tree_node n;
9200 struct omp_taskcopy_context tcctx;
9201 location_t loc = gimple_location (task_stmt);
9203 child_fn = gimple_omp_task_copy_fn (task_stmt);
9204 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9205 gcc_assert (child_cfun->cfg == NULL);
9206 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9208 /* Reset DECL_CONTEXT on function arguments. */
9209 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9210 DECL_CONTEXT (t) = child_fn;
9212 /* Populate the function. */
9213 push_gimplify_context ();
9214 push_cfun (child_cfun);
9216 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9217 TREE_SIDE_EFFECTS (bind) = 1;
9218 list = NULL;
9219 DECL_SAVED_TREE (child_fn) = bind;
9220 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9222 /* Remap src and dst argument types if needed. */
9223 record_type = ctx->record_type;
9224 srecord_type = ctx->srecord_type;
9225 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9226 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9228 record_needs_remap = true;
9229 break;
9231 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9232 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9234 srecord_needs_remap = true;
9235 break;
9238 if (record_needs_remap || srecord_needs_remap)
9240 memset (&tcctx, '\0', sizeof (tcctx));
9241 tcctx.cb.src_fn = ctx->cb.src_fn;
9242 tcctx.cb.dst_fn = child_fn;
9243 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
9244 gcc_checking_assert (tcctx.cb.src_node);
9245 tcctx.cb.dst_node = tcctx.cb.src_node;
9246 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9247 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9248 tcctx.cb.eh_lp_nr = 0;
9249 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9250 tcctx.cb.decl_map = pointer_map_create ();
9251 tcctx.ctx = ctx;
9253 if (record_needs_remap)
9254 record_type = task_copyfn_remap_type (&tcctx, record_type);
9255 if (srecord_needs_remap)
9256 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9258 else
9259 tcctx.cb.decl_map = NULL;
9261 arg = DECL_ARGUMENTS (child_fn);
9262 TREE_TYPE (arg) = build_pointer_type (record_type);
9263 sarg = DECL_CHAIN (arg);
9264 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9266 /* First pass: initialize temporaries used in record_type and srecord_type
9267 sizes and field offsets. */
9268 if (tcctx.cb.decl_map)
9269 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9270 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9272 tree *p;
9274 decl = OMP_CLAUSE_DECL (c);
9275 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
9276 if (p == NULL)
9277 continue;
9278 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9279 sf = (tree) n->value;
9280 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9281 src = build_simple_mem_ref_loc (loc, sarg);
9282 src = omp_build_component_ref (src, sf);
9283 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9284 append_to_statement_list (t, &list);
9287 /* Second pass: copy shared var pointers and copy construct non-VLA
9288 firstprivate vars. */
9289 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9290 switch (OMP_CLAUSE_CODE (c))
9292 case OMP_CLAUSE_SHARED:
9293 decl = OMP_CLAUSE_DECL (c);
9294 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9295 if (n == NULL)
9296 break;
9297 f = (tree) n->value;
9298 if (tcctx.cb.decl_map)
9299 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9300 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9301 sf = (tree) n->value;
9302 if (tcctx.cb.decl_map)
9303 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9304 src = build_simple_mem_ref_loc (loc, sarg);
9305 src = omp_build_component_ref (src, sf);
9306 dst = build_simple_mem_ref_loc (loc, arg);
9307 dst = omp_build_component_ref (dst, f);
9308 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9309 append_to_statement_list (t, &list);
9310 break;
9311 case OMP_CLAUSE_FIRSTPRIVATE:
9312 decl = OMP_CLAUSE_DECL (c);
9313 if (is_variable_sized (decl))
9314 break;
9315 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9316 if (n == NULL)
9317 break;
9318 f = (tree) n->value;
9319 if (tcctx.cb.decl_map)
9320 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9321 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9322 if (n != NULL)
9324 sf = (tree) n->value;
9325 if (tcctx.cb.decl_map)
9326 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9327 src = build_simple_mem_ref_loc (loc, sarg);
9328 src = omp_build_component_ref (src, sf);
9329 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9330 src = build_simple_mem_ref_loc (loc, src);
9332 else
9333 src = decl;
9334 dst = build_simple_mem_ref_loc (loc, arg);
9335 dst = omp_build_component_ref (dst, f);
9336 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9337 append_to_statement_list (t, &list);
9338 break;
9339 case OMP_CLAUSE_PRIVATE:
9340 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9341 break;
9342 decl = OMP_CLAUSE_DECL (c);
9343 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9344 f = (tree) n->value;
9345 if (tcctx.cb.decl_map)
9346 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9347 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9348 if (n != NULL)
9350 sf = (tree) n->value;
9351 if (tcctx.cb.decl_map)
9352 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9353 src = build_simple_mem_ref_loc (loc, sarg);
9354 src = omp_build_component_ref (src, sf);
9355 if (use_pointer_for_field (decl, NULL))
9356 src = build_simple_mem_ref_loc (loc, src);
9358 else
9359 src = decl;
9360 dst = build_simple_mem_ref_loc (loc, arg);
9361 dst = omp_build_component_ref (dst, f);
9362 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9363 append_to_statement_list (t, &list);
9364 break;
9365 default:
9366 break;
9369 /* Last pass: handle VLA firstprivates. */
9370 if (tcctx.cb.decl_map)
9371 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9372 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9374 tree ind, ptr, df;
9376 decl = OMP_CLAUSE_DECL (c);
9377 if (!is_variable_sized (decl))
9378 continue;
9379 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9380 if (n == NULL)
9381 continue;
9382 f = (tree) n->value;
9383 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9384 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9385 ind = DECL_VALUE_EXPR (decl);
9386 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9387 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9388 n = splay_tree_lookup (ctx->sfield_map,
9389 (splay_tree_key) TREE_OPERAND (ind, 0));
9390 sf = (tree) n->value;
9391 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9392 src = build_simple_mem_ref_loc (loc, sarg);
9393 src = omp_build_component_ref (src, sf);
9394 src = build_simple_mem_ref_loc (loc, src);
9395 dst = build_simple_mem_ref_loc (loc, arg);
9396 dst = omp_build_component_ref (dst, f);
9397 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9398 append_to_statement_list (t, &list);
9399 n = splay_tree_lookup (ctx->field_map,
9400 (splay_tree_key) TREE_OPERAND (ind, 0));
9401 df = (tree) n->value;
9402 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
9403 ptr = build_simple_mem_ref_loc (loc, arg);
9404 ptr = omp_build_component_ref (ptr, df);
9405 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9406 build_fold_addr_expr_loc (loc, dst));
9407 append_to_statement_list (t, &list);
9410 t = build1 (RETURN_EXPR, void_type_node, NULL);
9411 append_to_statement_list (t, &list);
9413 if (tcctx.cb.decl_map)
9414 pointer_map_destroy (tcctx.cb.decl_map);
9415 pop_gimplify_context (NULL);
9416 BIND_EXPR_BODY (bind) = list;
9417 pop_cfun ();
9420 static void
9421 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9423 tree c, clauses;
9424 gimple g;
9425 size_t n_in = 0, n_out = 0, idx = 2, i;
9427 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9428 OMP_CLAUSE_DEPEND);
9429 gcc_assert (clauses);
9430 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9431 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9432 switch (OMP_CLAUSE_DEPEND_KIND (c))
9434 case OMP_CLAUSE_DEPEND_IN:
9435 n_in++;
9436 break;
9437 case OMP_CLAUSE_DEPEND_OUT:
9438 case OMP_CLAUSE_DEPEND_INOUT:
9439 n_out++;
9440 break;
9441 default:
9442 gcc_unreachable ();
9444 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9445 tree array = create_tmp_var (type, NULL);
9446 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9447 NULL_TREE);
9448 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9449 gimple_seq_add_stmt (iseq, g);
9450 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9451 NULL_TREE);
9452 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9453 gimple_seq_add_stmt (iseq, g);
9454 for (i = 0; i < 2; i++)
9456 if ((i ? n_in : n_out) == 0)
9457 continue;
9458 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9459 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9460 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9462 tree t = OMP_CLAUSE_DECL (c);
9463 t = fold_convert (ptr_type_node, t);
9464 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9465 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9466 NULL_TREE, NULL_TREE);
9467 g = gimple_build_assign (r, t);
9468 gimple_seq_add_stmt (iseq, g);
9471 tree *p = gimple_omp_task_clauses_ptr (stmt);
9472 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9473 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9474 OMP_CLAUSE_CHAIN (c) = *p;
9475 *p = c;
9476 tree clobber = build_constructor (type, NULL);
9477 TREE_THIS_VOLATILE (clobber) = 1;
9478 g = gimple_build_assign (array, clobber);
9479 gimple_seq_add_stmt (oseq, g);
9482 /* Lower the OpenMP parallel or task directive in the current statement
9483 in GSI_P. CTX holds context information for the directive. */
9485 static void
9486 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9488 tree clauses;
9489 tree child_fn, t;
9490 gimple stmt = gsi_stmt (*gsi_p);
9491 gimple par_bind, bind, dep_bind = NULL;
9492 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9493 location_t loc = gimple_location (stmt);
9495 clauses = gimple_omp_taskreg_clauses (stmt);
9496 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9497 par_body = gimple_bind_body (par_bind);
9498 child_fn = ctx->cb.dst_fn;
9499 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9500 && !gimple_omp_parallel_combined_p (stmt))
9502 struct walk_stmt_info wi;
9503 int ws_num = 0;
9505 memset (&wi, 0, sizeof (wi));
9506 wi.info = &ws_num;
9507 wi.val_only = true;
9508 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9509 if (ws_num == 1)
9510 gimple_omp_parallel_set_combined_p (stmt, true);
9512 gimple_seq dep_ilist = NULL;
9513 gimple_seq dep_olist = NULL;
9514 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9515 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9517 push_gimplify_context ();
9518 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9519 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9522 if (ctx->srecord_type)
9523 create_task_copyfn (stmt, ctx);
9525 push_gimplify_context ();
9527 par_olist = NULL;
9528 par_ilist = NULL;
9529 par_rlist = NULL;
9530 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9531 lower_omp (&par_body, ctx);
9532 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9533 lower_reduction_clauses (clauses, &par_rlist, ctx);
9535 /* Declare all the variables created by mapping and the variables
9536 declared in the scope of the parallel body. */
9537 record_vars_into (ctx->block_vars, child_fn);
9538 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9540 if (ctx->record_type)
9542 ctx->sender_decl
9543 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9544 : ctx->record_type, ".omp_data_o");
9545 DECL_NAMELESS (ctx->sender_decl) = 1;
9546 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9547 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9550 olist = NULL;
9551 ilist = NULL;
9552 lower_send_clauses (clauses, &ilist, &olist, ctx);
9553 lower_send_shared_vars (&ilist, &olist, ctx);
9555 if (ctx->record_type)
9557 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9558 TREE_THIS_VOLATILE (clobber) = 1;
9559 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9560 clobber));
9563 /* Once all the expansions are done, sequence all the different
9564 fragments inside gimple_omp_body. */
9566 new_body = NULL;
9568 if (ctx->record_type)
9570 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9571 /* fixup_child_record_type might have changed receiver_decl's type. */
9572 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9573 gimple_seq_add_stmt (&new_body,
9574 gimple_build_assign (ctx->receiver_decl, t));
9577 gimple_seq_add_seq (&new_body, par_ilist);
9578 gimple_seq_add_seq (&new_body, par_body);
9579 gimple_seq_add_seq (&new_body, par_rlist);
9580 if (ctx->cancellable)
9581 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9582 gimple_seq_add_seq (&new_body, par_olist);
9583 new_body = maybe_catch_exception (new_body);
9584 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9585 gimple_omp_set_body (stmt, new_body);
9587 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9588 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
9589 gimple_bind_add_seq (bind, ilist);
9590 gimple_bind_add_stmt (bind, stmt);
9591 gimple_bind_add_seq (bind, olist);
9593 pop_gimplify_context (NULL);
9595 if (dep_bind)
9597 gimple_bind_add_seq (dep_bind, dep_ilist);
9598 gimple_bind_add_stmt (dep_bind, bind);
9599 gimple_bind_add_seq (dep_bind, dep_olist);
9600 pop_gimplify_context (dep_bind);
9604 /* Lower the OpenMP target directive in the current statement
9605 in GSI_P. CTX holds context information for the directive. */
9607 static void
9608 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9610 tree clauses;
9611 tree child_fn, t, c;
9612 gimple stmt = gsi_stmt (*gsi_p);
9613 gimple tgt_bind = NULL, bind;
9614 gimple_seq tgt_body = NULL, olist, ilist, new_body;
9615 location_t loc = gimple_location (stmt);
9616 int kind = gimple_omp_target_kind (stmt);
9617 unsigned int map_cnt = 0;
9619 clauses = gimple_omp_target_clauses (stmt);
9620 if (kind == GF_OMP_TARGET_KIND_REGION)
9622 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9623 tgt_body = gimple_bind_body (tgt_bind);
9625 else if (kind == GF_OMP_TARGET_KIND_DATA)
9626 tgt_body = gimple_omp_body (stmt);
9627 child_fn = ctx->cb.dst_fn;
9629 push_gimplify_context ();
9631 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9632 switch (OMP_CLAUSE_CODE (c))
9634 tree var, x;
9636 default:
9637 break;
9638 case OMP_CLAUSE_MAP:
9639 case OMP_CLAUSE_TO:
9640 case OMP_CLAUSE_FROM:
9641 var = OMP_CLAUSE_DECL (c);
9642 if (!DECL_P (var))
9644 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
9645 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9646 map_cnt++;
9647 continue;
9650 if (DECL_SIZE (var)
9651 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
9653 tree var2 = DECL_VALUE_EXPR (var);
9654 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
9655 var2 = TREE_OPERAND (var2, 0);
9656 gcc_assert (DECL_P (var2));
9657 var = var2;
9660 if (!maybe_lookup_field (var, ctx))
9661 continue;
9663 if (kind == GF_OMP_TARGET_KIND_REGION)
9665 x = build_receiver_ref (var, true, ctx);
9666 tree new_var = lookup_decl (var, ctx);
9667 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9668 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9669 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9670 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
9671 x = build_simple_mem_ref (x);
9672 SET_DECL_VALUE_EXPR (new_var, x);
9673 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
9675 map_cnt++;
9678 if (kind == GF_OMP_TARGET_KIND_REGION)
9680 target_nesting_level++;
9681 lower_omp (&tgt_body, ctx);
9682 target_nesting_level--;
9684 else if (kind == GF_OMP_TARGET_KIND_DATA)
9685 lower_omp (&tgt_body, ctx);
9687 if (kind == GF_OMP_TARGET_KIND_REGION)
9689 /* Declare all the variables created by mapping and the variables
9690 declared in the scope of the target body. */
9691 record_vars_into (ctx->block_vars, child_fn);
9692 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
9695 olist = NULL;
9696 ilist = NULL;
9697 if (ctx->record_type)
9699 ctx->sender_decl
9700 = create_tmp_var (ctx->record_type, ".omp_data_arr");
9701 DECL_NAMELESS (ctx->sender_decl) = 1;
9702 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9703 t = make_tree_vec (3);
9704 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
9705 TREE_VEC_ELT (t, 1)
9706 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
9707 ".omp_data_sizes");
9708 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
9709 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
9710 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
9711 TREE_VEC_ELT (t, 2)
9712 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
9713 map_cnt),
9714 ".omp_data_kinds");
9715 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
9716 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
9717 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
9718 gimple_omp_target_set_data_arg (stmt, t);
9720 vec<constructor_elt, va_gc> *vsize;
9721 vec<constructor_elt, va_gc> *vkind;
9722 vec_alloc (vsize, map_cnt);
9723 vec_alloc (vkind, map_cnt);
9724 unsigned int map_idx = 0;
9726 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9727 switch (OMP_CLAUSE_CODE (c))
9729 tree ovar, nc;
9731 default:
9732 break;
9733 case OMP_CLAUSE_MAP:
9734 case OMP_CLAUSE_TO:
9735 case OMP_CLAUSE_FROM:
9736 nc = c;
9737 ovar = OMP_CLAUSE_DECL (c);
9738 if (!DECL_P (ovar))
9740 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9741 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9743 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
9744 == get_base_address (ovar));
9745 nc = OMP_CLAUSE_CHAIN (c);
9746 ovar = OMP_CLAUSE_DECL (nc);
9748 else
9750 tree x = build_sender_ref (ovar, ctx);
9751 tree v
9752 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
9753 gimplify_assign (x, v, &ilist);
9754 nc = NULL_TREE;
9757 else
9759 if (DECL_SIZE (ovar)
9760 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
9762 tree ovar2 = DECL_VALUE_EXPR (ovar);
9763 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
9764 ovar2 = TREE_OPERAND (ovar2, 0);
9765 gcc_assert (DECL_P (ovar2));
9766 ovar = ovar2;
9768 if (!maybe_lookup_field (ovar, ctx))
9769 continue;
9772 if (nc)
9774 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
9775 tree x = build_sender_ref (ovar, ctx);
9776 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9777 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9778 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9779 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
9781 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9782 tree avar
9783 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
9784 mark_addressable (avar);
9785 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
9786 avar = build_fold_addr_expr (avar);
9787 gimplify_assign (x, avar, &ilist);
9789 else if (is_gimple_reg (var))
9791 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9792 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
9793 mark_addressable (avar);
9794 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
9795 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
9796 gimplify_assign (avar, var, &ilist);
9797 avar = build_fold_addr_expr (avar);
9798 gimplify_assign (x, avar, &ilist);
9799 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
9800 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
9801 && !TYPE_READONLY (TREE_TYPE (var)))
9803 x = build_sender_ref (ovar, ctx);
9804 x = build_simple_mem_ref (x);
9805 gimplify_assign (var, x, &olist);
9808 else
9810 var = build_fold_addr_expr (var);
9811 gimplify_assign (x, var, &ilist);
9814 tree s = OMP_CLAUSE_SIZE (c);
9815 if (s == NULL_TREE)
9816 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
9817 s = fold_convert (size_type_node, s);
9818 tree purpose = size_int (map_idx++);
9819 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
9820 if (TREE_CODE (s) != INTEGER_CST)
9821 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
9823 unsigned char tkind = 0;
9824 switch (OMP_CLAUSE_CODE (c))
9826 case OMP_CLAUSE_MAP:
9827 tkind = OMP_CLAUSE_MAP_KIND (c);
9828 break;
9829 case OMP_CLAUSE_TO:
9830 tkind = OMP_CLAUSE_MAP_TO;
9831 break;
9832 case OMP_CLAUSE_FROM:
9833 tkind = OMP_CLAUSE_MAP_FROM;
9834 break;
9835 default:
9836 gcc_unreachable ();
9838 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
9839 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
9840 talign = DECL_ALIGN_UNIT (ovar);
9841 talign = ceil_log2 (talign);
9842 tkind |= talign << 3;
9843 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
9844 build_int_cst (unsigned_char_type_node,
9845 tkind));
9846 if (nc && nc != c)
9847 c = nc;
9850 gcc_assert (map_idx == map_cnt);
9852 DECL_INITIAL (TREE_VEC_ELT (t, 1))
9853 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
9854 DECL_INITIAL (TREE_VEC_ELT (t, 2))
9855 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
9856 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
9858 gimple_seq initlist = NULL;
9859 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
9860 TREE_VEC_ELT (t, 1)),
9861 &initlist, true, NULL_TREE);
9862 gimple_seq_add_seq (&ilist, initlist);
9864 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
9865 NULL);
9866 TREE_THIS_VOLATILE (clobber) = 1;
9867 gimple_seq_add_stmt (&olist,
9868 gimple_build_assign (TREE_VEC_ELT (t, 1),
9869 clobber));
9872 tree clobber = build_constructor (ctx->record_type, NULL);
9873 TREE_THIS_VOLATILE (clobber) = 1;
9874 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9875 clobber));
9878 /* Once all the expansions are done, sequence all the different
9879 fragments inside gimple_omp_body. */
9881 new_body = NULL;
9883 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
9885 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9886 /* fixup_child_record_type might have changed receiver_decl's type. */
9887 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9888 gimple_seq_add_stmt (&new_body,
9889 gimple_build_assign (ctx->receiver_decl, t));
9892 if (kind == GF_OMP_TARGET_KIND_REGION)
9894 gimple_seq_add_seq (&new_body, tgt_body);
9895 new_body = maybe_catch_exception (new_body);
9897 else if (kind == GF_OMP_TARGET_KIND_DATA)
9898 new_body = tgt_body;
9899 if (kind != GF_OMP_TARGET_KIND_UPDATE)
9901 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9902 gimple_omp_set_body (stmt, new_body);
9905 bind = gimple_build_bind (NULL, NULL,
9906 tgt_bind ? gimple_bind_block (tgt_bind)
9907 : NULL_TREE);
9908 gsi_replace (gsi_p, bind, true);
9909 gimple_bind_add_seq (bind, ilist);
9910 gimple_bind_add_stmt (bind, stmt);
9911 gimple_bind_add_seq (bind, olist);
9913 pop_gimplify_context (NULL);
9916 /* Expand code for an OpenMP teams directive. */
9918 static void
9919 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9921 gimple teams_stmt = gsi_stmt (*gsi_p);
9922 push_gimplify_context ();
9924 tree block = make_node (BLOCK);
9925 gimple bind = gimple_build_bind (NULL, NULL, block);
9926 gsi_replace (gsi_p, bind, true);
9927 gimple_seq bind_body = NULL;
9928 gimple_seq dlist = NULL;
9929 gimple_seq olist = NULL;
9931 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9932 OMP_CLAUSE_NUM_TEAMS);
9933 if (num_teams == NULL_TREE)
9934 num_teams = build_int_cst (unsigned_type_node, 0);
9935 else
9937 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
9938 num_teams = fold_convert (unsigned_type_node, num_teams);
9939 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
9941 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9942 OMP_CLAUSE_THREAD_LIMIT);
9943 if (thread_limit == NULL_TREE)
9944 thread_limit = build_int_cst (unsigned_type_node, 0);
9945 else
9947 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
9948 thread_limit = fold_convert (unsigned_type_node, thread_limit);
9949 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
9950 fb_rvalue);
9953 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
9954 &bind_body, &dlist, ctx, NULL);
9955 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
9956 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
9957 gimple_seq_add_stmt (&bind_body, teams_stmt);
9959 location_t loc = gimple_location (teams_stmt);
9960 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
9961 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
9962 gimple_set_location (call, loc);
9963 gimple_seq_add_stmt (&bind_body, call);
9965 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
9966 gimple_omp_set_body (teams_stmt, NULL);
9967 gimple_seq_add_seq (&bind_body, olist);
9968 gimple_seq_add_seq (&bind_body, dlist);
9969 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
9970 gimple_bind_set_body (bind, bind_body);
9972 pop_gimplify_context (bind);
9974 gimple_bind_append_vars (bind, ctx->block_vars);
9975 BLOCK_VARS (block) = ctx->block_vars;
9976 if (BLOCK_VARS (block))
9977 TREE_USED (block) = 1;
9981 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
9982 regimplified. If DATA is non-NULL, lower_omp_1 is outside
9983 of OpenMP context, but with task_shared_vars set. */
9985 static tree
9986 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
9987 void *data)
9989 tree t = *tp;
9991 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
9992 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9993 return t;
9995 if (task_shared_vars
9996 && DECL_P (t)
9997 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
9998 return t;
10000 /* If a global variable has been privatized, TREE_CONSTANT on
10001 ADDR_EXPR might be wrong. */
10002 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10003 recompute_tree_invariant_for_addr_expr (t);
10005 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10006 return NULL_TREE;
10009 static void
10010 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10012 gimple stmt = gsi_stmt (*gsi_p);
10013 struct walk_stmt_info wi;
10015 if (gimple_has_location (stmt))
10016 input_location = gimple_location (stmt);
10018 if (task_shared_vars)
10019 memset (&wi, '\0', sizeof (wi));
10021 /* If we have issued syntax errors, avoid doing any heavy lifting.
10022 Just replace the OpenMP directives with a NOP to avoid
10023 confusing RTL expansion. */
10024 if (seen_error () && is_gimple_omp (stmt))
10026 gsi_replace (gsi_p, gimple_build_nop (), true);
10027 return;
10030 switch (gimple_code (stmt))
10032 case GIMPLE_COND:
10033 if ((ctx || task_shared_vars)
10034 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
10035 ctx ? NULL : &wi, NULL)
10036 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
10037 ctx ? NULL : &wi, NULL)))
10038 gimple_regimplify_operands (stmt, gsi_p);
10039 break;
10040 case GIMPLE_CATCH:
10041 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
10042 break;
10043 case GIMPLE_EH_FILTER:
10044 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10045 break;
10046 case GIMPLE_TRY:
10047 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10048 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10049 break;
10050 case GIMPLE_TRANSACTION:
10051 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
10052 break;
10053 case GIMPLE_BIND:
10054 lower_omp (gimple_bind_body_ptr (stmt), ctx);
10055 break;
10056 case GIMPLE_OMP_PARALLEL:
10057 case GIMPLE_OMP_TASK:
10058 ctx = maybe_lookup_ctx (stmt);
10059 gcc_assert (ctx);
10060 if (ctx->cancellable)
10061 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10062 lower_omp_taskreg (gsi_p, ctx);
10063 break;
10064 case GIMPLE_OMP_FOR:
10065 ctx = maybe_lookup_ctx (stmt);
10066 gcc_assert (ctx);
10067 if (ctx->cancellable)
10068 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10069 lower_omp_for (gsi_p, ctx);
10070 break;
10071 case GIMPLE_OMP_SECTIONS:
10072 ctx = maybe_lookup_ctx (stmt);
10073 gcc_assert (ctx);
10074 if (ctx->cancellable)
10075 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10076 lower_omp_sections (gsi_p, ctx);
10077 break;
10078 case GIMPLE_OMP_SINGLE:
10079 ctx = maybe_lookup_ctx (stmt);
10080 gcc_assert (ctx);
10081 lower_omp_single (gsi_p, ctx);
10082 break;
10083 case GIMPLE_OMP_MASTER:
10084 ctx = maybe_lookup_ctx (stmt);
10085 gcc_assert (ctx);
10086 lower_omp_master (gsi_p, ctx);
10087 break;
10088 case GIMPLE_OMP_TASKGROUP:
10089 ctx = maybe_lookup_ctx (stmt);
10090 gcc_assert (ctx);
10091 lower_omp_taskgroup (gsi_p, ctx);
10092 break;
10093 case GIMPLE_OMP_ORDERED:
10094 ctx = maybe_lookup_ctx (stmt);
10095 gcc_assert (ctx);
10096 lower_omp_ordered (gsi_p, ctx);
10097 break;
10098 case GIMPLE_OMP_CRITICAL:
10099 ctx = maybe_lookup_ctx (stmt);
10100 gcc_assert (ctx);
10101 lower_omp_critical (gsi_p, ctx);
10102 break;
10103 case GIMPLE_OMP_ATOMIC_LOAD:
10104 if ((ctx || task_shared_vars)
10105 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
10106 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10107 gimple_regimplify_operands (stmt, gsi_p);
10108 break;
10109 case GIMPLE_OMP_TARGET:
10110 ctx = maybe_lookup_ctx (stmt);
10111 gcc_assert (ctx);
10112 lower_omp_target (gsi_p, ctx);
10113 break;
10114 case GIMPLE_OMP_TEAMS:
10115 ctx = maybe_lookup_ctx (stmt);
10116 gcc_assert (ctx);
10117 lower_omp_teams (gsi_p, ctx);
10118 break;
10119 case GIMPLE_CALL:
10120 tree fndecl;
10121 fndecl = gimple_call_fndecl (stmt);
10122 if (fndecl
10123 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10124 switch (DECL_FUNCTION_CODE (fndecl))
10126 case BUILT_IN_GOMP_BARRIER:
10127 if (ctx == NULL)
10128 break;
10129 /* FALLTHRU */
10130 case BUILT_IN_GOMP_CANCEL:
10131 case BUILT_IN_GOMP_CANCELLATION_POINT:
10132 omp_context *cctx;
10133 cctx = ctx;
10134 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10135 cctx = cctx->outer;
10136 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10137 if (!cctx->cancellable)
10139 if (DECL_FUNCTION_CODE (fndecl)
10140 == BUILT_IN_GOMP_CANCELLATION_POINT)
10142 stmt = gimple_build_nop ();
10143 gsi_replace (gsi_p, stmt, false);
10145 break;
10147 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10149 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10150 gimple_call_set_fndecl (stmt, fndecl);
10151 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10153 tree lhs;
10154 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
10155 gimple_call_set_lhs (stmt, lhs);
10156 tree fallthru_label;
10157 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10158 gimple g;
10159 g = gimple_build_label (fallthru_label);
10160 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10161 g = gimple_build_cond (NE_EXPR, lhs,
10162 fold_convert (TREE_TYPE (lhs),
10163 boolean_false_node),
10164 cctx->cancel_label, fallthru_label);
10165 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10166 break;
10167 default:
10168 break;
10170 /* FALLTHRU */
10171 default:
10172 if ((ctx || task_shared_vars)
10173 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10174 ctx ? NULL : &wi))
10176 /* Just remove clobbers, this should happen only if we have
10177 "privatized" local addressable variables in SIMD regions,
10178 the clobber isn't needed in that case and gimplifying address
10179 of the ARRAY_REF into a pointer and creating MEM_REF based
10180 clobber would create worse code than we get with the clobber
10181 dropped. */
10182 if (gimple_clobber_p (stmt))
10184 gsi_replace (gsi_p, gimple_build_nop (), true);
10185 break;
10187 gimple_regimplify_operands (stmt, gsi_p);
10189 break;
10193 static void
10194 lower_omp (gimple_seq *body, omp_context *ctx)
10196 location_t saved_location = input_location;
10197 gimple_stmt_iterator gsi;
10198 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10199 lower_omp_1 (&gsi, ctx);
10200 /* During gimplification, we have not always invoked fold_stmt
10201 (gimplify.c:maybe_fold_stmt); call it now. */
10202 if (target_nesting_level)
10203 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10204 fold_stmt (&gsi);
10205 input_location = saved_location;
10208 /* Main entry point. */
10210 static unsigned int
10211 execute_lower_omp (void)
10213 gimple_seq body;
10215 /* This pass always runs, to provide PROP_gimple_lomp.
10216 But there is nothing to do unless -fopenmp is given. */
10217 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10218 return 0;
10220 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10221 delete_omp_context);
10223 body = gimple_body (current_function_decl);
10224 scan_omp (&body, NULL);
10225 gcc_assert (taskreg_nesting_level == 0);
10227 if (all_contexts->root)
10229 if (task_shared_vars)
10230 push_gimplify_context ();
10231 lower_omp (&body, NULL);
10232 if (task_shared_vars)
10233 pop_gimplify_context (NULL);
10236 if (all_contexts)
10238 splay_tree_delete (all_contexts);
10239 all_contexts = NULL;
10241 BITMAP_FREE (task_shared_vars);
10242 return 0;
10245 namespace {
10247 const pass_data pass_data_lower_omp =
10249 GIMPLE_PASS, /* type */
10250 "omplower", /* name */
10251 OPTGROUP_NONE, /* optinfo_flags */
10252 true, /* has_execute */
10253 TV_NONE, /* tv_id */
10254 PROP_gimple_any, /* properties_required */
10255 PROP_gimple_lomp, /* properties_provided */
10256 0, /* properties_destroyed */
10257 0, /* todo_flags_start */
10258 0, /* todo_flags_finish */
10261 class pass_lower_omp : public gimple_opt_pass
10263 public:
10264 pass_lower_omp (gcc::context *ctxt)
10265 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10268 /* opt_pass methods: */
10269 virtual unsigned int execute (function *) { return execute_lower_omp (); }
10271 }; // class pass_lower_omp
10273 } // anon namespace
10275 gimple_opt_pass *
10276 make_pass_lower_omp (gcc::context *ctxt)
10278 return new pass_lower_omp (ctxt);
10281 /* The following is a utility to diagnose OpenMP structured block violations.
10282 It is not part of the "omplower" pass, as that's invoked too late. It
10283 should be invoked by the respective front ends after gimplification. */
10285 static splay_tree all_labels;
10287 /* Check for mismatched contexts and generate an error if needed. Return
10288 true if an error is detected. */
10290 static bool
10291 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10292 gimple branch_ctx, gimple label_ctx)
10294 if (label_ctx == branch_ctx)
10295 return false;
10299 Previously we kept track of the label's entire context in diagnose_sb_[12]
10300 so we could traverse it and issue a correct "exit" or "enter" error
10301 message upon a structured block violation.
10303 We built the context by building a list with tree_cons'ing, but there is
10304 no easy counterpart in gimple tuples. It seems like far too much work
10305 for issuing exit/enter error messages. If someone really misses the
10306 distinct error message... patches welcome.
10309 #if 0
10310 /* Try to avoid confusing the user by producing and error message
10311 with correct "exit" or "enter" verbiage. We prefer "exit"
10312 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10313 if (branch_ctx == NULL)
10314 exit_p = false;
10315 else
10317 while (label_ctx)
10319 if (TREE_VALUE (label_ctx) == branch_ctx)
10321 exit_p = false;
10322 break;
10324 label_ctx = TREE_CHAIN (label_ctx);
10328 if (exit_p)
10329 error ("invalid exit from OpenMP structured block");
10330 else
10331 error ("invalid entry to OpenMP structured block");
10332 #endif
10334 bool cilkplus_block = false;
10335 if (flag_cilkplus)
10337 if ((branch_ctx
10338 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10339 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10340 || (label_ctx
10341 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10342 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10343 cilkplus_block = true;
10346 /* If it's obvious we have an invalid entry, be specific about the error. */
10347 if (branch_ctx == NULL)
10349 if (cilkplus_block)
10350 error ("invalid entry to Cilk Plus structured block");
10351 else
10352 error ("invalid entry to OpenMP structured block");
10354 else
10356 /* Otherwise, be vague and lazy, but efficient. */
10357 if (cilkplus_block)
10358 error ("invalid branch to/from a Cilk Plus structured block");
10359 else
10360 error ("invalid branch to/from an OpenMP structured block");
10363 gsi_replace (gsi_p, gimple_build_nop (), false);
10364 return true;
10367 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10368 where each label is found. */
10370 static tree
10371 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10372 struct walk_stmt_info *wi)
10374 gimple context = (gimple) wi->info;
10375 gimple inner_context;
10376 gimple stmt = gsi_stmt (*gsi_p);
10378 *handled_ops_p = true;
10380 switch (gimple_code (stmt))
10382 WALK_SUBSTMTS;
10384 case GIMPLE_OMP_PARALLEL:
10385 case GIMPLE_OMP_TASK:
10386 case GIMPLE_OMP_SECTIONS:
10387 case GIMPLE_OMP_SINGLE:
10388 case GIMPLE_OMP_SECTION:
10389 case GIMPLE_OMP_MASTER:
10390 case GIMPLE_OMP_ORDERED:
10391 case GIMPLE_OMP_CRITICAL:
10392 case GIMPLE_OMP_TARGET:
10393 case GIMPLE_OMP_TEAMS:
10394 case GIMPLE_OMP_TASKGROUP:
10395 /* The minimal context here is just the current OMP construct. */
10396 inner_context = stmt;
10397 wi->info = inner_context;
10398 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10399 wi->info = context;
10400 break;
10402 case GIMPLE_OMP_FOR:
10403 inner_context = stmt;
10404 wi->info = inner_context;
10405 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10406 walk them. */
10407 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10408 diagnose_sb_1, NULL, wi);
10409 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10410 wi->info = context;
10411 break;
10413 case GIMPLE_LABEL:
10414 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10415 (splay_tree_value) context);
10416 break;
10418 default:
10419 break;
10422 return NULL_TREE;
10425 /* Pass 2: Check each branch and see if its context differs from that of
10426 the destination label's context. */
10428 static tree
10429 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10430 struct walk_stmt_info *wi)
10432 gimple context = (gimple) wi->info;
10433 splay_tree_node n;
10434 gimple stmt = gsi_stmt (*gsi_p);
10436 *handled_ops_p = true;
10438 switch (gimple_code (stmt))
10440 WALK_SUBSTMTS;
10442 case GIMPLE_OMP_PARALLEL:
10443 case GIMPLE_OMP_TASK:
10444 case GIMPLE_OMP_SECTIONS:
10445 case GIMPLE_OMP_SINGLE:
10446 case GIMPLE_OMP_SECTION:
10447 case GIMPLE_OMP_MASTER:
10448 case GIMPLE_OMP_ORDERED:
10449 case GIMPLE_OMP_CRITICAL:
10450 case GIMPLE_OMP_TARGET:
10451 case GIMPLE_OMP_TEAMS:
10452 case GIMPLE_OMP_TASKGROUP:
10453 wi->info = stmt;
10454 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10455 wi->info = context;
10456 break;
10458 case GIMPLE_OMP_FOR:
10459 wi->info = stmt;
10460 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10461 walk them. */
10462 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10463 diagnose_sb_2, NULL, wi);
10464 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10465 wi->info = context;
10466 break;
10468 case GIMPLE_COND:
10470 tree lab = gimple_cond_true_label (stmt);
10471 if (lab)
10473 n = splay_tree_lookup (all_labels,
10474 (splay_tree_key) lab);
10475 diagnose_sb_0 (gsi_p, context,
10476 n ? (gimple) n->value : NULL);
10478 lab = gimple_cond_false_label (stmt);
10479 if (lab)
10481 n = splay_tree_lookup (all_labels,
10482 (splay_tree_key) lab);
10483 diagnose_sb_0 (gsi_p, context,
10484 n ? (gimple) n->value : NULL);
10487 break;
10489 case GIMPLE_GOTO:
10491 tree lab = gimple_goto_dest (stmt);
10492 if (TREE_CODE (lab) != LABEL_DECL)
10493 break;
10495 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10496 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10498 break;
10500 case GIMPLE_SWITCH:
10502 unsigned int i;
10503 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10505 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10506 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10507 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10508 break;
10511 break;
10513 case GIMPLE_RETURN:
10514 diagnose_sb_0 (gsi_p, context, NULL);
10515 break;
10517 default:
10518 break;
10521 return NULL_TREE;
10524 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10525 codes. */
10526 bool
10527 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
10528 int *region_idx)
10530 gimple last = last_stmt (bb);
10531 enum gimple_code code = gimple_code (last);
10532 struct omp_region *cur_region = *region;
10533 bool fallthru = false;
10535 switch (code)
10537 case GIMPLE_OMP_PARALLEL:
10538 case GIMPLE_OMP_TASK:
10539 case GIMPLE_OMP_FOR:
10540 case GIMPLE_OMP_SINGLE:
10541 case GIMPLE_OMP_TEAMS:
10542 case GIMPLE_OMP_MASTER:
10543 case GIMPLE_OMP_TASKGROUP:
10544 case GIMPLE_OMP_ORDERED:
10545 case GIMPLE_OMP_CRITICAL:
10546 case GIMPLE_OMP_SECTION:
10547 cur_region = new_omp_region (bb, code, cur_region);
10548 fallthru = true;
10549 break;
10551 case GIMPLE_OMP_TARGET:
10552 cur_region = new_omp_region (bb, code, cur_region);
10553 fallthru = true;
10554 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10555 cur_region = cur_region->outer;
10556 break;
10558 case GIMPLE_OMP_SECTIONS:
10559 cur_region = new_omp_region (bb, code, cur_region);
10560 fallthru = true;
10561 break;
10563 case GIMPLE_OMP_SECTIONS_SWITCH:
10564 fallthru = false;
10565 break;
10567 case GIMPLE_OMP_ATOMIC_LOAD:
10568 case GIMPLE_OMP_ATOMIC_STORE:
10569 fallthru = true;
10570 break;
10572 case GIMPLE_OMP_RETURN:
10573 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10574 somewhere other than the next block. This will be
10575 created later. */
10576 cur_region->exit = bb;
10577 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
10578 cur_region = cur_region->outer;
10579 break;
10581 case GIMPLE_OMP_CONTINUE:
10582 cur_region->cont = bb;
10583 switch (cur_region->type)
10585 case GIMPLE_OMP_FOR:
10586 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
10587 succs edges as abnormal to prevent splitting
10588 them. */
10589 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
10590 /* Make the loopback edge. */
10591 make_edge (bb, single_succ (cur_region->entry),
10592 EDGE_ABNORMAL);
10594 /* Create an edge from GIMPLE_OMP_FOR to exit, which
10595 corresponds to the case that the body of the loop
10596 is not executed at all. */
10597 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
10598 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
10599 fallthru = false;
10600 break;
10602 case GIMPLE_OMP_SECTIONS:
10603 /* Wire up the edges into and out of the nested sections. */
10605 basic_block switch_bb = single_succ (cur_region->entry);
10607 struct omp_region *i;
10608 for (i = cur_region->inner; i ; i = i->next)
10610 gcc_assert (i->type == GIMPLE_OMP_SECTION);
10611 make_edge (switch_bb, i->entry, 0);
10612 make_edge (i->exit, bb, EDGE_FALLTHRU);
10615 /* Make the loopback edge to the block with
10616 GIMPLE_OMP_SECTIONS_SWITCH. */
10617 make_edge (bb, switch_bb, 0);
10619 /* Make the edge from the switch to exit. */
10620 make_edge (switch_bb, bb->next_bb, 0);
10621 fallthru = false;
10623 break;
10625 default:
10626 gcc_unreachable ();
10628 break;
10630 default:
10631 gcc_unreachable ();
10634 if (*region != cur_region)
10636 *region = cur_region;
10637 if (cur_region)
10638 *region_idx = cur_region->entry->index;
10639 else
10640 *region_idx = 0;
10643 return fallthru;
10646 static unsigned int
10647 diagnose_omp_structured_block_errors (void)
10649 struct walk_stmt_info wi;
10650 gimple_seq body = gimple_body (current_function_decl);
10652 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
10654 memset (&wi, 0, sizeof (wi));
10655 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
10657 memset (&wi, 0, sizeof (wi));
10658 wi.want_locations = true;
10659 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
10661 gimple_set_body (current_function_decl, body);
10663 splay_tree_delete (all_labels);
10664 all_labels = NULL;
10666 return 0;
10669 namespace {
10671 const pass_data pass_data_diagnose_omp_blocks =
10673 GIMPLE_PASS, /* type */
10674 "*diagnose_omp_blocks", /* name */
10675 OPTGROUP_NONE, /* optinfo_flags */
10676 true, /* has_execute */
10677 TV_NONE, /* tv_id */
10678 PROP_gimple_any, /* properties_required */
10679 0, /* properties_provided */
10680 0, /* properties_destroyed */
10681 0, /* todo_flags_start */
10682 0, /* todo_flags_finish */
10685 class pass_diagnose_omp_blocks : public gimple_opt_pass
10687 public:
10688 pass_diagnose_omp_blocks (gcc::context *ctxt)
10689 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
10692 /* opt_pass methods: */
10693 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
10694 virtual unsigned int execute (function *)
10696 return diagnose_omp_structured_block_errors ();
10699 }; // class pass_diagnose_omp_blocks
10701 } // anon namespace
10703 gimple_opt_pass *
10704 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
10706 return new pass_diagnose_omp_blocks (ctxt);
10709 /* SIMD clone supporting code. */
10711 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
10712 of arguments to reserve space for. */
10714 static struct cgraph_simd_clone *
10715 simd_clone_struct_alloc (int nargs)
10717 struct cgraph_simd_clone *clone_info;
10718 size_t len = (sizeof (struct cgraph_simd_clone)
10719 + nargs * sizeof (struct cgraph_simd_clone_arg));
10720 clone_info = (struct cgraph_simd_clone *)
10721 ggc_internal_cleared_alloc (len);
10722 return clone_info;
10725 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
10727 static inline void
10728 simd_clone_struct_copy (struct cgraph_simd_clone *to,
10729 struct cgraph_simd_clone *from)
10731 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
10732 + ((from->nargs - from->inbranch)
10733 * sizeof (struct cgraph_simd_clone_arg))));
10736 /* Return vector of parameter types of function FNDECL. This uses
10737 TYPE_ARG_TYPES if available, otherwise falls back to types of
10738 DECL_ARGUMENTS types. */
10740 vec<tree>
10741 simd_clone_vector_of_formal_parm_types (tree fndecl)
10743 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
10744 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
10745 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
10746 unsigned int i;
10747 tree arg;
10748 FOR_EACH_VEC_ELT (args, i, arg)
10749 args[i] = TREE_TYPE (args[i]);
10750 return args;
10753 /* Given a simd function in NODE, extract the simd specific
10754 information from the OMP clauses passed in CLAUSES, and return
10755 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
10756 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
10757 otherwise set to FALSE. */
10759 static struct cgraph_simd_clone *
10760 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
10761 bool *inbranch_specified)
10763 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
10764 tree t;
10765 int n;
10766 *inbranch_specified = false;
10768 n = args.length ();
10769 if (n > 0 && args.last () == void_type_node)
10770 n--;
10772 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
10773 be cloned have a distinctive artificial label in addition to "omp
10774 declare simd". */
10775 bool cilk_clone
10776 = (flag_cilkplus
10777 && lookup_attribute ("cilk simd function",
10778 DECL_ATTRIBUTES (node->decl)));
10780 /* Allocate one more than needed just in case this is an in-branch
10781 clone which will require a mask argument. */
10782 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
10783 clone_info->nargs = n;
10784 clone_info->cilk_elemental = cilk_clone;
10786 if (!clauses)
10788 args.release ();
10789 return clone_info;
10791 clauses = TREE_VALUE (clauses);
10792 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
10793 return clone_info;
10795 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
10797 switch (OMP_CLAUSE_CODE (t))
10799 case OMP_CLAUSE_INBRANCH:
10800 clone_info->inbranch = 1;
10801 *inbranch_specified = true;
10802 break;
10803 case OMP_CLAUSE_NOTINBRANCH:
10804 clone_info->inbranch = 0;
10805 *inbranch_specified = true;
10806 break;
10807 case OMP_CLAUSE_SIMDLEN:
10808 clone_info->simdlen
10809 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
10810 break;
10811 case OMP_CLAUSE_LINEAR:
10813 tree decl = OMP_CLAUSE_DECL (t);
10814 tree step = OMP_CLAUSE_LINEAR_STEP (t);
10815 int argno = TREE_INT_CST_LOW (decl);
10816 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
10818 clone_info->args[argno].arg_type
10819 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
10820 clone_info->args[argno].linear_step = tree_to_shwi (step);
10821 gcc_assert (clone_info->args[argno].linear_step >= 0
10822 && clone_info->args[argno].linear_step < n);
10824 else
10826 if (POINTER_TYPE_P (args[argno]))
10827 step = fold_convert (ssizetype, step);
10828 if (!tree_fits_shwi_p (step))
10830 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10831 "ignoring large linear step");
10832 args.release ();
10833 return NULL;
10835 else if (integer_zerop (step))
10837 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10838 "ignoring zero linear step");
10839 args.release ();
10840 return NULL;
10842 else
10844 clone_info->args[argno].arg_type
10845 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
10846 clone_info->args[argno].linear_step = tree_to_shwi (step);
10849 break;
10851 case OMP_CLAUSE_UNIFORM:
10853 tree decl = OMP_CLAUSE_DECL (t);
10854 int argno = tree_to_uhwi (decl);
10855 clone_info->args[argno].arg_type
10856 = SIMD_CLONE_ARG_TYPE_UNIFORM;
10857 break;
10859 case OMP_CLAUSE_ALIGNED:
10861 tree decl = OMP_CLAUSE_DECL (t);
10862 int argno = tree_to_uhwi (decl);
10863 clone_info->args[argno].alignment
10864 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
10865 break;
10867 default:
10868 break;
10871 args.release ();
10872 return clone_info;
10875 /* Given a SIMD clone in NODE, calculate the characteristic data
10876 type and return the coresponding type. The characteristic data
10877 type is computed as described in the Intel Vector ABI. */
10879 static tree
10880 simd_clone_compute_base_data_type (struct cgraph_node *node,
10881 struct cgraph_simd_clone *clone_info)
10883 tree type = integer_type_node;
10884 tree fndecl = node->decl;
10886 /* a) For non-void function, the characteristic data type is the
10887 return type. */
10888 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
10889 type = TREE_TYPE (TREE_TYPE (fndecl));
10891 /* b) If the function has any non-uniform, non-linear parameters,
10892 then the characteristic data type is the type of the first
10893 such parameter. */
10894 else
10896 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
10897 for (unsigned int i = 0; i < clone_info->nargs; ++i)
10898 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
10900 type = map[i];
10901 break;
10903 map.release ();
10906 /* c) If the characteristic data type determined by a) or b) above
10907 is struct, union, or class type which is pass-by-value (except
10908 for the type that maps to the built-in complex data type), the
10909 characteristic data type is int. */
10910 if (RECORD_OR_UNION_TYPE_P (type)
10911 && !aggregate_value_p (type, NULL)
10912 && TREE_CODE (type) != COMPLEX_TYPE)
10913 return integer_type_node;
10915 /* d) If none of the above three classes is applicable, the
10916 characteristic data type is int. */
10918 return type;
10920 /* e) For Intel Xeon Phi native and offload compilation, if the
10921 resulting characteristic data type is 8-bit or 16-bit integer
10922 data type, the characteristic data type is int. */
10923 /* Well, we don't handle Xeon Phi yet. */
10926 static tree
10927 simd_clone_mangle (struct cgraph_node *node,
10928 struct cgraph_simd_clone *clone_info)
10930 char vecsize_mangle = clone_info->vecsize_mangle;
10931 char mask = clone_info->inbranch ? 'M' : 'N';
10932 unsigned int simdlen = clone_info->simdlen;
10933 unsigned int n;
10934 pretty_printer pp;
10936 gcc_assert (vecsize_mangle && simdlen);
10938 pp_string (&pp, "_ZGV");
10939 pp_character (&pp, vecsize_mangle);
10940 pp_character (&pp, mask);
10941 pp_decimal_int (&pp, simdlen);
10943 for (n = 0; n < clone_info->nargs; ++n)
10945 struct cgraph_simd_clone_arg arg = clone_info->args[n];
10947 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
10948 pp_character (&pp, 'u');
10949 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
10951 gcc_assert (arg.linear_step != 0);
10952 pp_character (&pp, 'l');
10953 if (arg.linear_step > 1)
10954 pp_unsigned_wide_integer (&pp, arg.linear_step);
10955 else if (arg.linear_step < 0)
10957 pp_character (&pp, 'n');
10958 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
10959 arg.linear_step));
10962 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
10964 pp_character (&pp, 's');
10965 pp_unsigned_wide_integer (&pp, arg.linear_step);
10967 else
10968 pp_character (&pp, 'v');
10969 if (arg.alignment)
10971 pp_character (&pp, 'a');
10972 pp_decimal_int (&pp, arg.alignment);
10976 pp_underscore (&pp);
10977 pp_string (&pp,
10978 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
10979 const char *str = pp_formatted_text (&pp);
10981 /* If there already is a SIMD clone with the same mangled name, don't
10982 add another one. This can happen e.g. for
10983 #pragma omp declare simd
10984 #pragma omp declare simd simdlen(8)
10985 int foo (int, int);
10986 if the simdlen is assumed to be 8 for the first one, etc. */
10987 for (struct cgraph_node *clone = node->simd_clones; clone;
10988 clone = clone->simdclone->next_clone)
10989 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
10990 str) == 0)
10991 return NULL_TREE;
10993 return get_identifier (str);
10996 /* Create a simd clone of OLD_NODE and return it. */
10998 static struct cgraph_node *
10999 simd_clone_create (struct cgraph_node *old_node)
11001 struct cgraph_node *new_node;
11002 if (old_node->definition)
11004 if (!cgraph_function_with_gimple_body_p (old_node))
11005 return NULL;
11006 cgraph_get_body (old_node);
11007 new_node = cgraph_function_versioning (old_node, vNULL, NULL, NULL,
11008 false, NULL, NULL, "simdclone");
11010 else
11012 tree old_decl = old_node->decl;
11013 tree new_decl = copy_node (old_node->decl);
11014 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11015 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11016 SET_DECL_RTL (new_decl, NULL);
11017 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11018 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11019 new_node
11020 = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL);
11021 cgraph_call_function_insertion_hooks (new_node);
11023 if (new_node == NULL)
11024 return new_node;
11026 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11028 /* The function cgraph_function_versioning () will force the new
11029 symbol local. Undo this, and inherit external visability from
11030 the old node. */
11031 new_node->local.local = old_node->local.local;
11032 new_node->externally_visible = old_node->externally_visible;
11034 return new_node;
11037 /* Adjust the return type of the given function to its appropriate
11038 vector counterpart. Returns a simd array to be used throughout the
11039 function as a return value. */
11041 static tree
11042 simd_clone_adjust_return_type (struct cgraph_node *node)
11044 tree fndecl = node->decl;
11045 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11046 unsigned int veclen;
11047 tree t;
11049 /* Adjust the function return type. */
11050 if (orig_rettype == void_type_node)
11051 return NULL_TREE;
11052 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11053 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11054 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11055 veclen = node->simdclone->vecsize_int;
11056 else
11057 veclen = node->simdclone->vecsize_float;
11058 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11059 if (veclen > node->simdclone->simdlen)
11060 veclen = node->simdclone->simdlen;
11061 if (veclen == node->simdclone->simdlen)
11062 TREE_TYPE (TREE_TYPE (fndecl))
11063 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11064 node->simdclone->simdlen);
11065 else
11067 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11068 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11069 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11071 if (!node->definition)
11072 return NULL_TREE;
11074 t = DECL_RESULT (fndecl);
11075 /* Adjust the DECL_RESULT. */
11076 gcc_assert (TREE_TYPE (t) != void_type_node);
11077 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11078 relayout_decl (t);
11080 tree atype = build_array_type_nelts (orig_rettype,
11081 node->simdclone->simdlen);
11082 if (veclen != node->simdclone->simdlen)
11083 return build1 (VIEW_CONVERT_EXPR, atype, t);
11085 /* Set up a SIMD array to use as the return value. */
11086 tree retval = create_tmp_var_raw (atype, "retval");
11087 gimple_add_tmp_var (retval);
11088 return retval;
11091 /* Each vector argument has a corresponding array to be used locally
11092 as part of the eventual loop. Create such temporary array and
11093 return it.
11095 PREFIX is the prefix to be used for the temporary.
11097 TYPE is the inner element type.
11099 SIMDLEN is the number of elements. */
11101 static tree
11102 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11104 tree atype = build_array_type_nelts (type, simdlen);
11105 tree avar = create_tmp_var_raw (atype, prefix);
11106 gimple_add_tmp_var (avar);
11107 return avar;
11110 /* Modify the function argument types to their corresponding vector
11111 counterparts if appropriate. Also, create one array for each simd
11112 argument to be used locally when using the function arguments as
11113 part of the loop.
11115 NODE is the function whose arguments are to be adjusted.
11117 Returns an adjustment vector that will be filled describing how the
11118 argument types will be adjusted. */
11120 static ipa_parm_adjustment_vec
11121 simd_clone_adjust_argument_types (struct cgraph_node *node)
11123 vec<tree> args;
11124 ipa_parm_adjustment_vec adjustments;
11126 if (node->definition)
11127 args = ipa_get_vector_of_formal_parms (node->decl);
11128 else
11129 args = simd_clone_vector_of_formal_parm_types (node->decl);
11130 adjustments.create (args.length ());
11131 unsigned i, j, veclen;
11132 struct ipa_parm_adjustment adj;
11133 for (i = 0; i < node->simdclone->nargs; ++i)
11135 memset (&adj, 0, sizeof (adj));
11136 tree parm = args[i];
11137 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11138 adj.base_index = i;
11139 adj.base = parm;
11141 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11142 node->simdclone->args[i].orig_type = parm_type;
11144 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11146 /* No adjustment necessary for scalar arguments. */
11147 adj.op = IPA_PARM_OP_COPY;
11149 else
11151 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11152 veclen = node->simdclone->vecsize_int;
11153 else
11154 veclen = node->simdclone->vecsize_float;
11155 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11156 if (veclen > node->simdclone->simdlen)
11157 veclen = node->simdclone->simdlen;
11158 adj.arg_prefix = "simd";
11159 adj.type = build_vector_type (parm_type, veclen);
11160 node->simdclone->args[i].vector_type = adj.type;
11161 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11163 adjustments.safe_push (adj);
11164 if (j == veclen)
11166 memset (&adj, 0, sizeof (adj));
11167 adj.op = IPA_PARM_OP_NEW;
11168 adj.arg_prefix = "simd";
11169 adj.base_index = i;
11170 adj.type = node->simdclone->args[i].vector_type;
11174 if (node->definition)
11175 node->simdclone->args[i].simd_array
11176 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11177 parm_type, node->simdclone->simdlen);
11179 adjustments.safe_push (adj);
11182 if (node->simdclone->inbranch)
11184 tree base_type
11185 = simd_clone_compute_base_data_type (node->simdclone->origin,
11186 node->simdclone);
11188 memset (&adj, 0, sizeof (adj));
11189 adj.op = IPA_PARM_OP_NEW;
11190 adj.arg_prefix = "mask";
11192 adj.base_index = i;
11193 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11194 veclen = node->simdclone->vecsize_int;
11195 else
11196 veclen = node->simdclone->vecsize_float;
11197 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11198 if (veclen > node->simdclone->simdlen)
11199 veclen = node->simdclone->simdlen;
11200 adj.type = build_vector_type (base_type, veclen);
11201 adjustments.safe_push (adj);
11203 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11204 adjustments.safe_push (adj);
11206 /* We have previously allocated one extra entry for the mask. Use
11207 it and fill it. */
11208 struct cgraph_simd_clone *sc = node->simdclone;
11209 sc->nargs++;
11210 if (node->definition)
11212 sc->args[i].orig_arg
11213 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11214 sc->args[i].simd_array
11215 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11217 sc->args[i].orig_type = base_type;
11218 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11221 if (node->definition)
11222 ipa_modify_formal_parameters (node->decl, adjustments);
11223 else
11225 tree new_arg_types = NULL_TREE, new_reversed;
11226 bool last_parm_void = false;
11227 if (args.length () > 0 && args.last () == void_type_node)
11228 last_parm_void = true;
11230 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11231 j = adjustments.length ();
11232 for (i = 0; i < j; i++)
11234 struct ipa_parm_adjustment *adj = &adjustments[i];
11235 tree ptype;
11236 if (adj->op == IPA_PARM_OP_COPY)
11237 ptype = args[adj->base_index];
11238 else
11239 ptype = adj->type;
11240 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11242 new_reversed = nreverse (new_arg_types);
11243 if (last_parm_void)
11245 if (new_reversed)
11246 TREE_CHAIN (new_arg_types) = void_list_node;
11247 else
11248 new_reversed = void_list_node;
11251 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11252 TYPE_ARG_TYPES (new_type) = new_reversed;
11253 TREE_TYPE (node->decl) = new_type;
11255 adjustments.release ();
11257 args.release ();
11258 return adjustments;
11261 /* Initialize and copy the function arguments in NODE to their
11262 corresponding local simd arrays. Returns a fresh gimple_seq with
11263 the instruction sequence generated. */
11265 static gimple_seq
11266 simd_clone_init_simd_arrays (struct cgraph_node *node,
11267 ipa_parm_adjustment_vec adjustments)
11269 gimple_seq seq = NULL;
11270 unsigned i = 0, j = 0, k;
11272 for (tree arg = DECL_ARGUMENTS (node->decl);
11273 arg;
11274 arg = DECL_CHAIN (arg), i++, j++)
11276 if (adjustments[j].op == IPA_PARM_OP_COPY)
11277 continue;
11279 node->simdclone->args[i].vector_arg = arg;
11281 tree array = node->simdclone->args[i].simd_array;
11282 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11284 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11285 tree ptr = build_fold_addr_expr (array);
11286 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11287 build_int_cst (ptype, 0));
11288 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11289 gimplify_and_add (t, &seq);
11291 else
11293 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11294 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11295 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11297 tree ptr = build_fold_addr_expr (array);
11298 int elemsize;
11299 if (k)
11301 arg = DECL_CHAIN (arg);
11302 j++;
11304 elemsize
11305 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11306 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11307 build_int_cst (ptype, k * elemsize));
11308 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11309 gimplify_and_add (t, &seq);
11313 return seq;
11316 /* Callback info for ipa_simd_modify_stmt_ops below. */
11318 struct modify_stmt_info {
11319 ipa_parm_adjustment_vec adjustments;
11320 gimple stmt;
11321 /* True if the parent statement was modified by
11322 ipa_simd_modify_stmt_ops. */
11323 bool modified;
11326 /* Callback for walk_gimple_op.
11328 Adjust operands from a given statement as specified in the
11329 adjustments vector in the callback data. */
11331 static tree
11332 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11334 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11335 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11336 tree *orig_tp = tp;
11337 if (TREE_CODE (*tp) == ADDR_EXPR)
11338 tp = &TREE_OPERAND (*tp, 0);
11339 struct ipa_parm_adjustment *cand = NULL;
11340 if (TREE_CODE (*tp) == PARM_DECL)
11341 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11342 else
11344 if (TYPE_P (*tp))
11345 *walk_subtrees = 0;
11348 tree repl = NULL_TREE;
11349 if (cand)
11350 repl = unshare_expr (cand->new_decl);
11351 else
11353 if (tp != orig_tp)
11355 *walk_subtrees = 0;
11356 bool modified = info->modified;
11357 info->modified = false;
11358 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11359 if (!info->modified)
11361 info->modified = modified;
11362 return NULL_TREE;
11364 info->modified = modified;
11365 repl = *tp;
11367 else
11368 return NULL_TREE;
11371 if (tp != orig_tp)
11373 repl = build_fold_addr_expr (repl);
11374 gimple stmt
11375 = gimple_build_assign (make_ssa_name (TREE_TYPE (repl), NULL), repl);
11376 repl = gimple_assign_lhs (stmt);
11377 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11378 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11379 *orig_tp = repl;
11381 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11383 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11384 *tp = vce;
11386 else
11387 *tp = repl;
11389 info->modified = true;
11390 return NULL_TREE;
11393 /* Traverse the function body and perform all modifications as
11394 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11395 modified such that the replacement/reduction value will now be an
11396 offset into the corresponding simd_array.
11398 This function will replace all function argument uses with their
11399 corresponding simd array elements, and ajust the return values
11400 accordingly. */
11402 static void
11403 ipa_simd_modify_function_body (struct cgraph_node *node,
11404 ipa_parm_adjustment_vec adjustments,
11405 tree retval_array, tree iter)
11407 basic_block bb;
11408 unsigned int i, j, l;
11410 /* Re-use the adjustments array, but this time use it to replace
11411 every function argument use to an offset into the corresponding
11412 simd_array. */
11413 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11415 if (!node->simdclone->args[i].vector_arg)
11416 continue;
11418 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11419 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11420 adjustments[j].new_decl
11421 = build4 (ARRAY_REF,
11422 basetype,
11423 node->simdclone->args[i].simd_array,
11424 iter,
11425 NULL_TREE, NULL_TREE);
11426 if (adjustments[j].op == IPA_PARM_OP_NONE
11427 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11428 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11431 l = adjustments.length ();
11432 for (i = 1; i < num_ssa_names; i++)
11434 tree name = ssa_name (i);
11435 if (name
11436 && SSA_NAME_VAR (name)
11437 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11439 for (j = 0; j < l; j++)
11440 if (SSA_NAME_VAR (name) == adjustments[j].base
11441 && adjustments[j].new_decl)
11443 tree base_var;
11444 if (adjustments[j].new_ssa_base == NULL_TREE)
11446 base_var
11447 = copy_var_decl (adjustments[j].base,
11448 DECL_NAME (adjustments[j].base),
11449 TREE_TYPE (adjustments[j].base));
11450 adjustments[j].new_ssa_base = base_var;
11452 else
11453 base_var = adjustments[j].new_ssa_base;
11454 if (SSA_NAME_IS_DEFAULT_DEF (name))
11456 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11457 gimple_stmt_iterator gsi = gsi_after_labels (bb);
11458 tree new_decl = unshare_expr (adjustments[j].new_decl);
11459 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
11460 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11461 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
11462 gimple stmt = gimple_build_assign (name, new_decl);
11463 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11465 else
11466 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11471 struct modify_stmt_info info;
11472 info.adjustments = adjustments;
11474 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
11476 gimple_stmt_iterator gsi;
11478 gsi = gsi_start_bb (bb);
11479 while (!gsi_end_p (gsi))
11481 gimple stmt = gsi_stmt (gsi);
11482 info.stmt = stmt;
11483 struct walk_stmt_info wi;
11485 memset (&wi, 0, sizeof (wi));
11486 info.modified = false;
11487 wi.info = &info;
11488 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
11490 if (gimple_code (stmt) == GIMPLE_RETURN)
11492 tree retval = gimple_return_retval (stmt);
11493 if (!retval)
11495 gsi_remove (&gsi, true);
11496 continue;
11499 /* Replace `return foo' with `retval_array[iter] = foo'. */
11500 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
11501 retval_array, iter, NULL, NULL);
11502 stmt = gimple_build_assign (ref, retval);
11503 gsi_replace (&gsi, stmt, true);
11504 info.modified = true;
11507 if (info.modified)
11509 update_stmt (stmt);
11510 if (maybe_clean_eh_stmt (stmt))
11511 gimple_purge_dead_eh_edges (gimple_bb (stmt));
11513 gsi_next (&gsi);
11518 /* Adjust the argument types in NODE to their appropriate vector
11519 counterparts. */
11521 static void
11522 simd_clone_adjust (struct cgraph_node *node)
11524 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
11526 targetm.simd_clone.adjust (node);
11528 tree retval = simd_clone_adjust_return_type (node);
11529 ipa_parm_adjustment_vec adjustments
11530 = simd_clone_adjust_argument_types (node);
11532 push_gimplify_context ();
11534 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
11536 /* Adjust all uses of vector arguments accordingly. Adjust all
11537 return values accordingly. */
11538 tree iter = create_tmp_var (unsigned_type_node, "iter");
11539 tree iter1 = make_ssa_name (iter, NULL);
11540 tree iter2 = make_ssa_name (iter, NULL);
11541 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
11543 /* Initialize the iteration variable. */
11544 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11545 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
11546 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
11547 /* Insert the SIMD array and iv initialization at function
11548 entry. */
11549 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
11551 pop_gimplify_context (NULL);
11553 /* Create a new BB right before the original exit BB, to hold the
11554 iteration increment and the condition/branch. */
11555 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
11556 basic_block incr_bb = create_empty_bb (orig_exit);
11557 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11558 flag. Set it now to be a FALLTHRU_EDGE. */
11559 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
11560 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
11561 for (unsigned i = 0;
11562 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
11564 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
11565 redirect_edge_succ (e, incr_bb);
11567 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
11568 e->probability = REG_BR_PROB_BASE;
11569 gsi = gsi_last_bb (incr_bb);
11570 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
11571 build_int_cst (unsigned_type_node,
11572 1));
11573 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11575 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
11576 struct loop *loop = alloc_loop ();
11577 cfun->has_force_vectorize_loops = true;
11578 loop->safelen = node->simdclone->simdlen;
11579 loop->force_vectorize = true;
11580 loop->header = body_bb;
11581 add_bb_to_loop (incr_bb, loop);
11583 /* Branch around the body if the mask applies. */
11584 if (node->simdclone->inbranch)
11586 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
11587 tree mask_array
11588 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
11589 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
11590 tree aref = build4 (ARRAY_REF,
11591 TREE_TYPE (TREE_TYPE (mask_array)),
11592 mask_array, iter1,
11593 NULL, NULL);
11594 g = gimple_build_assign (mask, aref);
11595 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11596 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
11597 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
11599 aref = build1 (VIEW_CONVERT_EXPR,
11600 build_nonstandard_integer_type (bitsize, 0), mask);
11601 mask = make_ssa_name (TREE_TYPE (aref), NULL);
11602 g = gimple_build_assign (mask, aref);
11603 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11606 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
11607 NULL, NULL);
11608 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11609 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
11610 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
11613 /* Generate the condition. */
11614 g = gimple_build_cond (LT_EXPR,
11615 iter2,
11616 build_int_cst (unsigned_type_node,
11617 node->simdclone->simdlen),
11618 NULL, NULL);
11619 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11620 e = split_block (incr_bb, gsi_stmt (gsi));
11621 basic_block latch_bb = e->dest;
11622 basic_block new_exit_bb = e->dest;
11623 new_exit_bb = split_block (latch_bb, NULL)->dest;
11624 loop->latch = latch_bb;
11626 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
11628 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
11629 /* The successor of incr_bb is already pointing to latch_bb; just
11630 change the flags.
11631 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
11632 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
11634 gimple phi = create_phi_node (iter1, body_bb);
11635 edge preheader_edge = find_edge (entry_bb, body_bb);
11636 edge latch_edge = single_succ_edge (latch_bb);
11637 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
11638 UNKNOWN_LOCATION);
11639 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11641 /* Generate the new return. */
11642 gsi = gsi_last_bb (new_exit_bb);
11643 if (retval
11644 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
11645 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
11646 retval = TREE_OPERAND (retval, 0);
11647 else if (retval)
11649 retval = build1 (VIEW_CONVERT_EXPR,
11650 TREE_TYPE (TREE_TYPE (node->decl)),
11651 retval);
11652 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
11653 false, GSI_CONTINUE_LINKING);
11655 g = gimple_build_return (retval);
11656 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11658 /* Handle aligned clauses by replacing default defs of the aligned
11659 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
11660 lhs. Handle linear by adding PHIs. */
11661 for (unsigned i = 0; i < node->simdclone->nargs; i++)
11662 if (node->simdclone->args[i].alignment
11663 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
11664 && (node->simdclone->args[i].alignment
11665 & (node->simdclone->args[i].alignment - 1)) == 0
11666 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
11667 == POINTER_TYPE)
11669 unsigned int alignment = node->simdclone->args[i].alignment;
11670 tree orig_arg = node->simdclone->args[i].orig_arg;
11671 tree def = ssa_default_def (cfun, orig_arg);
11672 if (def && !has_zero_uses (def))
11674 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
11675 gimple_seq seq = NULL;
11676 bool need_cvt = false;
11677 gimple call
11678 = gimple_build_call (fn, 2, def, size_int (alignment));
11679 g = call;
11680 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
11681 ptr_type_node))
11682 need_cvt = true;
11683 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
11684 gimple_call_set_lhs (g, t);
11685 gimple_seq_add_stmt_without_update (&seq, g);
11686 if (need_cvt)
11688 t = make_ssa_name (orig_arg, NULL);
11689 g = gimple_build_assign_with_ops (NOP_EXPR, t,
11690 gimple_call_lhs (g),
11691 NULL_TREE);
11692 gimple_seq_add_stmt_without_update (&seq, g);
11694 gsi_insert_seq_on_edge_immediate
11695 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
11697 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11698 int freq = compute_call_stmt_bb_frequency (current_function_decl,
11699 entry_bb);
11700 cgraph_create_edge (node, cgraph_get_create_node (fn),
11701 call, entry_bb->count, freq);
11703 imm_use_iterator iter;
11704 use_operand_p use_p;
11705 gimple use_stmt;
11706 tree repl = gimple_get_lhs (g);
11707 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11708 if (is_gimple_debug (use_stmt) || use_stmt == call)
11709 continue;
11710 else
11711 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11712 SET_USE (use_p, repl);
11715 else if (node->simdclone->args[i].arg_type
11716 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11718 tree orig_arg = node->simdclone->args[i].orig_arg;
11719 tree def = ssa_default_def (cfun, orig_arg);
11720 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11721 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
11722 if (def && !has_zero_uses (def))
11724 iter1 = make_ssa_name (orig_arg, NULL);
11725 iter2 = make_ssa_name (orig_arg, NULL);
11726 phi = create_phi_node (iter1, body_bb);
11727 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
11728 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11729 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11730 ? PLUS_EXPR : POINTER_PLUS_EXPR;
11731 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11732 ? TREE_TYPE (orig_arg) : sizetype;
11733 tree addcst
11734 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
11735 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
11736 gsi = gsi_last_bb (incr_bb);
11737 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
11739 imm_use_iterator iter;
11740 use_operand_p use_p;
11741 gimple use_stmt;
11742 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11743 if (use_stmt == phi)
11744 continue;
11745 else
11746 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11747 SET_USE (use_p, iter1);
11751 calculate_dominance_info (CDI_DOMINATORS);
11752 add_loop (loop, loop->header->loop_father);
11753 update_ssa (TODO_update_ssa);
11755 pop_cfun ();
11758 /* If the function in NODE is tagged as an elemental SIMD function,
11759 create the appropriate SIMD clones. */
11761 static void
11762 expand_simd_clones (struct cgraph_node *node)
11764 tree attr = lookup_attribute ("omp declare simd",
11765 DECL_ATTRIBUTES (node->decl));
11766 if (attr == NULL_TREE
11767 || node->global.inlined_to
11768 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
11769 return;
11771 /* Ignore
11772 #pragma omp declare simd
11773 extern int foo ();
11774 in C, there we don't know the argument types at all. */
11775 if (!node->definition
11776 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
11777 return;
11781 /* Start with parsing the "omp declare simd" attribute(s). */
11782 bool inbranch_clause_specified;
11783 struct cgraph_simd_clone *clone_info
11784 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
11785 &inbranch_clause_specified);
11786 if (clone_info == NULL)
11787 continue;
11789 int orig_simdlen = clone_info->simdlen;
11790 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
11791 /* The target can return 0 (no simd clones should be created),
11792 1 (just one ISA of simd clones should be created) or higher
11793 count of ISA variants. In that case, clone_info is initialized
11794 for the first ISA variant. */
11795 int count
11796 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
11797 base_type, 0);
11798 if (count == 0)
11799 continue;
11801 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
11802 also create one inbranch and one !inbranch clone of it. */
11803 for (int i = 0; i < count * 2; i++)
11805 struct cgraph_simd_clone *clone = clone_info;
11806 if (inbranch_clause_specified && (i & 1) != 0)
11807 continue;
11809 if (i != 0)
11811 clone = simd_clone_struct_alloc (clone_info->nargs
11812 + ((i & 1) != 0));
11813 simd_clone_struct_copy (clone, clone_info);
11814 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
11815 and simd_clone_adjust_argument_types did to the first
11816 clone's info. */
11817 clone->nargs -= clone_info->inbranch;
11818 clone->simdlen = orig_simdlen;
11819 /* And call the target hook again to get the right ISA. */
11820 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
11821 base_type,
11822 i / 2);
11823 if ((i & 1) != 0)
11824 clone->inbranch = 1;
11827 /* simd_clone_mangle might fail if such a clone has been created
11828 already. */
11829 tree id = simd_clone_mangle (node, clone);
11830 if (id == NULL_TREE)
11831 continue;
11833 /* Only when we are sure we want to create the clone actually
11834 clone the function (or definitions) or create another
11835 extern FUNCTION_DECL (for prototypes without definitions). */
11836 struct cgraph_node *n = simd_clone_create (node);
11837 if (n == NULL)
11838 continue;
11840 n->simdclone = clone;
11841 clone->origin = node;
11842 clone->next_clone = NULL;
11843 if (node->simd_clones == NULL)
11845 clone->prev_clone = n;
11846 node->simd_clones = n;
11848 else
11850 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
11851 clone->prev_clone->simdclone->next_clone = n;
11852 node->simd_clones->simdclone->prev_clone = n;
11854 change_decl_assembler_name (n->decl, id);
11855 /* And finally adjust the return type, parameters and for
11856 definitions also function body. */
11857 if (node->definition)
11858 simd_clone_adjust (n);
11859 else
11861 simd_clone_adjust_return_type (n);
11862 simd_clone_adjust_argument_types (n);
11866 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
11869 /* Entry point for IPA simd clone creation pass. */
11871 static unsigned int
11872 ipa_omp_simd_clone (void)
11874 struct cgraph_node *node;
11875 FOR_EACH_FUNCTION (node)
11876 expand_simd_clones (node);
11877 return 0;
11880 namespace {
11882 const pass_data pass_data_omp_simd_clone =
11884 SIMPLE_IPA_PASS, /* type */
11885 "simdclone", /* name */
11886 OPTGROUP_NONE, /* optinfo_flags */
11887 true, /* has_execute */
11888 TV_NONE, /* tv_id */
11889 ( PROP_ssa | PROP_cfg ), /* properties_required */
11890 0, /* properties_provided */
11891 0, /* properties_destroyed */
11892 0, /* todo_flags_start */
11893 0, /* todo_flags_finish */
11896 class pass_omp_simd_clone : public simple_ipa_opt_pass
11898 public:
11899 pass_omp_simd_clone(gcc::context *ctxt)
11900 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
11903 /* opt_pass methods: */
11904 virtual bool gate (function *);
11905 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
11908 bool
11909 pass_omp_simd_clone::gate (function *)
11911 return ((flag_openmp || flag_openmp_simd
11912 || flag_cilkplus
11913 || (in_lto_p && !flag_wpa))
11914 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
11917 } // anon namespace
11919 simple_ipa_opt_pass *
11920 make_pass_omp_simd_clone (gcc::context *ctxt)
11922 return new pass_omp_simd_clone (ctxt);
11925 #include "gt-omp-low.h"