AVX-512. Branch to hold overall changes introduced by 20140717 EAS.
[official-gcc.git] / gcc / omp-low.c
blob1b1cf2ce307ae7b342780829677fd986196ad40a
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 decl = OMP_CLAUSE_DECL (c);
1513 /* Ignore shared directives in teams construct. */
1514 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1516 /* Global variables don't need to be copied,
1517 the receiver side will use them directly. */
1518 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1519 if (is_global_var (odecl))
1520 break;
1521 insert_decl_map (&ctx->cb, decl, odecl);
1522 break;
1524 gcc_assert (is_taskreg_ctx (ctx));
1525 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1526 || !is_variable_sized (decl));
1527 /* Global variables don't need to be copied,
1528 the receiver side will use them directly. */
1529 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1530 break;
1531 by_ref = use_pointer_for_field (decl, ctx);
1532 if (! TREE_READONLY (decl)
1533 || TREE_ADDRESSABLE (decl)
1534 || by_ref
1535 || is_reference (decl))
1537 install_var_field (decl, by_ref, 3, ctx);
1538 install_var_local (decl, ctx);
1539 break;
1541 /* We don't need to copy const scalar vars back. */
1542 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1543 goto do_private;
1545 case OMP_CLAUSE_LASTPRIVATE:
1546 /* Let the corresponding firstprivate clause create
1547 the variable. */
1548 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1549 break;
1550 /* FALLTHRU */
1552 case OMP_CLAUSE_FIRSTPRIVATE:
1553 case OMP_CLAUSE_REDUCTION:
1554 case OMP_CLAUSE_LINEAR:
1555 decl = OMP_CLAUSE_DECL (c);
1556 do_private:
1557 if (is_variable_sized (decl))
1559 if (is_task_ctx (ctx))
1560 install_var_field (decl, false, 1, ctx);
1561 break;
1563 else if (is_taskreg_ctx (ctx))
1565 bool global
1566 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1567 by_ref = use_pointer_for_field (decl, NULL);
1569 if (is_task_ctx (ctx)
1570 && (global || by_ref || is_reference (decl)))
1572 install_var_field (decl, false, 1, ctx);
1573 if (!global)
1574 install_var_field (decl, by_ref, 2, ctx);
1576 else if (!global)
1577 install_var_field (decl, by_ref, 3, ctx);
1579 install_var_local (decl, ctx);
1580 break;
1582 case OMP_CLAUSE__LOOPTEMP_:
1583 gcc_assert (is_parallel_ctx (ctx));
1584 decl = OMP_CLAUSE_DECL (c);
1585 install_var_field (decl, false, 3, ctx);
1586 install_var_local (decl, ctx);
1587 break;
1589 case OMP_CLAUSE_COPYPRIVATE:
1590 case OMP_CLAUSE_COPYIN:
1591 decl = OMP_CLAUSE_DECL (c);
1592 by_ref = use_pointer_for_field (decl, NULL);
1593 install_var_field (decl, by_ref, 3, ctx);
1594 break;
1596 case OMP_CLAUSE_DEFAULT:
1597 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1598 break;
1600 case OMP_CLAUSE_FINAL:
1601 case OMP_CLAUSE_IF:
1602 case OMP_CLAUSE_NUM_THREADS:
1603 case OMP_CLAUSE_NUM_TEAMS:
1604 case OMP_CLAUSE_THREAD_LIMIT:
1605 case OMP_CLAUSE_DEVICE:
1606 case OMP_CLAUSE_SCHEDULE:
1607 case OMP_CLAUSE_DIST_SCHEDULE:
1608 case OMP_CLAUSE_DEPEND:
1609 if (ctx->outer)
1610 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1611 break;
1613 case OMP_CLAUSE_TO:
1614 case OMP_CLAUSE_FROM:
1615 case OMP_CLAUSE_MAP:
1616 if (ctx->outer)
1617 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1618 decl = OMP_CLAUSE_DECL (c);
1619 /* Global variables with "omp declare target" attribute
1620 don't need to be copied, the receiver side will use them
1621 directly. */
1622 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1623 && DECL_P (decl)
1624 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1625 && lookup_attribute ("omp declare target",
1626 DECL_ATTRIBUTES (decl)))
1627 break;
1628 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1629 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1631 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1632 #pragma omp target data, there is nothing to map for
1633 those. */
1634 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1635 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1636 break;
1638 if (DECL_P (decl))
1640 if (DECL_SIZE (decl)
1641 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1643 tree decl2 = DECL_VALUE_EXPR (decl);
1644 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1645 decl2 = TREE_OPERAND (decl2, 0);
1646 gcc_assert (DECL_P (decl2));
1647 install_var_field (decl2, true, 3, ctx);
1648 install_var_local (decl2, ctx);
1649 install_var_local (decl, ctx);
1651 else
1653 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1654 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1655 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1656 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1657 install_var_field (decl, true, 7, ctx);
1658 else
1659 install_var_field (decl, true, 3, ctx);
1660 if (gimple_omp_target_kind (ctx->stmt)
1661 == GF_OMP_TARGET_KIND_REGION)
1662 install_var_local (decl, ctx);
1665 else
1667 tree base = get_base_address (decl);
1668 tree nc = OMP_CLAUSE_CHAIN (c);
1669 if (DECL_P (base)
1670 && nc != NULL_TREE
1671 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1672 && OMP_CLAUSE_DECL (nc) == base
1673 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1674 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1676 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1677 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1679 else
1681 if (ctx->outer)
1683 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1684 decl = OMP_CLAUSE_DECL (c);
1686 gcc_assert (!splay_tree_lookup (ctx->field_map,
1687 (splay_tree_key) decl));
1688 tree field
1689 = build_decl (OMP_CLAUSE_LOCATION (c),
1690 FIELD_DECL, NULL_TREE, ptr_type_node);
1691 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1692 insert_field_into_struct (ctx->record_type, field);
1693 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1694 (splay_tree_value) field);
1697 break;
1699 case OMP_CLAUSE_NOWAIT:
1700 case OMP_CLAUSE_ORDERED:
1701 case OMP_CLAUSE_COLLAPSE:
1702 case OMP_CLAUSE_UNTIED:
1703 case OMP_CLAUSE_MERGEABLE:
1704 case OMP_CLAUSE_PROC_BIND:
1705 case OMP_CLAUSE_SAFELEN:
1706 break;
1708 case OMP_CLAUSE_ALIGNED:
1709 decl = OMP_CLAUSE_DECL (c);
1710 if (is_global_var (decl)
1711 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1712 install_var_local (decl, ctx);
1713 break;
1715 default:
1716 gcc_unreachable ();
1720 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1722 switch (OMP_CLAUSE_CODE (c))
1724 case OMP_CLAUSE_LASTPRIVATE:
1725 /* Let the corresponding firstprivate clause create
1726 the variable. */
1727 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1728 scan_array_reductions = true;
1729 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1730 break;
1731 /* FALLTHRU */
1733 case OMP_CLAUSE_PRIVATE:
1734 case OMP_CLAUSE_FIRSTPRIVATE:
1735 case OMP_CLAUSE_REDUCTION:
1736 case OMP_CLAUSE_LINEAR:
1737 decl = OMP_CLAUSE_DECL (c);
1738 if (is_variable_sized (decl))
1739 install_var_local (decl, ctx);
1740 fixup_remapped_decl (decl, ctx,
1741 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1742 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1743 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1744 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1745 scan_array_reductions = true;
1746 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1747 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1748 scan_array_reductions = true;
1749 break;
1751 case OMP_CLAUSE_SHARED:
1752 /* Ignore shared directives in teams construct. */
1753 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1754 break;
1755 decl = OMP_CLAUSE_DECL (c);
1756 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1757 fixup_remapped_decl (decl, ctx, false);
1758 break;
1760 case OMP_CLAUSE_MAP:
1761 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1762 break;
1763 decl = OMP_CLAUSE_DECL (c);
1764 if (DECL_P (decl)
1765 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1766 && lookup_attribute ("omp declare target",
1767 DECL_ATTRIBUTES (decl)))
1768 break;
1769 if (DECL_P (decl))
1771 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1772 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1773 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1775 tree new_decl = lookup_decl (decl, ctx);
1776 TREE_TYPE (new_decl)
1777 = remap_type (TREE_TYPE (decl), &ctx->cb);
1779 else if (DECL_SIZE (decl)
1780 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1782 tree decl2 = DECL_VALUE_EXPR (decl);
1783 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1784 decl2 = TREE_OPERAND (decl2, 0);
1785 gcc_assert (DECL_P (decl2));
1786 fixup_remapped_decl (decl2, ctx, false);
1787 fixup_remapped_decl (decl, ctx, true);
1789 else
1790 fixup_remapped_decl (decl, ctx, false);
1792 break;
1794 case OMP_CLAUSE_COPYPRIVATE:
1795 case OMP_CLAUSE_COPYIN:
1796 case OMP_CLAUSE_DEFAULT:
1797 case OMP_CLAUSE_IF:
1798 case OMP_CLAUSE_NUM_THREADS:
1799 case OMP_CLAUSE_NUM_TEAMS:
1800 case OMP_CLAUSE_THREAD_LIMIT:
1801 case OMP_CLAUSE_DEVICE:
1802 case OMP_CLAUSE_SCHEDULE:
1803 case OMP_CLAUSE_DIST_SCHEDULE:
1804 case OMP_CLAUSE_NOWAIT:
1805 case OMP_CLAUSE_ORDERED:
1806 case OMP_CLAUSE_COLLAPSE:
1807 case OMP_CLAUSE_UNTIED:
1808 case OMP_CLAUSE_FINAL:
1809 case OMP_CLAUSE_MERGEABLE:
1810 case OMP_CLAUSE_PROC_BIND:
1811 case OMP_CLAUSE_SAFELEN:
1812 case OMP_CLAUSE_ALIGNED:
1813 case OMP_CLAUSE_DEPEND:
1814 case OMP_CLAUSE__LOOPTEMP_:
1815 case OMP_CLAUSE_TO:
1816 case OMP_CLAUSE_FROM:
1817 break;
1819 default:
1820 gcc_unreachable ();
1824 if (scan_array_reductions)
1825 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1826 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1827 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1829 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1830 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1832 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1833 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1834 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1835 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1836 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1837 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1840 /* Create a new name for omp child function. Returns an identifier. */
1842 static tree
1843 create_omp_child_function_name (bool task_copy)
1845 return (clone_function_name (current_function_decl,
1846 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1849 /* Build a decl for the omp child function. It'll not contain a body
1850 yet, just the bare decl. */
1852 static void
1853 create_omp_child_function (omp_context *ctx, bool task_copy)
1855 tree decl, type, name, t;
1857 name = create_omp_child_function_name (task_copy);
1858 if (task_copy)
1859 type = build_function_type_list (void_type_node, ptr_type_node,
1860 ptr_type_node, NULL_TREE);
1861 else
1862 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1864 decl = build_decl (gimple_location (ctx->stmt),
1865 FUNCTION_DECL, name, type);
1867 if (!task_copy)
1868 ctx->cb.dst_fn = decl;
1869 else
1870 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1872 TREE_STATIC (decl) = 1;
1873 TREE_USED (decl) = 1;
1874 DECL_ARTIFICIAL (decl) = 1;
1875 DECL_IGNORED_P (decl) = 0;
1876 TREE_PUBLIC (decl) = 0;
1877 DECL_UNINLINABLE (decl) = 1;
1878 DECL_EXTERNAL (decl) = 0;
1879 DECL_CONTEXT (decl) = NULL_TREE;
1880 DECL_INITIAL (decl) = make_node (BLOCK);
1881 bool target_p = false;
1882 if (lookup_attribute ("omp declare target",
1883 DECL_ATTRIBUTES (current_function_decl)))
1884 target_p = true;
1885 else
1887 omp_context *octx;
1888 for (octx = ctx; octx; octx = octx->outer)
1889 if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
1890 && gimple_omp_target_kind (octx->stmt)
1891 == GF_OMP_TARGET_KIND_REGION)
1893 target_p = true;
1894 break;
1897 if (target_p)
1898 DECL_ATTRIBUTES (decl)
1899 = tree_cons (get_identifier ("omp declare target"),
1900 NULL_TREE, DECL_ATTRIBUTES (decl));
1902 t = build_decl (DECL_SOURCE_LOCATION (decl),
1903 RESULT_DECL, NULL_TREE, void_type_node);
1904 DECL_ARTIFICIAL (t) = 1;
1905 DECL_IGNORED_P (t) = 1;
1906 DECL_CONTEXT (t) = decl;
1907 DECL_RESULT (decl) = t;
1909 t = build_decl (DECL_SOURCE_LOCATION (decl),
1910 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1911 DECL_ARTIFICIAL (t) = 1;
1912 DECL_NAMELESS (t) = 1;
1913 DECL_ARG_TYPE (t) = ptr_type_node;
1914 DECL_CONTEXT (t) = current_function_decl;
1915 TREE_USED (t) = 1;
1916 DECL_ARGUMENTS (decl) = t;
1917 if (!task_copy)
1918 ctx->receiver_decl = t;
1919 else
1921 t = build_decl (DECL_SOURCE_LOCATION (decl),
1922 PARM_DECL, get_identifier (".omp_data_o"),
1923 ptr_type_node);
1924 DECL_ARTIFICIAL (t) = 1;
1925 DECL_NAMELESS (t) = 1;
1926 DECL_ARG_TYPE (t) = ptr_type_node;
1927 DECL_CONTEXT (t) = current_function_decl;
1928 TREE_USED (t) = 1;
1929 TREE_ADDRESSABLE (t) = 1;
1930 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1931 DECL_ARGUMENTS (decl) = t;
1934 /* Allocate memory for the function structure. The call to
1935 allocate_struct_function clobbers CFUN, so we need to restore
1936 it afterward. */
1937 push_struct_function (decl);
1938 cfun->function_end_locus = gimple_location (ctx->stmt);
1939 pop_cfun ();
1942 /* Callback for walk_gimple_seq. Check if combined parallel
1943 contains gimple_omp_for_combined_into_p OMP_FOR. */
1945 static tree
1946 find_combined_for (gimple_stmt_iterator *gsi_p,
1947 bool *handled_ops_p,
1948 struct walk_stmt_info *wi)
1950 gimple stmt = gsi_stmt (*gsi_p);
1952 *handled_ops_p = true;
1953 switch (gimple_code (stmt))
1955 WALK_SUBSTMTS;
1957 case GIMPLE_OMP_FOR:
1958 if (gimple_omp_for_combined_into_p (stmt)
1959 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
1961 wi->info = stmt;
1962 return integer_zero_node;
1964 break;
1965 default:
1966 break;
1968 return NULL;
1971 /* Scan an OpenMP parallel directive. */
1973 static void
1974 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1976 omp_context *ctx;
1977 tree name;
1978 gimple stmt = gsi_stmt (*gsi);
1980 /* Ignore parallel directives with empty bodies, unless there
1981 are copyin clauses. */
1982 if (optimize > 0
1983 && empty_body_p (gimple_omp_body (stmt))
1984 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1985 OMP_CLAUSE_COPYIN) == NULL)
1987 gsi_replace (gsi, gimple_build_nop (), false);
1988 return;
1991 if (gimple_omp_parallel_combined_p (stmt))
1993 gimple for_stmt;
1994 struct walk_stmt_info wi;
1996 memset (&wi, 0, sizeof (wi));
1997 wi.val_only = true;
1998 walk_gimple_seq (gimple_omp_body (stmt),
1999 find_combined_for, NULL, &wi);
2000 for_stmt = (gimple) wi.info;
2001 if (for_stmt)
2003 struct omp_for_data fd;
2004 extract_omp_for_data (for_stmt, &fd, NULL);
2005 /* We need two temporaries with fd.loop.v type (istart/iend)
2006 and then (fd.collapse - 1) temporaries with the same
2007 type for count2 ... countN-1 vars if not constant. */
2008 size_t count = 2, i;
2009 tree type = fd.iter_type;
2010 if (fd.collapse > 1
2011 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2012 count += fd.collapse - 1;
2013 for (i = 0; i < count; i++)
2015 tree temp = create_tmp_var (type, NULL);
2016 tree c = build_omp_clause (UNKNOWN_LOCATION,
2017 OMP_CLAUSE__LOOPTEMP_);
2018 insert_decl_map (&outer_ctx->cb, temp, temp);
2019 OMP_CLAUSE_DECL (c) = temp;
2020 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2021 gimple_omp_parallel_set_clauses (stmt, c);
2026 ctx = new_omp_context (stmt, outer_ctx);
2027 if (taskreg_nesting_level > 1)
2028 ctx->is_nested = true;
2029 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2030 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2031 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2032 name = create_tmp_var_name (".omp_data_s");
2033 name = build_decl (gimple_location (stmt),
2034 TYPE_DECL, name, ctx->record_type);
2035 DECL_ARTIFICIAL (name) = 1;
2036 DECL_NAMELESS (name) = 1;
2037 TYPE_NAME (ctx->record_type) = name;
2038 create_omp_child_function (ctx, false);
2039 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2041 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2042 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2044 if (TYPE_FIELDS (ctx->record_type) == NULL)
2045 ctx->record_type = ctx->receiver_decl = NULL;
2046 else
2048 layout_type (ctx->record_type);
2049 fixup_child_record_type (ctx);
2053 /* Scan an OpenMP task directive. */
2055 static void
2056 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2058 omp_context *ctx;
2059 tree name, t;
2060 gimple stmt = gsi_stmt (*gsi);
2061 location_t loc = gimple_location (stmt);
2063 /* Ignore task directives with empty bodies. */
2064 if (optimize > 0
2065 && empty_body_p (gimple_omp_body (stmt)))
2067 gsi_replace (gsi, gimple_build_nop (), false);
2068 return;
2071 ctx = new_omp_context (stmt, outer_ctx);
2072 if (taskreg_nesting_level > 1)
2073 ctx->is_nested = true;
2074 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2075 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2076 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2077 name = create_tmp_var_name (".omp_data_s");
2078 name = build_decl (gimple_location (stmt),
2079 TYPE_DECL, name, ctx->record_type);
2080 DECL_ARTIFICIAL (name) = 1;
2081 DECL_NAMELESS (name) = 1;
2082 TYPE_NAME (ctx->record_type) = name;
2083 create_omp_child_function (ctx, false);
2084 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2086 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2088 if (ctx->srecord_type)
2090 name = create_tmp_var_name (".omp_data_a");
2091 name = build_decl (gimple_location (stmt),
2092 TYPE_DECL, name, ctx->srecord_type);
2093 DECL_ARTIFICIAL (name) = 1;
2094 DECL_NAMELESS (name) = 1;
2095 TYPE_NAME (ctx->srecord_type) = name;
2096 create_omp_child_function (ctx, true);
2099 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2101 if (TYPE_FIELDS (ctx->record_type) == NULL)
2103 ctx->record_type = ctx->receiver_decl = NULL;
2104 t = build_int_cst (long_integer_type_node, 0);
2105 gimple_omp_task_set_arg_size (stmt, t);
2106 t = build_int_cst (long_integer_type_node, 1);
2107 gimple_omp_task_set_arg_align (stmt, t);
2109 else
2111 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2112 /* Move VLA fields to the end. */
2113 p = &TYPE_FIELDS (ctx->record_type);
2114 while (*p)
2115 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2116 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2118 *q = *p;
2119 *p = TREE_CHAIN (*p);
2120 TREE_CHAIN (*q) = NULL_TREE;
2121 q = &TREE_CHAIN (*q);
2123 else
2124 p = &DECL_CHAIN (*p);
2125 *p = vla_fields;
2126 layout_type (ctx->record_type);
2127 fixup_child_record_type (ctx);
2128 if (ctx->srecord_type)
2129 layout_type (ctx->srecord_type);
2130 t = fold_convert_loc (loc, long_integer_type_node,
2131 TYPE_SIZE_UNIT (ctx->record_type));
2132 gimple_omp_task_set_arg_size (stmt, t);
2133 t = build_int_cst (long_integer_type_node,
2134 TYPE_ALIGN_UNIT (ctx->record_type));
2135 gimple_omp_task_set_arg_align (stmt, t);
2140 /* Scan an OpenMP loop directive. */
2142 static void
2143 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2145 omp_context *ctx;
2146 size_t i;
2148 ctx = new_omp_context (stmt, outer_ctx);
2150 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2152 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2153 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2155 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2156 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2157 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2158 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2160 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2163 /* Scan an OpenMP sections directive. */
2165 static void
2166 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2168 omp_context *ctx;
2170 ctx = new_omp_context (stmt, outer_ctx);
2171 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2172 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2175 /* Scan an OpenMP single directive. */
2177 static void
2178 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2180 omp_context *ctx;
2181 tree name;
2183 ctx = new_omp_context (stmt, outer_ctx);
2184 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2185 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2186 name = create_tmp_var_name (".omp_copy_s");
2187 name = build_decl (gimple_location (stmt),
2188 TYPE_DECL, name, ctx->record_type);
2189 TYPE_NAME (ctx->record_type) = name;
2191 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2192 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2194 if (TYPE_FIELDS (ctx->record_type) == NULL)
2195 ctx->record_type = NULL;
2196 else
2197 layout_type (ctx->record_type);
2200 /* Scan an OpenMP target{, data, update} directive. */
2202 static void
2203 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2205 omp_context *ctx;
2206 tree name;
2207 int kind = gimple_omp_target_kind (stmt);
2209 ctx = new_omp_context (stmt, outer_ctx);
2210 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2211 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2212 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2213 name = create_tmp_var_name (".omp_data_t");
2214 name = build_decl (gimple_location (stmt),
2215 TYPE_DECL, name, ctx->record_type);
2216 DECL_ARTIFICIAL (name) = 1;
2217 DECL_NAMELESS (name) = 1;
2218 TYPE_NAME (ctx->record_type) = name;
2219 if (kind == GF_OMP_TARGET_KIND_REGION)
2221 create_omp_child_function (ctx, false);
2222 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2225 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2226 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2228 if (TYPE_FIELDS (ctx->record_type) == NULL)
2229 ctx->record_type = ctx->receiver_decl = NULL;
2230 else
2232 TYPE_FIELDS (ctx->record_type)
2233 = nreverse (TYPE_FIELDS (ctx->record_type));
2234 #ifdef ENABLE_CHECKING
2235 tree field;
2236 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2237 for (field = TYPE_FIELDS (ctx->record_type);
2238 field;
2239 field = DECL_CHAIN (field))
2240 gcc_assert (DECL_ALIGN (field) == align);
2241 #endif
2242 layout_type (ctx->record_type);
2243 if (kind == GF_OMP_TARGET_KIND_REGION)
2244 fixup_child_record_type (ctx);
2248 /* Scan an OpenMP teams directive. */
2250 static void
2251 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2253 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2254 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2255 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2258 /* Check OpenMP nesting restrictions. */
2259 static bool
2260 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2262 if (ctx != NULL)
2264 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2265 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2267 error_at (gimple_location (stmt),
2268 "OpenMP constructs may not be nested inside simd region");
2269 return false;
2271 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2273 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2274 || (gimple_omp_for_kind (stmt)
2275 != GF_OMP_FOR_KIND_DISTRIBUTE))
2276 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2278 error_at (gimple_location (stmt),
2279 "only distribute or parallel constructs are allowed to "
2280 "be closely nested inside teams construct");
2281 return false;
2285 switch (gimple_code (stmt))
2287 case GIMPLE_OMP_FOR:
2288 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2289 return true;
2290 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2292 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2294 error_at (gimple_location (stmt),
2295 "distribute construct must be closely nested inside "
2296 "teams construct");
2297 return false;
2299 return true;
2301 /* FALLTHRU */
2302 case GIMPLE_CALL:
2303 if (is_gimple_call (stmt)
2304 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2305 == BUILT_IN_GOMP_CANCEL
2306 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2307 == BUILT_IN_GOMP_CANCELLATION_POINT))
2309 const char *bad = NULL;
2310 const char *kind = NULL;
2311 if (ctx == NULL)
2313 error_at (gimple_location (stmt), "orphaned %qs construct",
2314 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2315 == BUILT_IN_GOMP_CANCEL
2316 ? "#pragma omp cancel"
2317 : "#pragma omp cancellation point");
2318 return false;
2320 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2321 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2322 : 0)
2324 case 1:
2325 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2326 bad = "#pragma omp parallel";
2327 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2328 == BUILT_IN_GOMP_CANCEL
2329 && !integer_zerop (gimple_call_arg (stmt, 1)))
2330 ctx->cancellable = true;
2331 kind = "parallel";
2332 break;
2333 case 2:
2334 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2335 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2336 bad = "#pragma omp for";
2337 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2338 == BUILT_IN_GOMP_CANCEL
2339 && !integer_zerop (gimple_call_arg (stmt, 1)))
2341 ctx->cancellable = true;
2342 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2343 OMP_CLAUSE_NOWAIT))
2344 warning_at (gimple_location (stmt), 0,
2345 "%<#pragma omp cancel for%> inside "
2346 "%<nowait%> for construct");
2347 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2348 OMP_CLAUSE_ORDERED))
2349 warning_at (gimple_location (stmt), 0,
2350 "%<#pragma omp cancel for%> inside "
2351 "%<ordered%> for construct");
2353 kind = "for";
2354 break;
2355 case 4:
2356 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2357 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2358 bad = "#pragma omp sections";
2359 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2360 == BUILT_IN_GOMP_CANCEL
2361 && !integer_zerop (gimple_call_arg (stmt, 1)))
2363 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2365 ctx->cancellable = true;
2366 if (find_omp_clause (gimple_omp_sections_clauses
2367 (ctx->stmt),
2368 OMP_CLAUSE_NOWAIT))
2369 warning_at (gimple_location (stmt), 0,
2370 "%<#pragma omp cancel sections%> inside "
2371 "%<nowait%> sections construct");
2373 else
2375 gcc_assert (ctx->outer
2376 && gimple_code (ctx->outer->stmt)
2377 == GIMPLE_OMP_SECTIONS);
2378 ctx->outer->cancellable = true;
2379 if (find_omp_clause (gimple_omp_sections_clauses
2380 (ctx->outer->stmt),
2381 OMP_CLAUSE_NOWAIT))
2382 warning_at (gimple_location (stmt), 0,
2383 "%<#pragma omp cancel sections%> inside "
2384 "%<nowait%> sections construct");
2387 kind = "sections";
2388 break;
2389 case 8:
2390 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2391 bad = "#pragma omp task";
2392 else
2393 ctx->cancellable = true;
2394 kind = "taskgroup";
2395 break;
2396 default:
2397 error_at (gimple_location (stmt), "invalid arguments");
2398 return false;
2400 if (bad)
2402 error_at (gimple_location (stmt),
2403 "%<%s %s%> construct not closely nested inside of %qs",
2404 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2405 == BUILT_IN_GOMP_CANCEL
2406 ? "#pragma omp cancel"
2407 : "#pragma omp cancellation point", kind, bad);
2408 return false;
2411 /* FALLTHRU */
2412 case GIMPLE_OMP_SECTIONS:
2413 case GIMPLE_OMP_SINGLE:
2414 for (; ctx != NULL; ctx = ctx->outer)
2415 switch (gimple_code (ctx->stmt))
2417 case GIMPLE_OMP_FOR:
2418 case GIMPLE_OMP_SECTIONS:
2419 case GIMPLE_OMP_SINGLE:
2420 case GIMPLE_OMP_ORDERED:
2421 case GIMPLE_OMP_MASTER:
2422 case GIMPLE_OMP_TASK:
2423 case GIMPLE_OMP_CRITICAL:
2424 if (is_gimple_call (stmt))
2426 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2427 != BUILT_IN_GOMP_BARRIER)
2428 return true;
2429 error_at (gimple_location (stmt),
2430 "barrier region may not be closely nested inside "
2431 "of work-sharing, critical, ordered, master or "
2432 "explicit task region");
2433 return false;
2435 error_at (gimple_location (stmt),
2436 "work-sharing region may not be closely nested inside "
2437 "of work-sharing, critical, ordered, master or explicit "
2438 "task region");
2439 return false;
2440 case GIMPLE_OMP_PARALLEL:
2441 return true;
2442 default:
2443 break;
2445 break;
2446 case GIMPLE_OMP_MASTER:
2447 for (; ctx != NULL; ctx = ctx->outer)
2448 switch (gimple_code (ctx->stmt))
2450 case GIMPLE_OMP_FOR:
2451 case GIMPLE_OMP_SECTIONS:
2452 case GIMPLE_OMP_SINGLE:
2453 case GIMPLE_OMP_TASK:
2454 error_at (gimple_location (stmt),
2455 "master region may not be closely nested inside "
2456 "of work-sharing or explicit task region");
2457 return false;
2458 case GIMPLE_OMP_PARALLEL:
2459 return true;
2460 default:
2461 break;
2463 break;
2464 case GIMPLE_OMP_ORDERED:
2465 for (; ctx != NULL; ctx = ctx->outer)
2466 switch (gimple_code (ctx->stmt))
2468 case GIMPLE_OMP_CRITICAL:
2469 case GIMPLE_OMP_TASK:
2470 error_at (gimple_location (stmt),
2471 "ordered region may not be closely nested inside "
2472 "of critical or explicit task region");
2473 return false;
2474 case GIMPLE_OMP_FOR:
2475 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2476 OMP_CLAUSE_ORDERED) == NULL)
2478 error_at (gimple_location (stmt),
2479 "ordered region must be closely nested inside "
2480 "a loop region with an ordered clause");
2481 return false;
2483 return true;
2484 case GIMPLE_OMP_PARALLEL:
2485 error_at (gimple_location (stmt),
2486 "ordered region must be closely nested inside "
2487 "a loop region with an ordered clause");
2488 return false;
2489 default:
2490 break;
2492 break;
2493 case GIMPLE_OMP_CRITICAL:
2494 for (; ctx != NULL; ctx = ctx->outer)
2495 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2496 && (gimple_omp_critical_name (stmt)
2497 == gimple_omp_critical_name (ctx->stmt)))
2499 error_at (gimple_location (stmt),
2500 "critical region may not be nested inside a critical "
2501 "region with the same name");
2502 return false;
2504 break;
2505 case GIMPLE_OMP_TEAMS:
2506 if (ctx == NULL
2507 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2508 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2510 error_at (gimple_location (stmt),
2511 "teams construct not closely nested inside of target "
2512 "region");
2513 return false;
2515 break;
2516 case GIMPLE_OMP_TARGET:
2517 for (; ctx != NULL; ctx = ctx->outer)
2518 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
2519 && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION)
2521 const char *name;
2522 switch (gimple_omp_target_kind (stmt))
2524 case GF_OMP_TARGET_KIND_REGION: name = "target"; break;
2525 case GF_OMP_TARGET_KIND_DATA: name = "target data"; break;
2526 case GF_OMP_TARGET_KIND_UPDATE: name = "target update"; break;
2527 default: gcc_unreachable ();
2529 warning_at (gimple_location (stmt), 0,
2530 "%s construct inside of target region", name);
2532 break;
2533 default:
2534 break;
2536 return true;
2540 /* Helper function scan_omp.
2542 Callback for walk_tree or operators in walk_gimple_stmt used to
2543 scan for OpenMP directives in TP. */
2545 static tree
2546 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2548 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2549 omp_context *ctx = (omp_context *) wi->info;
2550 tree t = *tp;
2552 switch (TREE_CODE (t))
2554 case VAR_DECL:
2555 case PARM_DECL:
2556 case LABEL_DECL:
2557 case RESULT_DECL:
2558 if (ctx)
2559 *tp = remap_decl (t, &ctx->cb);
2560 break;
2562 default:
2563 if (ctx && TYPE_P (t))
2564 *tp = remap_type (t, &ctx->cb);
2565 else if (!DECL_P (t))
2567 *walk_subtrees = 1;
2568 if (ctx)
2570 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2571 if (tem != TREE_TYPE (t))
2573 if (TREE_CODE (t) == INTEGER_CST)
2574 *tp = wide_int_to_tree (tem, t);
2575 else
2576 TREE_TYPE (t) = tem;
2580 break;
2583 return NULL_TREE;
2586 /* Return true if FNDECL is a setjmp or a longjmp. */
2588 static bool
2589 setjmp_or_longjmp_p (const_tree fndecl)
2591 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2592 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2593 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2594 return true;
2596 tree declname = DECL_NAME (fndecl);
2597 if (!declname)
2598 return false;
2599 const char *name = IDENTIFIER_POINTER (declname);
2600 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2604 /* Helper function for scan_omp.
2606 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2607 the current statement in GSI. */
2609 static tree
2610 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2611 struct walk_stmt_info *wi)
2613 gimple stmt = gsi_stmt (*gsi);
2614 omp_context *ctx = (omp_context *) wi->info;
2616 if (gimple_has_location (stmt))
2617 input_location = gimple_location (stmt);
2619 /* Check the OpenMP nesting restrictions. */
2620 bool remove = false;
2621 if (is_gimple_omp (stmt))
2622 remove = !check_omp_nesting_restrictions (stmt, ctx);
2623 else if (is_gimple_call (stmt))
2625 tree fndecl = gimple_call_fndecl (stmt);
2626 if (fndecl)
2628 if (setjmp_or_longjmp_p (fndecl)
2629 && ctx
2630 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2631 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2633 remove = true;
2634 error_at (gimple_location (stmt),
2635 "setjmp/longjmp inside simd construct");
2637 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2638 switch (DECL_FUNCTION_CODE (fndecl))
2640 case BUILT_IN_GOMP_BARRIER:
2641 case BUILT_IN_GOMP_CANCEL:
2642 case BUILT_IN_GOMP_CANCELLATION_POINT:
2643 case BUILT_IN_GOMP_TASKYIELD:
2644 case BUILT_IN_GOMP_TASKWAIT:
2645 case BUILT_IN_GOMP_TASKGROUP_START:
2646 case BUILT_IN_GOMP_TASKGROUP_END:
2647 remove = !check_omp_nesting_restrictions (stmt, ctx);
2648 break;
2649 default:
2650 break;
2654 if (remove)
2656 stmt = gimple_build_nop ();
2657 gsi_replace (gsi, stmt, false);
2660 *handled_ops_p = true;
2662 switch (gimple_code (stmt))
2664 case GIMPLE_OMP_PARALLEL:
2665 taskreg_nesting_level++;
2666 scan_omp_parallel (gsi, ctx);
2667 taskreg_nesting_level--;
2668 break;
2670 case GIMPLE_OMP_TASK:
2671 taskreg_nesting_level++;
2672 scan_omp_task (gsi, ctx);
2673 taskreg_nesting_level--;
2674 break;
2676 case GIMPLE_OMP_FOR:
2677 scan_omp_for (stmt, ctx);
2678 break;
2680 case GIMPLE_OMP_SECTIONS:
2681 scan_omp_sections (stmt, ctx);
2682 break;
2684 case GIMPLE_OMP_SINGLE:
2685 scan_omp_single (stmt, ctx);
2686 break;
2688 case GIMPLE_OMP_SECTION:
2689 case GIMPLE_OMP_MASTER:
2690 case GIMPLE_OMP_TASKGROUP:
2691 case GIMPLE_OMP_ORDERED:
2692 case GIMPLE_OMP_CRITICAL:
2693 ctx = new_omp_context (stmt, ctx);
2694 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2695 break;
2697 case GIMPLE_OMP_TARGET:
2698 scan_omp_target (stmt, ctx);
2699 break;
2701 case GIMPLE_OMP_TEAMS:
2702 scan_omp_teams (stmt, ctx);
2703 break;
2705 case GIMPLE_BIND:
2707 tree var;
2709 *handled_ops_p = false;
2710 if (ctx)
2711 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2712 insert_decl_map (&ctx->cb, var, var);
2714 break;
2715 default:
2716 *handled_ops_p = false;
2717 break;
2720 return NULL_TREE;
2724 /* Scan all the statements starting at the current statement. CTX
2725 contains context information about the OpenMP directives and
2726 clauses found during the scan. */
2728 static void
2729 scan_omp (gimple_seq *body_p, omp_context *ctx)
2731 location_t saved_location;
2732 struct walk_stmt_info wi;
2734 memset (&wi, 0, sizeof (wi));
2735 wi.info = ctx;
2736 wi.want_locations = true;
2738 saved_location = input_location;
2739 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2740 input_location = saved_location;
2743 /* Re-gimplification and code generation routines. */
2745 /* Build a call to GOMP_barrier. */
2747 static gimple
2748 build_omp_barrier (tree lhs)
2750 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2751 : BUILT_IN_GOMP_BARRIER);
2752 gimple g = gimple_build_call (fndecl, 0);
2753 if (lhs)
2754 gimple_call_set_lhs (g, lhs);
2755 return g;
2758 /* If a context was created for STMT when it was scanned, return it. */
2760 static omp_context *
2761 maybe_lookup_ctx (gimple stmt)
2763 splay_tree_node n;
2764 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2765 return n ? (omp_context *) n->value : NULL;
2769 /* Find the mapping for DECL in CTX or the immediately enclosing
2770 context that has a mapping for DECL.
2772 If CTX is a nested parallel directive, we may have to use the decl
2773 mappings created in CTX's parent context. Suppose that we have the
2774 following parallel nesting (variable UIDs showed for clarity):
2776 iD.1562 = 0;
2777 #omp parallel shared(iD.1562) -> outer parallel
2778 iD.1562 = iD.1562 + 1;
2780 #omp parallel shared (iD.1562) -> inner parallel
2781 iD.1562 = iD.1562 - 1;
2783 Each parallel structure will create a distinct .omp_data_s structure
2784 for copying iD.1562 in/out of the directive:
2786 outer parallel .omp_data_s.1.i -> iD.1562
2787 inner parallel .omp_data_s.2.i -> iD.1562
2789 A shared variable mapping will produce a copy-out operation before
2790 the parallel directive and a copy-in operation after it. So, in
2791 this case we would have:
2793 iD.1562 = 0;
2794 .omp_data_o.1.i = iD.1562;
2795 #omp parallel shared(iD.1562) -> outer parallel
2796 .omp_data_i.1 = &.omp_data_o.1
2797 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2799 .omp_data_o.2.i = iD.1562; -> **
2800 #omp parallel shared(iD.1562) -> inner parallel
2801 .omp_data_i.2 = &.omp_data_o.2
2802 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2805 ** This is a problem. The symbol iD.1562 cannot be referenced
2806 inside the body of the outer parallel region. But since we are
2807 emitting this copy operation while expanding the inner parallel
2808 directive, we need to access the CTX structure of the outer
2809 parallel directive to get the correct mapping:
2811 .omp_data_o.2.i = .omp_data_i.1->i
2813 Since there may be other workshare or parallel directives enclosing
2814 the parallel directive, it may be necessary to walk up the context
2815 parent chain. This is not a problem in general because nested
2816 parallelism happens only rarely. */
2818 static tree
2819 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2821 tree t;
2822 omp_context *up;
2824 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2825 t = maybe_lookup_decl (decl, up);
2827 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2829 return t ? t : decl;
2833 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2834 in outer contexts. */
2836 static tree
2837 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2839 tree t = NULL;
2840 omp_context *up;
2842 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2843 t = maybe_lookup_decl (decl, up);
2845 return t ? t : decl;
2849 /* Construct the initialization value for reduction CLAUSE. */
2851 tree
2852 omp_reduction_init (tree clause, tree type)
2854 location_t loc = OMP_CLAUSE_LOCATION (clause);
2855 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2857 case PLUS_EXPR:
2858 case MINUS_EXPR:
2859 case BIT_IOR_EXPR:
2860 case BIT_XOR_EXPR:
2861 case TRUTH_OR_EXPR:
2862 case TRUTH_ORIF_EXPR:
2863 case TRUTH_XOR_EXPR:
2864 case NE_EXPR:
2865 return build_zero_cst (type);
2867 case MULT_EXPR:
2868 case TRUTH_AND_EXPR:
2869 case TRUTH_ANDIF_EXPR:
2870 case EQ_EXPR:
2871 return fold_convert_loc (loc, type, integer_one_node);
2873 case BIT_AND_EXPR:
2874 return fold_convert_loc (loc, type, integer_minus_one_node);
2876 case MAX_EXPR:
2877 if (SCALAR_FLOAT_TYPE_P (type))
2879 REAL_VALUE_TYPE max, min;
2880 if (HONOR_INFINITIES (TYPE_MODE (type)))
2882 real_inf (&max);
2883 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2885 else
2886 real_maxval (&min, 1, TYPE_MODE (type));
2887 return build_real (type, min);
2889 else
2891 gcc_assert (INTEGRAL_TYPE_P (type));
2892 return TYPE_MIN_VALUE (type);
2895 case MIN_EXPR:
2896 if (SCALAR_FLOAT_TYPE_P (type))
2898 REAL_VALUE_TYPE max;
2899 if (HONOR_INFINITIES (TYPE_MODE (type)))
2900 real_inf (&max);
2901 else
2902 real_maxval (&max, 0, TYPE_MODE (type));
2903 return build_real (type, max);
2905 else
2907 gcc_assert (INTEGRAL_TYPE_P (type));
2908 return TYPE_MAX_VALUE (type);
2911 default:
2912 gcc_unreachable ();
2916 /* Return alignment to be assumed for var in CLAUSE, which should be
2917 OMP_CLAUSE_ALIGNED. */
2919 static tree
2920 omp_clause_aligned_alignment (tree clause)
2922 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
2923 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
2925 /* Otherwise return implementation defined alignment. */
2926 unsigned int al = 1;
2927 enum machine_mode mode, vmode;
2928 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2929 if (vs)
2930 vs = 1 << floor_log2 (vs);
2931 static enum mode_class classes[]
2932 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
2933 for (int i = 0; i < 4; i += 2)
2934 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
2935 mode != VOIDmode;
2936 mode = GET_MODE_WIDER_MODE (mode))
2938 vmode = targetm.vectorize.preferred_simd_mode (mode);
2939 if (GET_MODE_CLASS (vmode) != classes[i + 1])
2940 continue;
2941 while (vs
2942 && GET_MODE_SIZE (vmode) < vs
2943 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
2944 vmode = GET_MODE_2XWIDER_MODE (vmode);
2946 tree type = lang_hooks.types.type_for_mode (mode, 1);
2947 if (type == NULL_TREE || TYPE_MODE (type) != mode)
2948 continue;
2949 type = build_vector_type (type, GET_MODE_SIZE (vmode)
2950 / GET_MODE_SIZE (mode));
2951 if (TYPE_MODE (type) != vmode)
2952 continue;
2953 if (TYPE_ALIGN_UNIT (type) > al)
2954 al = TYPE_ALIGN_UNIT (type);
2956 return build_int_cst (integer_type_node, al);
2959 /* Return maximum possible vectorization factor for the target. */
2961 static int
2962 omp_max_vf (void)
2964 if (!optimize
2965 || optimize_debug
2966 || !flag_tree_loop_optimize
2967 || (!flag_tree_loop_vectorize
2968 && (global_options_set.x_flag_tree_loop_vectorize
2969 || global_options_set.x_flag_tree_vectorize)))
2970 return 1;
2972 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2973 if (vs)
2975 vs = 1 << floor_log2 (vs);
2976 return vs;
2978 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
2979 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
2980 return GET_MODE_NUNITS (vqimode);
2981 return 1;
2984 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2985 privatization. */
2987 static bool
2988 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
2989 tree &idx, tree &lane, tree &ivar, tree &lvar)
2991 if (max_vf == 0)
2993 max_vf = omp_max_vf ();
2994 if (max_vf > 1)
2996 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2997 OMP_CLAUSE_SAFELEN);
2998 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
2999 max_vf = 1;
3000 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3001 max_vf) == -1)
3002 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3004 if (max_vf > 1)
3006 idx = create_tmp_var (unsigned_type_node, NULL);
3007 lane = create_tmp_var (unsigned_type_node, NULL);
3010 if (max_vf == 1)
3011 return false;
3013 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3014 tree avar = create_tmp_var_raw (atype, NULL);
3015 if (TREE_ADDRESSABLE (new_var))
3016 TREE_ADDRESSABLE (avar) = 1;
3017 DECL_ATTRIBUTES (avar)
3018 = tree_cons (get_identifier ("omp simd array"), NULL,
3019 DECL_ATTRIBUTES (avar));
3020 gimple_add_tmp_var (avar);
3021 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3022 NULL_TREE, NULL_TREE);
3023 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3024 NULL_TREE, NULL_TREE);
3025 if (DECL_P (new_var))
3027 SET_DECL_VALUE_EXPR (new_var, lvar);
3028 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3030 return true;
3033 /* Helper function of lower_rec_input_clauses. For a reference
3034 in simd reduction, add an underlying variable it will reference. */
3036 static void
3037 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3039 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3040 if (TREE_CONSTANT (z))
3042 const char *name = NULL;
3043 if (DECL_NAME (new_vard))
3044 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3046 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3047 gimple_add_tmp_var (z);
3048 TREE_ADDRESSABLE (z) = 1;
3049 z = build_fold_addr_expr_loc (loc, z);
3050 gimplify_assign (new_vard, z, ilist);
3054 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3055 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3056 private variables. Initialization statements go in ILIST, while calls
3057 to destructors go in DLIST. */
3059 static void
3060 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3061 omp_context *ctx, struct omp_for_data *fd)
3063 tree c, dtor, copyin_seq, x, ptr;
3064 bool copyin_by_ref = false;
3065 bool lastprivate_firstprivate = false;
3066 bool reduction_omp_orig_ref = false;
3067 int pass;
3068 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3069 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3070 int max_vf = 0;
3071 tree lane = NULL_TREE, idx = NULL_TREE;
3072 tree ivar = NULL_TREE, lvar = NULL_TREE;
3073 gimple_seq llist[2] = { NULL, NULL };
3075 copyin_seq = NULL;
3077 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3078 with data sharing clauses referencing variable sized vars. That
3079 is unnecessarily hard to support and very unlikely to result in
3080 vectorized code anyway. */
3081 if (is_simd)
3082 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3083 switch (OMP_CLAUSE_CODE (c))
3085 case OMP_CLAUSE_LINEAR:
3086 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3087 max_vf = 1;
3088 /* FALLTHRU */
3089 case OMP_CLAUSE_REDUCTION:
3090 case OMP_CLAUSE_PRIVATE:
3091 case OMP_CLAUSE_FIRSTPRIVATE:
3092 case OMP_CLAUSE_LASTPRIVATE:
3093 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3094 max_vf = 1;
3095 break;
3096 default:
3097 continue;
3100 /* Do all the fixed sized types in the first pass, and the variable sized
3101 types in the second pass. This makes sure that the scalar arguments to
3102 the variable sized types are processed before we use them in the
3103 variable sized operations. */
3104 for (pass = 0; pass < 2; ++pass)
3106 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3108 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3109 tree var, new_var;
3110 bool by_ref;
3111 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3113 switch (c_kind)
3115 case OMP_CLAUSE_PRIVATE:
3116 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3117 continue;
3118 break;
3119 case OMP_CLAUSE_SHARED:
3120 /* Ignore shared directives in teams construct. */
3121 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3122 continue;
3123 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3125 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3126 continue;
3128 case OMP_CLAUSE_FIRSTPRIVATE:
3129 case OMP_CLAUSE_COPYIN:
3130 case OMP_CLAUSE_LINEAR:
3131 break;
3132 case OMP_CLAUSE_REDUCTION:
3133 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3134 reduction_omp_orig_ref = true;
3135 break;
3136 case OMP_CLAUSE__LOOPTEMP_:
3137 /* Handle _looptemp_ clauses only on parallel. */
3138 if (fd)
3139 continue;
3140 break;
3141 case OMP_CLAUSE_LASTPRIVATE:
3142 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3144 lastprivate_firstprivate = true;
3145 if (pass != 0)
3146 continue;
3148 /* Even without corresponding firstprivate, if
3149 decl is Fortran allocatable, it needs outer var
3150 reference. */
3151 else if (pass == 0
3152 && lang_hooks.decls.omp_private_outer_ref
3153 (OMP_CLAUSE_DECL (c)))
3154 lastprivate_firstprivate = true;
3155 break;
3156 case OMP_CLAUSE_ALIGNED:
3157 if (pass == 0)
3158 continue;
3159 var = OMP_CLAUSE_DECL (c);
3160 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3161 && !is_global_var (var))
3163 new_var = maybe_lookup_decl (var, ctx);
3164 if (new_var == NULL_TREE)
3165 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3166 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3167 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3168 omp_clause_aligned_alignment (c));
3169 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3170 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3171 gimplify_and_add (x, ilist);
3173 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3174 && is_global_var (var))
3176 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3177 new_var = lookup_decl (var, ctx);
3178 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3179 t = build_fold_addr_expr_loc (clause_loc, t);
3180 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3181 t = build_call_expr_loc (clause_loc, t2, 2, t,
3182 omp_clause_aligned_alignment (c));
3183 t = fold_convert_loc (clause_loc, ptype, t);
3184 x = create_tmp_var (ptype, NULL);
3185 t = build2 (MODIFY_EXPR, ptype, x, t);
3186 gimplify_and_add (t, ilist);
3187 t = build_simple_mem_ref_loc (clause_loc, x);
3188 SET_DECL_VALUE_EXPR (new_var, t);
3189 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3191 continue;
3192 default:
3193 continue;
3196 new_var = var = OMP_CLAUSE_DECL (c);
3197 if (c_kind != OMP_CLAUSE_COPYIN)
3198 new_var = lookup_decl (var, ctx);
3200 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3202 if (pass != 0)
3203 continue;
3205 else if (is_variable_sized (var))
3207 /* For variable sized types, we need to allocate the
3208 actual storage here. Call alloca and store the
3209 result in the pointer decl that we created elsewhere. */
3210 if (pass == 0)
3211 continue;
3213 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3215 gimple stmt;
3216 tree tmp, atmp;
3218 ptr = DECL_VALUE_EXPR (new_var);
3219 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3220 ptr = TREE_OPERAND (ptr, 0);
3221 gcc_assert (DECL_P (ptr));
3222 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3224 /* void *tmp = __builtin_alloca */
3225 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3226 stmt = gimple_build_call (atmp, 1, x);
3227 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3228 gimple_add_tmp_var (tmp);
3229 gimple_call_set_lhs (stmt, tmp);
3231 gimple_seq_add_stmt (ilist, stmt);
3233 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3234 gimplify_assign (ptr, x, ilist);
3237 else if (is_reference (var))
3239 /* For references that are being privatized for Fortran,
3240 allocate new backing storage for the new pointer
3241 variable. This allows us to avoid changing all the
3242 code that expects a pointer to something that expects
3243 a direct variable. */
3244 if (pass == 0)
3245 continue;
3247 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3248 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3250 x = build_receiver_ref (var, false, ctx);
3251 x = build_fold_addr_expr_loc (clause_loc, x);
3253 else if (TREE_CONSTANT (x))
3255 /* For reduction in SIMD loop, defer adding the
3256 initialization of the reference, because if we decide
3257 to use SIMD array for it, the initilization could cause
3258 expansion ICE. */
3259 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3260 x = NULL_TREE;
3261 else
3263 const char *name = NULL;
3264 if (DECL_NAME (var))
3265 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3267 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3268 name);
3269 gimple_add_tmp_var (x);
3270 TREE_ADDRESSABLE (x) = 1;
3271 x = build_fold_addr_expr_loc (clause_loc, x);
3274 else
3276 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3277 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3280 if (x)
3282 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3283 gimplify_assign (new_var, x, ilist);
3286 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3288 else if (c_kind == OMP_CLAUSE_REDUCTION
3289 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3291 if (pass == 0)
3292 continue;
3294 else if (pass != 0)
3295 continue;
3297 switch (OMP_CLAUSE_CODE (c))
3299 case OMP_CLAUSE_SHARED:
3300 /* Ignore shared directives in teams construct. */
3301 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3302 continue;
3303 /* Shared global vars are just accessed directly. */
3304 if (is_global_var (new_var))
3305 break;
3306 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3307 needs to be delayed until after fixup_child_record_type so
3308 that we get the correct type during the dereference. */
3309 by_ref = use_pointer_for_field (var, ctx);
3310 x = build_receiver_ref (var, by_ref, ctx);
3311 SET_DECL_VALUE_EXPR (new_var, x);
3312 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3314 /* ??? If VAR is not passed by reference, and the variable
3315 hasn't been initialized yet, then we'll get a warning for
3316 the store into the omp_data_s structure. Ideally, we'd be
3317 able to notice this and not store anything at all, but
3318 we're generating code too early. Suppress the warning. */
3319 if (!by_ref)
3320 TREE_NO_WARNING (var) = 1;
3321 break;
3323 case OMP_CLAUSE_LASTPRIVATE:
3324 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3325 break;
3326 /* FALLTHRU */
3328 case OMP_CLAUSE_PRIVATE:
3329 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3330 x = build_outer_var_ref (var, ctx);
3331 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3333 if (is_task_ctx (ctx))
3334 x = build_receiver_ref (var, false, ctx);
3335 else
3336 x = build_outer_var_ref (var, ctx);
3338 else
3339 x = NULL;
3340 do_private:
3341 tree nx;
3342 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3343 if (is_simd)
3345 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3346 if ((TREE_ADDRESSABLE (new_var) || nx || y
3347 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3348 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3349 idx, lane, ivar, lvar))
3351 if (nx)
3352 x = lang_hooks.decls.omp_clause_default_ctor
3353 (c, unshare_expr (ivar), x);
3354 if (nx && x)
3355 gimplify_and_add (x, &llist[0]);
3356 if (y)
3358 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3359 if (y)
3361 gimple_seq tseq = NULL;
3363 dtor = y;
3364 gimplify_stmt (&dtor, &tseq);
3365 gimple_seq_add_seq (&llist[1], tseq);
3368 break;
3371 if (nx)
3372 gimplify_and_add (nx, ilist);
3373 /* FALLTHRU */
3375 do_dtor:
3376 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3377 if (x)
3379 gimple_seq tseq = NULL;
3381 dtor = x;
3382 gimplify_stmt (&dtor, &tseq);
3383 gimple_seq_add_seq (dlist, tseq);
3385 break;
3387 case OMP_CLAUSE_LINEAR:
3388 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3389 goto do_firstprivate;
3390 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3391 x = NULL;
3392 else
3393 x = build_outer_var_ref (var, ctx);
3394 goto do_private;
3396 case OMP_CLAUSE_FIRSTPRIVATE:
3397 if (is_task_ctx (ctx))
3399 if (is_reference (var) || is_variable_sized (var))
3400 goto do_dtor;
3401 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3402 ctx))
3403 || use_pointer_for_field (var, NULL))
3405 x = build_receiver_ref (var, false, ctx);
3406 SET_DECL_VALUE_EXPR (new_var, x);
3407 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3408 goto do_dtor;
3411 do_firstprivate:
3412 x = build_outer_var_ref (var, ctx);
3413 if (is_simd)
3415 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3416 && gimple_omp_for_combined_into_p (ctx->stmt))
3418 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3419 tree stept = TREE_TYPE (t);
3420 tree ct = find_omp_clause (clauses,
3421 OMP_CLAUSE__LOOPTEMP_);
3422 gcc_assert (ct);
3423 tree l = OMP_CLAUSE_DECL (ct);
3424 tree n1 = fd->loop.n1;
3425 tree step = fd->loop.step;
3426 tree itype = TREE_TYPE (l);
3427 if (POINTER_TYPE_P (itype))
3428 itype = signed_type_for (itype);
3429 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3430 if (TYPE_UNSIGNED (itype)
3431 && fd->loop.cond_code == GT_EXPR)
3432 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3433 fold_build1 (NEGATE_EXPR, itype, l),
3434 fold_build1 (NEGATE_EXPR,
3435 itype, step));
3436 else
3437 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3438 t = fold_build2 (MULT_EXPR, stept,
3439 fold_convert (stept, l), t);
3441 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3443 x = lang_hooks.decls.omp_clause_linear_ctor
3444 (c, new_var, x, t);
3445 gimplify_and_add (x, ilist);
3446 goto do_dtor;
3449 if (POINTER_TYPE_P (TREE_TYPE (x)))
3450 x = fold_build2 (POINTER_PLUS_EXPR,
3451 TREE_TYPE (x), x, t);
3452 else
3453 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3456 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3457 || TREE_ADDRESSABLE (new_var))
3458 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3459 idx, lane, ivar, lvar))
3461 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3463 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3464 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3465 gimplify_and_add (x, ilist);
3466 gimple_stmt_iterator gsi
3467 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3468 gimple g
3469 = gimple_build_assign (unshare_expr (lvar), iv);
3470 gsi_insert_before_without_update (&gsi, g,
3471 GSI_SAME_STMT);
3472 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3473 enum tree_code code = PLUS_EXPR;
3474 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3475 code = POINTER_PLUS_EXPR;
3476 g = gimple_build_assign_with_ops (code, iv, iv, t);
3477 gsi_insert_before_without_update (&gsi, g,
3478 GSI_SAME_STMT);
3479 break;
3481 x = lang_hooks.decls.omp_clause_copy_ctor
3482 (c, unshare_expr (ivar), x);
3483 gimplify_and_add (x, &llist[0]);
3484 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3485 if (x)
3487 gimple_seq tseq = NULL;
3489 dtor = x;
3490 gimplify_stmt (&dtor, &tseq);
3491 gimple_seq_add_seq (&llist[1], tseq);
3493 break;
3496 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3497 gimplify_and_add (x, ilist);
3498 goto do_dtor;
3500 case OMP_CLAUSE__LOOPTEMP_:
3501 gcc_assert (is_parallel_ctx (ctx));
3502 x = build_outer_var_ref (var, ctx);
3503 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3504 gimplify_and_add (x, ilist);
3505 break;
3507 case OMP_CLAUSE_COPYIN:
3508 by_ref = use_pointer_for_field (var, NULL);
3509 x = build_receiver_ref (var, by_ref, ctx);
3510 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3511 append_to_statement_list (x, &copyin_seq);
3512 copyin_by_ref |= by_ref;
3513 break;
3515 case OMP_CLAUSE_REDUCTION:
3516 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3518 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3519 gimple tseq;
3520 x = build_outer_var_ref (var, ctx);
3522 if (is_reference (var)
3523 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3524 TREE_TYPE (x)))
3525 x = build_fold_addr_expr_loc (clause_loc, x);
3526 SET_DECL_VALUE_EXPR (placeholder, x);
3527 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3528 tree new_vard = new_var;
3529 if (is_reference (var))
3531 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3532 new_vard = TREE_OPERAND (new_var, 0);
3533 gcc_assert (DECL_P (new_vard));
3535 if (is_simd
3536 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3537 idx, lane, ivar, lvar))
3539 if (new_vard == new_var)
3541 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3542 SET_DECL_VALUE_EXPR (new_var, ivar);
3544 else
3546 SET_DECL_VALUE_EXPR (new_vard,
3547 build_fold_addr_expr (ivar));
3548 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3550 x = lang_hooks.decls.omp_clause_default_ctor
3551 (c, unshare_expr (ivar),
3552 build_outer_var_ref (var, ctx));
3553 if (x)
3554 gimplify_and_add (x, &llist[0]);
3555 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3557 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3558 lower_omp (&tseq, ctx);
3559 gimple_seq_add_seq (&llist[0], tseq);
3561 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3562 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3563 lower_omp (&tseq, ctx);
3564 gimple_seq_add_seq (&llist[1], tseq);
3565 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3566 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3567 if (new_vard == new_var)
3568 SET_DECL_VALUE_EXPR (new_var, lvar);
3569 else
3570 SET_DECL_VALUE_EXPR (new_vard,
3571 build_fold_addr_expr (lvar));
3572 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3573 if (x)
3575 tseq = NULL;
3576 dtor = x;
3577 gimplify_stmt (&dtor, &tseq);
3578 gimple_seq_add_seq (&llist[1], tseq);
3580 break;
3582 /* If this is a reference to constant size reduction var
3583 with placeholder, we haven't emitted the initializer
3584 for it because it is undesirable if SIMD arrays are used.
3585 But if they aren't used, we need to emit the deferred
3586 initialization now. */
3587 else if (is_reference (var) && is_simd)
3588 handle_simd_reference (clause_loc, new_vard, ilist);
3589 x = lang_hooks.decls.omp_clause_default_ctor
3590 (c, unshare_expr (new_var),
3591 build_outer_var_ref (var, ctx));
3592 if (x)
3593 gimplify_and_add (x, ilist);
3594 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3596 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3597 lower_omp (&tseq, ctx);
3598 gimple_seq_add_seq (ilist, tseq);
3600 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3601 if (is_simd)
3603 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3604 lower_omp (&tseq, ctx);
3605 gimple_seq_add_seq (dlist, tseq);
3606 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3608 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3609 goto do_dtor;
3611 else
3613 x = omp_reduction_init (c, TREE_TYPE (new_var));
3614 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3615 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3617 /* reduction(-:var) sums up the partial results, so it
3618 acts identically to reduction(+:var). */
3619 if (code == MINUS_EXPR)
3620 code = PLUS_EXPR;
3622 tree new_vard = new_var;
3623 if (is_simd && is_reference (var))
3625 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3626 new_vard = TREE_OPERAND (new_var, 0);
3627 gcc_assert (DECL_P (new_vard));
3629 if (is_simd
3630 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3631 idx, lane, ivar, lvar))
3633 tree ref = build_outer_var_ref (var, ctx);
3635 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3637 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3638 ref = build_outer_var_ref (var, ctx);
3639 gimplify_assign (ref, x, &llist[1]);
3641 if (new_vard != new_var)
3643 SET_DECL_VALUE_EXPR (new_vard,
3644 build_fold_addr_expr (lvar));
3645 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3648 else
3650 if (is_reference (var) && is_simd)
3651 handle_simd_reference (clause_loc, new_vard, ilist);
3652 gimplify_assign (new_var, x, ilist);
3653 if (is_simd)
3655 tree ref = build_outer_var_ref (var, ctx);
3657 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3658 ref = build_outer_var_ref (var, ctx);
3659 gimplify_assign (ref, x, dlist);
3663 break;
3665 default:
3666 gcc_unreachable ();
3671 if (lane)
3673 tree uid = create_tmp_var (ptr_type_node, "simduid");
3674 /* Don't want uninit warnings on simduid, it is always uninitialized,
3675 but we use it not for the value, but for the DECL_UID only. */
3676 TREE_NO_WARNING (uid) = 1;
3677 gimple g
3678 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3679 gimple_call_set_lhs (g, lane);
3680 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3681 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3682 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3683 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3684 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3685 gimple_omp_for_set_clauses (ctx->stmt, c);
3686 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3687 build_int_cst (unsigned_type_node, 0),
3688 NULL_TREE);
3689 gimple_seq_add_stmt (ilist, g);
3690 for (int i = 0; i < 2; i++)
3691 if (llist[i])
3693 tree vf = create_tmp_var (unsigned_type_node, NULL);
3694 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3695 gimple_call_set_lhs (g, vf);
3696 gimple_seq *seq = i == 0 ? ilist : dlist;
3697 gimple_seq_add_stmt (seq, g);
3698 tree t = build_int_cst (unsigned_type_node, 0);
3699 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3700 gimple_seq_add_stmt (seq, g);
3701 tree body = create_artificial_label (UNKNOWN_LOCATION);
3702 tree header = create_artificial_label (UNKNOWN_LOCATION);
3703 tree end = create_artificial_label (UNKNOWN_LOCATION);
3704 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3705 gimple_seq_add_stmt (seq, gimple_build_label (body));
3706 gimple_seq_add_seq (seq, llist[i]);
3707 t = build_int_cst (unsigned_type_node, 1);
3708 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3709 gimple_seq_add_stmt (seq, g);
3710 gimple_seq_add_stmt (seq, gimple_build_label (header));
3711 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3712 gimple_seq_add_stmt (seq, g);
3713 gimple_seq_add_stmt (seq, gimple_build_label (end));
3717 /* The copyin sequence is not to be executed by the main thread, since
3718 that would result in self-copies. Perhaps not visible to scalars,
3719 but it certainly is to C++ operator=. */
3720 if (copyin_seq)
3722 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3724 x = build2 (NE_EXPR, boolean_type_node, x,
3725 build_int_cst (TREE_TYPE (x), 0));
3726 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3727 gimplify_and_add (x, ilist);
3730 /* If any copyin variable is passed by reference, we must ensure the
3731 master thread doesn't modify it before it is copied over in all
3732 threads. Similarly for variables in both firstprivate and
3733 lastprivate clauses we need to ensure the lastprivate copying
3734 happens after firstprivate copying in all threads. And similarly
3735 for UDRs if initializer expression refers to omp_orig. */
3736 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3738 /* Don't add any barrier for #pragma omp simd or
3739 #pragma omp distribute. */
3740 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3741 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3742 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3745 /* If max_vf is non-zero, then we can use only a vectorization factor
3746 up to the max_vf we chose. So stick it into the safelen clause. */
3747 if (max_vf)
3749 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3750 OMP_CLAUSE_SAFELEN);
3751 if (c == NULL_TREE
3752 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
3753 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3754 max_vf) == 1))
3756 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3757 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3758 max_vf);
3759 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3760 gimple_omp_for_set_clauses (ctx->stmt, c);
3766 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3767 both parallel and workshare constructs. PREDICATE may be NULL if it's
3768 always true. */
3770 static void
3771 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3772 omp_context *ctx)
3774 tree x, c, label = NULL, orig_clauses = clauses;
3775 bool par_clauses = false;
3776 tree simduid = NULL, lastlane = NULL;
3778 /* Early exit if there are no lastprivate or linear clauses. */
3779 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3780 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3781 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3782 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3783 break;
3784 if (clauses == NULL)
3786 /* If this was a workshare clause, see if it had been combined
3787 with its parallel. In that case, look for the clauses on the
3788 parallel statement itself. */
3789 if (is_parallel_ctx (ctx))
3790 return;
3792 ctx = ctx->outer;
3793 if (ctx == NULL || !is_parallel_ctx (ctx))
3794 return;
3796 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3797 OMP_CLAUSE_LASTPRIVATE);
3798 if (clauses == NULL)
3799 return;
3800 par_clauses = true;
3803 if (predicate)
3805 gimple stmt;
3806 tree label_true, arm1, arm2;
3808 label = create_artificial_label (UNKNOWN_LOCATION);
3809 label_true = create_artificial_label (UNKNOWN_LOCATION);
3810 arm1 = TREE_OPERAND (predicate, 0);
3811 arm2 = TREE_OPERAND (predicate, 1);
3812 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3813 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3814 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3815 label_true, label);
3816 gimple_seq_add_stmt (stmt_list, stmt);
3817 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3820 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3821 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3823 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3824 if (simduid)
3825 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3828 for (c = clauses; c ;)
3830 tree var, new_var;
3831 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3833 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3834 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3835 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3837 var = OMP_CLAUSE_DECL (c);
3838 new_var = lookup_decl (var, ctx);
3840 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3842 tree val = DECL_VALUE_EXPR (new_var);
3843 if (TREE_CODE (val) == ARRAY_REF
3844 && VAR_P (TREE_OPERAND (val, 0))
3845 && lookup_attribute ("omp simd array",
3846 DECL_ATTRIBUTES (TREE_OPERAND (val,
3847 0))))
3849 if (lastlane == NULL)
3851 lastlane = create_tmp_var (unsigned_type_node, NULL);
3852 gimple g
3853 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
3854 2, simduid,
3855 TREE_OPERAND (val, 1));
3856 gimple_call_set_lhs (g, lastlane);
3857 gimple_seq_add_stmt (stmt_list, g);
3859 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
3860 TREE_OPERAND (val, 0), lastlane,
3861 NULL_TREE, NULL_TREE);
3865 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3866 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
3868 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
3869 gimple_seq_add_seq (stmt_list,
3870 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3871 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
3873 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3874 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
3876 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
3877 gimple_seq_add_seq (stmt_list,
3878 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
3879 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
3882 x = build_outer_var_ref (var, ctx);
3883 if (is_reference (var))
3884 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3885 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
3886 gimplify_and_add (x, stmt_list);
3888 c = OMP_CLAUSE_CHAIN (c);
3889 if (c == NULL && !par_clauses)
3891 /* If this was a workshare clause, see if it had been combined
3892 with its parallel. In that case, continue looking for the
3893 clauses also on the parallel statement itself. */
3894 if (is_parallel_ctx (ctx))
3895 break;
3897 ctx = ctx->outer;
3898 if (ctx == NULL || !is_parallel_ctx (ctx))
3899 break;
3901 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3902 OMP_CLAUSE_LASTPRIVATE);
3903 par_clauses = true;
3907 if (label)
3908 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
3912 /* Generate code to implement the REDUCTION clauses. */
3914 static void
3915 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
3917 gimple_seq sub_seq = NULL;
3918 gimple stmt;
3919 tree x, c;
3920 int count = 0;
3922 /* SIMD reductions are handled in lower_rec_input_clauses. */
3923 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3924 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3925 return;
3927 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3928 update in that case, otherwise use a lock. */
3929 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
3930 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
3932 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3934 /* Never use OMP_ATOMIC for array reductions or UDRs. */
3935 count = -1;
3936 break;
3938 count++;
3941 if (count == 0)
3942 return;
3944 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3946 tree var, ref, new_var;
3947 enum tree_code code;
3948 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3950 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
3951 continue;
3953 var = OMP_CLAUSE_DECL (c);
3954 new_var = lookup_decl (var, ctx);
3955 if (is_reference (var))
3956 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3957 ref = build_outer_var_ref (var, ctx);
3958 code = OMP_CLAUSE_REDUCTION_CODE (c);
3960 /* reduction(-:var) sums up the partial results, so it acts
3961 identically to reduction(+:var). */
3962 if (code == MINUS_EXPR)
3963 code = PLUS_EXPR;
3965 if (count == 1)
3967 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
3969 addr = save_expr (addr);
3970 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
3971 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
3972 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
3973 gimplify_and_add (x, stmt_seqp);
3974 return;
3977 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3979 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3981 if (is_reference (var)
3982 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3983 TREE_TYPE (ref)))
3984 ref = build_fold_addr_expr_loc (clause_loc, ref);
3985 SET_DECL_VALUE_EXPR (placeholder, ref);
3986 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3987 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
3988 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
3989 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3990 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
3992 else
3994 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3995 ref = build_outer_var_ref (var, ctx);
3996 gimplify_assign (ref, x, &sub_seq);
4000 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4002 gimple_seq_add_stmt (stmt_seqp, stmt);
4004 gimple_seq_add_seq (stmt_seqp, sub_seq);
4006 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4008 gimple_seq_add_stmt (stmt_seqp, stmt);
4012 /* Generate code to implement the COPYPRIVATE clauses. */
4014 static void
4015 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4016 omp_context *ctx)
4018 tree c;
4020 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4022 tree var, new_var, ref, x;
4023 bool by_ref;
4024 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4026 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4027 continue;
4029 var = OMP_CLAUSE_DECL (c);
4030 by_ref = use_pointer_for_field (var, NULL);
4032 ref = build_sender_ref (var, ctx);
4033 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4034 if (by_ref)
4036 x = build_fold_addr_expr_loc (clause_loc, new_var);
4037 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4039 gimplify_assign (ref, x, slist);
4041 ref = build_receiver_ref (var, false, ctx);
4042 if (by_ref)
4044 ref = fold_convert_loc (clause_loc,
4045 build_pointer_type (TREE_TYPE (new_var)),
4046 ref);
4047 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4049 if (is_reference (var))
4051 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4052 ref = build_simple_mem_ref_loc (clause_loc, ref);
4053 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4055 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4056 gimplify_and_add (x, rlist);
4061 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4062 and REDUCTION from the sender (aka parent) side. */
4064 static void
4065 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4066 omp_context *ctx)
4068 tree c;
4070 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4072 tree val, ref, x, var;
4073 bool by_ref, do_in = false, do_out = false;
4074 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4076 switch (OMP_CLAUSE_CODE (c))
4078 case OMP_CLAUSE_PRIVATE:
4079 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4080 break;
4081 continue;
4082 case OMP_CLAUSE_FIRSTPRIVATE:
4083 case OMP_CLAUSE_COPYIN:
4084 case OMP_CLAUSE_LASTPRIVATE:
4085 case OMP_CLAUSE_REDUCTION:
4086 case OMP_CLAUSE__LOOPTEMP_:
4087 break;
4088 default:
4089 continue;
4092 val = OMP_CLAUSE_DECL (c);
4093 var = lookup_decl_in_outer_ctx (val, ctx);
4095 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4096 && is_global_var (var))
4097 continue;
4098 if (is_variable_sized (val))
4099 continue;
4100 by_ref = use_pointer_for_field (val, NULL);
4102 switch (OMP_CLAUSE_CODE (c))
4104 case OMP_CLAUSE_PRIVATE:
4105 case OMP_CLAUSE_FIRSTPRIVATE:
4106 case OMP_CLAUSE_COPYIN:
4107 case OMP_CLAUSE__LOOPTEMP_:
4108 do_in = true;
4109 break;
4111 case OMP_CLAUSE_LASTPRIVATE:
4112 if (by_ref || is_reference (val))
4114 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4115 continue;
4116 do_in = true;
4118 else
4120 do_out = true;
4121 if (lang_hooks.decls.omp_private_outer_ref (val))
4122 do_in = true;
4124 break;
4126 case OMP_CLAUSE_REDUCTION:
4127 do_in = true;
4128 do_out = !(by_ref || is_reference (val));
4129 break;
4131 default:
4132 gcc_unreachable ();
4135 if (do_in)
4137 ref = build_sender_ref (val, ctx);
4138 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4139 gimplify_assign (ref, x, ilist);
4140 if (is_task_ctx (ctx))
4141 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4144 if (do_out)
4146 ref = build_sender_ref (val, ctx);
4147 gimplify_assign (var, ref, olist);
4152 /* Generate code to implement SHARED from the sender (aka parent)
4153 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4154 list things that got automatically shared. */
4156 static void
4157 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4159 tree var, ovar, nvar, f, x, record_type;
4161 if (ctx->record_type == NULL)
4162 return;
4164 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4165 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4167 ovar = DECL_ABSTRACT_ORIGIN (f);
4168 nvar = maybe_lookup_decl (ovar, ctx);
4169 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4170 continue;
4172 /* If CTX is a nested parallel directive. Find the immediately
4173 enclosing parallel or workshare construct that contains a
4174 mapping for OVAR. */
4175 var = lookup_decl_in_outer_ctx (ovar, ctx);
4177 if (use_pointer_for_field (ovar, ctx))
4179 x = build_sender_ref (ovar, ctx);
4180 var = build_fold_addr_expr (var);
4181 gimplify_assign (x, var, ilist);
4183 else
4185 x = build_sender_ref (ovar, ctx);
4186 gimplify_assign (x, var, ilist);
4188 if (!TREE_READONLY (var)
4189 /* We don't need to receive a new reference to a result
4190 or parm decl. In fact we may not store to it as we will
4191 invalidate any pending RSO and generate wrong gimple
4192 during inlining. */
4193 && !((TREE_CODE (var) == RESULT_DECL
4194 || TREE_CODE (var) == PARM_DECL)
4195 && DECL_BY_REFERENCE (var)))
4197 x = build_sender_ref (ovar, ctx);
4198 gimplify_assign (var, x, olist);
4205 /* A convenience function to build an empty GIMPLE_COND with just the
4206 condition. */
4208 static gimple
4209 gimple_build_cond_empty (tree cond)
4211 enum tree_code pred_code;
4212 tree lhs, rhs;
4214 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4215 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4219 /* Build the function calls to GOMP_parallel_start etc to actually
4220 generate the parallel operation. REGION is the parallel region
4221 being expanded. BB is the block where to insert the code. WS_ARGS
4222 will be set if this is a call to a combined parallel+workshare
4223 construct, it contains the list of additional arguments needed by
4224 the workshare construct. */
4226 static void
4227 expand_parallel_call (struct omp_region *region, basic_block bb,
4228 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4230 tree t, t1, t2, val, cond, c, clauses, flags;
4231 gimple_stmt_iterator gsi;
4232 gimple stmt;
4233 enum built_in_function start_ix;
4234 int start_ix2;
4235 location_t clause_loc;
4236 vec<tree, va_gc> *args;
4238 clauses = gimple_omp_parallel_clauses (entry_stmt);
4240 /* Determine what flavor of GOMP_parallel we will be
4241 emitting. */
4242 start_ix = BUILT_IN_GOMP_PARALLEL;
4243 if (is_combined_parallel (region))
4245 switch (region->inner->type)
4247 case GIMPLE_OMP_FOR:
4248 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4249 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4250 + (region->inner->sched_kind
4251 == OMP_CLAUSE_SCHEDULE_RUNTIME
4252 ? 3 : region->inner->sched_kind));
4253 start_ix = (enum built_in_function)start_ix2;
4254 break;
4255 case GIMPLE_OMP_SECTIONS:
4256 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4257 break;
4258 default:
4259 gcc_unreachable ();
4263 /* By default, the value of NUM_THREADS is zero (selected at run time)
4264 and there is no conditional. */
4265 cond = NULL_TREE;
4266 val = build_int_cst (unsigned_type_node, 0);
4267 flags = build_int_cst (unsigned_type_node, 0);
4269 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4270 if (c)
4271 cond = OMP_CLAUSE_IF_EXPR (c);
4273 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4274 if (c)
4276 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4277 clause_loc = OMP_CLAUSE_LOCATION (c);
4279 else
4280 clause_loc = gimple_location (entry_stmt);
4282 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4283 if (c)
4284 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4286 /* Ensure 'val' is of the correct type. */
4287 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4289 /* If we found the clause 'if (cond)', build either
4290 (cond != 0) or (cond ? val : 1u). */
4291 if (cond)
4293 cond = gimple_boolify (cond);
4295 if (integer_zerop (val))
4296 val = fold_build2_loc (clause_loc,
4297 EQ_EXPR, unsigned_type_node, cond,
4298 build_int_cst (TREE_TYPE (cond), 0));
4299 else
4301 basic_block cond_bb, then_bb, else_bb;
4302 edge e, e_then, e_else;
4303 tree tmp_then, tmp_else, tmp_join, tmp_var;
4305 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4306 if (gimple_in_ssa_p (cfun))
4308 tmp_then = make_ssa_name (tmp_var, NULL);
4309 tmp_else = make_ssa_name (tmp_var, NULL);
4310 tmp_join = make_ssa_name (tmp_var, NULL);
4312 else
4314 tmp_then = tmp_var;
4315 tmp_else = tmp_var;
4316 tmp_join = tmp_var;
4319 e = split_block (bb, NULL);
4320 cond_bb = e->src;
4321 bb = e->dest;
4322 remove_edge (e);
4324 then_bb = create_empty_bb (cond_bb);
4325 else_bb = create_empty_bb (then_bb);
4326 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4327 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4329 stmt = gimple_build_cond_empty (cond);
4330 gsi = gsi_start_bb (cond_bb);
4331 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4333 gsi = gsi_start_bb (then_bb);
4334 stmt = gimple_build_assign (tmp_then, val);
4335 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4337 gsi = gsi_start_bb (else_bb);
4338 stmt = gimple_build_assign
4339 (tmp_else, build_int_cst (unsigned_type_node, 1));
4340 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4342 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4343 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4344 add_bb_to_loop (then_bb, cond_bb->loop_father);
4345 add_bb_to_loop (else_bb, cond_bb->loop_father);
4346 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4347 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4349 if (gimple_in_ssa_p (cfun))
4351 gimple phi = create_phi_node (tmp_join, bb);
4352 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4353 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4356 val = tmp_join;
4359 gsi = gsi_start_bb (bb);
4360 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4361 false, GSI_CONTINUE_LINKING);
4364 gsi = gsi_last_bb (bb);
4365 t = gimple_omp_parallel_data_arg (entry_stmt);
4366 if (t == NULL)
4367 t1 = null_pointer_node;
4368 else
4369 t1 = build_fold_addr_expr (t);
4370 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4372 vec_alloc (args, 4 + vec_safe_length (ws_args));
4373 args->quick_push (t2);
4374 args->quick_push (t1);
4375 args->quick_push (val);
4376 if (ws_args)
4377 args->splice (*ws_args);
4378 args->quick_push (flags);
4380 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4381 builtin_decl_explicit (start_ix), args);
4383 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4384 false, GSI_CONTINUE_LINKING);
4388 /* Build the function call to GOMP_task to actually
4389 generate the task operation. BB is the block where to insert the code. */
4391 static void
4392 expand_task_call (basic_block bb, gimple entry_stmt)
4394 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4395 gimple_stmt_iterator gsi;
4396 location_t loc = gimple_location (entry_stmt);
4398 clauses = gimple_omp_task_clauses (entry_stmt);
4400 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4401 if (c)
4402 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4403 else
4404 cond = boolean_true_node;
4406 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4407 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4408 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4409 flags = build_int_cst (unsigned_type_node,
4410 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4412 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4413 if (c)
4415 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4416 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4417 build_int_cst (unsigned_type_node, 2),
4418 build_int_cst (unsigned_type_node, 0));
4419 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4421 if (depend)
4422 depend = OMP_CLAUSE_DECL (depend);
4423 else
4424 depend = build_int_cst (ptr_type_node, 0);
4426 gsi = gsi_last_bb (bb);
4427 t = gimple_omp_task_data_arg (entry_stmt);
4428 if (t == NULL)
4429 t2 = null_pointer_node;
4430 else
4431 t2 = build_fold_addr_expr_loc (loc, t);
4432 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4433 t = gimple_omp_task_copy_fn (entry_stmt);
4434 if (t == NULL)
4435 t3 = null_pointer_node;
4436 else
4437 t3 = build_fold_addr_expr_loc (loc, t);
4439 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4440 8, t1, t2, t3,
4441 gimple_omp_task_arg_size (entry_stmt),
4442 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4443 depend);
4445 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4446 false, GSI_CONTINUE_LINKING);
4450 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4451 catch handler and return it. This prevents programs from violating the
4452 structured block semantics with throws. */
4454 static gimple_seq
4455 maybe_catch_exception (gimple_seq body)
4457 gimple g;
4458 tree decl;
4460 if (!flag_exceptions)
4461 return body;
4463 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4464 decl = lang_hooks.eh_protect_cleanup_actions ();
4465 else
4466 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4468 g = gimple_build_eh_must_not_throw (decl);
4469 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4470 GIMPLE_TRY_CATCH);
4472 return gimple_seq_alloc_with_stmt (g);
4475 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4477 static tree
4478 vec2chain (vec<tree, va_gc> *v)
4480 tree chain = NULL_TREE, t;
4481 unsigned ix;
4483 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4485 DECL_CHAIN (t) = chain;
4486 chain = t;
4489 return chain;
4493 /* Remove barriers in REGION->EXIT's block. Note that this is only
4494 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4495 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4496 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4497 removed. */
4499 static void
4500 remove_exit_barrier (struct omp_region *region)
4502 gimple_stmt_iterator gsi;
4503 basic_block exit_bb;
4504 edge_iterator ei;
4505 edge e;
4506 gimple stmt;
4507 int any_addressable_vars = -1;
4509 exit_bb = region->exit;
4511 /* If the parallel region doesn't return, we don't have REGION->EXIT
4512 block at all. */
4513 if (! exit_bb)
4514 return;
4516 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4517 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4518 statements that can appear in between are extremely limited -- no
4519 memory operations at all. Here, we allow nothing at all, so the
4520 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4521 gsi = gsi_last_bb (exit_bb);
4522 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4523 gsi_prev (&gsi);
4524 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4525 return;
4527 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4529 gsi = gsi_last_bb (e->src);
4530 if (gsi_end_p (gsi))
4531 continue;
4532 stmt = gsi_stmt (gsi);
4533 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4534 && !gimple_omp_return_nowait_p (stmt))
4536 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4537 in many cases. If there could be tasks queued, the barrier
4538 might be needed to let the tasks run before some local
4539 variable of the parallel that the task uses as shared
4540 runs out of scope. The task can be spawned either
4541 from within current function (this would be easy to check)
4542 or from some function it calls and gets passed an address
4543 of such a variable. */
4544 if (any_addressable_vars < 0)
4546 gimple parallel_stmt = last_stmt (region->entry);
4547 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4548 tree local_decls, block, decl;
4549 unsigned ix;
4551 any_addressable_vars = 0;
4552 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4553 if (TREE_ADDRESSABLE (decl))
4555 any_addressable_vars = 1;
4556 break;
4558 for (block = gimple_block (stmt);
4559 !any_addressable_vars
4560 && block
4561 && TREE_CODE (block) == BLOCK;
4562 block = BLOCK_SUPERCONTEXT (block))
4564 for (local_decls = BLOCK_VARS (block);
4565 local_decls;
4566 local_decls = DECL_CHAIN (local_decls))
4567 if (TREE_ADDRESSABLE (local_decls))
4569 any_addressable_vars = 1;
4570 break;
4572 if (block == gimple_block (parallel_stmt))
4573 break;
4576 if (!any_addressable_vars)
4577 gimple_omp_return_set_nowait (stmt);
4582 static void
4583 remove_exit_barriers (struct omp_region *region)
4585 if (region->type == GIMPLE_OMP_PARALLEL)
4586 remove_exit_barrier (region);
4588 if (region->inner)
4590 region = region->inner;
4591 remove_exit_barriers (region);
4592 while (region->next)
4594 region = region->next;
4595 remove_exit_barriers (region);
4600 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4601 calls. These can't be declared as const functions, but
4602 within one parallel body they are constant, so they can be
4603 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4604 which are declared const. Similarly for task body, except
4605 that in untied task omp_get_thread_num () can change at any task
4606 scheduling point. */
4608 static void
4609 optimize_omp_library_calls (gimple entry_stmt)
4611 basic_block bb;
4612 gimple_stmt_iterator gsi;
4613 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4614 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4615 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4616 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4617 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4618 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4619 OMP_CLAUSE_UNTIED) != NULL);
4621 FOR_EACH_BB_FN (bb, cfun)
4622 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4624 gimple call = gsi_stmt (gsi);
4625 tree decl;
4627 if (is_gimple_call (call)
4628 && (decl = gimple_call_fndecl (call))
4629 && DECL_EXTERNAL (decl)
4630 && TREE_PUBLIC (decl)
4631 && DECL_INITIAL (decl) == NULL)
4633 tree built_in;
4635 if (DECL_NAME (decl) == thr_num_id)
4637 /* In #pragma omp task untied omp_get_thread_num () can change
4638 during the execution of the task region. */
4639 if (untied_task)
4640 continue;
4641 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4643 else if (DECL_NAME (decl) == num_thr_id)
4644 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4645 else
4646 continue;
4648 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4649 || gimple_call_num_args (call) != 0)
4650 continue;
4652 if (flag_exceptions && !TREE_NOTHROW (decl))
4653 continue;
4655 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4656 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4657 TREE_TYPE (TREE_TYPE (built_in))))
4658 continue;
4660 gimple_call_set_fndecl (call, built_in);
4665 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4666 regimplified. */
4668 static tree
4669 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4671 tree t = *tp;
4673 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4674 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4675 return t;
4677 if (TREE_CODE (t) == ADDR_EXPR)
4678 recompute_tree_invariant_for_addr_expr (t);
4680 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4681 return NULL_TREE;
4684 /* Prepend TO = FROM assignment before *GSI_P. */
4686 static void
4687 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4689 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4690 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4691 true, GSI_SAME_STMT);
4692 gimple stmt = gimple_build_assign (to, from);
4693 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4694 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4695 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4697 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4698 gimple_regimplify_operands (stmt, &gsi);
4702 /* Expand the OpenMP parallel or task directive starting at REGION. */
4704 static void
4705 expand_omp_taskreg (struct omp_region *region)
4707 basic_block entry_bb, exit_bb, new_bb;
4708 struct function *child_cfun;
4709 tree child_fn, block, t;
4710 gimple_stmt_iterator gsi;
4711 gimple entry_stmt, stmt;
4712 edge e;
4713 vec<tree, va_gc> *ws_args;
4715 entry_stmt = last_stmt (region->entry);
4716 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4717 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4719 entry_bb = region->entry;
4720 exit_bb = region->exit;
4722 if (is_combined_parallel (region))
4723 ws_args = region->ws_args;
4724 else
4725 ws_args = NULL;
4727 if (child_cfun->cfg)
4729 /* Due to inlining, it may happen that we have already outlined
4730 the region, in which case all we need to do is make the
4731 sub-graph unreachable and emit the parallel call. */
4732 edge entry_succ_e, exit_succ_e;
4734 entry_succ_e = single_succ_edge (entry_bb);
4736 gsi = gsi_last_bb (entry_bb);
4737 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4738 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4739 gsi_remove (&gsi, true);
4741 new_bb = entry_bb;
4742 if (exit_bb)
4744 exit_succ_e = single_succ_edge (exit_bb);
4745 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4747 remove_edge_and_dominated_blocks (entry_succ_e);
4749 else
4751 unsigned srcidx, dstidx, num;
4753 /* If the parallel region needs data sent from the parent
4754 function, then the very first statement (except possible
4755 tree profile counter updates) of the parallel body
4756 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4757 &.OMP_DATA_O is passed as an argument to the child function,
4758 we need to replace it with the argument as seen by the child
4759 function.
4761 In most cases, this will end up being the identity assignment
4762 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4763 a function call that has been inlined, the original PARM_DECL
4764 .OMP_DATA_I may have been converted into a different local
4765 variable. In which case, we need to keep the assignment. */
4766 if (gimple_omp_taskreg_data_arg (entry_stmt))
4768 basic_block entry_succ_bb = single_succ (entry_bb);
4769 tree arg, narg;
4770 gimple parcopy_stmt = NULL;
4772 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4774 gimple stmt;
4776 gcc_assert (!gsi_end_p (gsi));
4777 stmt = gsi_stmt (gsi);
4778 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4779 continue;
4781 if (gimple_num_ops (stmt) == 2)
4783 tree arg = gimple_assign_rhs1 (stmt);
4785 /* We're ignore the subcode because we're
4786 effectively doing a STRIP_NOPS. */
4788 if (TREE_CODE (arg) == ADDR_EXPR
4789 && TREE_OPERAND (arg, 0)
4790 == gimple_omp_taskreg_data_arg (entry_stmt))
4792 parcopy_stmt = stmt;
4793 break;
4798 gcc_assert (parcopy_stmt != NULL);
4799 arg = DECL_ARGUMENTS (child_fn);
4801 if (!gimple_in_ssa_p (cfun))
4803 if (gimple_assign_lhs (parcopy_stmt) == arg)
4804 gsi_remove (&gsi, true);
4805 else
4807 /* ?? Is setting the subcode really necessary ?? */
4808 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
4809 gimple_assign_set_rhs1 (parcopy_stmt, arg);
4812 else
4814 /* If we are in ssa form, we must load the value from the default
4815 definition of the argument. That should not be defined now,
4816 since the argument is not used uninitialized. */
4817 gcc_assert (ssa_default_def (cfun, arg) == NULL);
4818 narg = make_ssa_name (arg, gimple_build_nop ());
4819 set_ssa_default_def (cfun, arg, narg);
4820 /* ?? Is setting the subcode really necessary ?? */
4821 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
4822 gimple_assign_set_rhs1 (parcopy_stmt, narg);
4823 update_stmt (parcopy_stmt);
4827 /* Declare local variables needed in CHILD_CFUN. */
4828 block = DECL_INITIAL (child_fn);
4829 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4830 /* The gimplifier could record temporaries in parallel/task block
4831 rather than in containing function's local_decls chain,
4832 which would mean cgraph missed finalizing them. Do it now. */
4833 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4834 if (TREE_CODE (t) == VAR_DECL
4835 && TREE_STATIC (t)
4836 && !DECL_EXTERNAL (t))
4837 varpool_finalize_decl (t);
4838 DECL_SAVED_TREE (child_fn) = NULL;
4839 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4840 gimple_set_body (child_fn, NULL);
4841 TREE_USED (block) = 1;
4843 /* Reset DECL_CONTEXT on function arguments. */
4844 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
4845 DECL_CONTEXT (t) = child_fn;
4847 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
4848 so that it can be moved to the child function. */
4849 gsi = gsi_last_bb (entry_bb);
4850 stmt = gsi_stmt (gsi);
4851 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
4852 || gimple_code (stmt) == GIMPLE_OMP_TASK));
4853 gsi_remove (&gsi, true);
4854 e = split_block (entry_bb, stmt);
4855 entry_bb = e->dest;
4856 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4858 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4859 if (exit_bb)
4861 gsi = gsi_last_bb (exit_bb);
4862 gcc_assert (!gsi_end_p (gsi)
4863 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4864 stmt = gimple_build_return (NULL);
4865 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4866 gsi_remove (&gsi, true);
4869 /* Move the parallel region into CHILD_CFUN. */
4871 if (gimple_in_ssa_p (cfun))
4873 init_tree_ssa (child_cfun);
4874 init_ssa_operands (child_cfun);
4875 child_cfun->gimple_df->in_ssa_p = true;
4876 block = NULL_TREE;
4878 else
4879 block = gimple_block (entry_stmt);
4881 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
4882 if (exit_bb)
4883 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
4884 /* When the OMP expansion process cannot guarantee an up-to-date
4885 loop tree arrange for the child function to fixup loops. */
4886 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
4887 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
4889 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
4890 num = vec_safe_length (child_cfun->local_decls);
4891 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
4893 t = (*child_cfun->local_decls)[srcidx];
4894 if (DECL_CONTEXT (t) == cfun->decl)
4895 continue;
4896 if (srcidx != dstidx)
4897 (*child_cfun->local_decls)[dstidx] = t;
4898 dstidx++;
4900 if (dstidx != num)
4901 vec_safe_truncate (child_cfun->local_decls, dstidx);
4903 /* Inform the callgraph about the new function. */
4904 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
4905 cgraph_add_new_function (child_fn, true);
4907 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4908 fixed in a following pass. */
4909 push_cfun (child_cfun);
4910 if (optimize)
4911 optimize_omp_library_calls (entry_stmt);
4912 rebuild_cgraph_edges ();
4914 /* Some EH regions might become dead, see PR34608. If
4915 pass_cleanup_cfg isn't the first pass to happen with the
4916 new child, these dead EH edges might cause problems.
4917 Clean them up now. */
4918 if (flag_exceptions)
4920 basic_block bb;
4921 bool changed = false;
4923 FOR_EACH_BB_FN (bb, cfun)
4924 changed |= gimple_purge_dead_eh_edges (bb);
4925 if (changed)
4926 cleanup_tree_cfg ();
4928 if (gimple_in_ssa_p (cfun))
4929 update_ssa (TODO_update_ssa);
4930 pop_cfun ();
4933 /* Emit a library call to launch the children threads. */
4934 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
4935 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
4936 else
4937 expand_task_call (new_bb, entry_stmt);
4938 if (gimple_in_ssa_p (cfun))
4939 update_ssa (TODO_update_ssa_only_virtuals);
4943 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4944 of the combined collapse > 1 loop constructs, generate code like:
4945 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4946 if (cond3 is <)
4947 adj = STEP3 - 1;
4948 else
4949 adj = STEP3 + 1;
4950 count3 = (adj + N32 - N31) / STEP3;
4951 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4952 if (cond2 is <)
4953 adj = STEP2 - 1;
4954 else
4955 adj = STEP2 + 1;
4956 count2 = (adj + N22 - N21) / STEP2;
4957 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4958 if (cond1 is <)
4959 adj = STEP1 - 1;
4960 else
4961 adj = STEP1 + 1;
4962 count1 = (adj + N12 - N11) / STEP1;
4963 count = count1 * count2 * count3;
4964 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4965 count = 0;
4966 and set ZERO_ITER_BB to that bb. If this isn't the outermost
4967 of the combined loop constructs, just initialize COUNTS array
4968 from the _looptemp_ clauses. */
4970 /* NOTE: It *could* be better to moosh all of the BBs together,
4971 creating one larger BB with all the computation and the unexpected
4972 jump at the end. I.e.
4974 bool zero3, zero2, zero1, zero;
4976 zero3 = N32 c3 N31;
4977 count3 = (N32 - N31) /[cl] STEP3;
4978 zero2 = N22 c2 N21;
4979 count2 = (N22 - N21) /[cl] STEP2;
4980 zero1 = N12 c1 N11;
4981 count1 = (N12 - N11) /[cl] STEP1;
4982 zero = zero3 || zero2 || zero1;
4983 count = count1 * count2 * count3;
4984 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4986 After all, we expect the zero=false, and thus we expect to have to
4987 evaluate all of the comparison expressions, so short-circuiting
4988 oughtn't be a win. Since the condition isn't protecting a
4989 denominator, we're not concerned about divide-by-zero, so we can
4990 fully evaluate count even if a numerator turned out to be wrong.
4992 It seems like putting this all together would create much better
4993 scheduling opportunities, and less pressure on the chip's branch
4994 predictor. */
4996 static void
4997 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4998 basic_block &entry_bb, tree *counts,
4999 basic_block &zero_iter_bb, int &first_zero_iter,
5000 basic_block &l2_dom_bb)
5002 tree t, type = TREE_TYPE (fd->loop.v);
5003 gimple stmt;
5004 edge e, ne;
5005 int i;
5007 /* Collapsed loops need work for expansion into SSA form. */
5008 gcc_assert (!gimple_in_ssa_p (cfun));
5010 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5011 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5013 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5014 isn't supposed to be handled, as the inner loop doesn't
5015 use it. */
5016 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5017 OMP_CLAUSE__LOOPTEMP_);
5018 gcc_assert (innerc);
5019 for (i = 0; i < fd->collapse; i++)
5021 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5022 OMP_CLAUSE__LOOPTEMP_);
5023 gcc_assert (innerc);
5024 if (i)
5025 counts[i] = OMP_CLAUSE_DECL (innerc);
5026 else
5027 counts[0] = NULL_TREE;
5029 return;
5032 for (i = 0; i < fd->collapse; i++)
5034 tree itype = TREE_TYPE (fd->loops[i].v);
5036 if (SSA_VAR_P (fd->loop.n2)
5037 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5038 fold_convert (itype, fd->loops[i].n1),
5039 fold_convert (itype, fd->loops[i].n2)))
5040 == NULL_TREE || !integer_onep (t)))
5042 tree n1, n2;
5043 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5044 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5045 true, GSI_SAME_STMT);
5046 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5047 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5048 true, GSI_SAME_STMT);
5049 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5050 NULL_TREE, NULL_TREE);
5051 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5052 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5053 expand_omp_regimplify_p, NULL, NULL)
5054 || walk_tree (gimple_cond_rhs_ptr (stmt),
5055 expand_omp_regimplify_p, NULL, NULL))
5057 *gsi = gsi_for_stmt (stmt);
5058 gimple_regimplify_operands (stmt, gsi);
5060 e = split_block (entry_bb, stmt);
5061 if (zero_iter_bb == NULL)
5063 first_zero_iter = i;
5064 zero_iter_bb = create_empty_bb (entry_bb);
5065 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5066 *gsi = gsi_after_labels (zero_iter_bb);
5067 stmt = gimple_build_assign (fd->loop.n2,
5068 build_zero_cst (type));
5069 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5070 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5071 entry_bb);
5073 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5074 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5075 e->flags = EDGE_TRUE_VALUE;
5076 e->probability = REG_BR_PROB_BASE - ne->probability;
5077 if (l2_dom_bb == NULL)
5078 l2_dom_bb = entry_bb;
5079 entry_bb = e->dest;
5080 *gsi = gsi_last_bb (entry_bb);
5083 if (POINTER_TYPE_P (itype))
5084 itype = signed_type_for (itype);
5085 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5086 ? -1 : 1));
5087 t = fold_build2 (PLUS_EXPR, itype,
5088 fold_convert (itype, fd->loops[i].step), t);
5089 t = fold_build2 (PLUS_EXPR, itype, t,
5090 fold_convert (itype, fd->loops[i].n2));
5091 t = fold_build2 (MINUS_EXPR, itype, t,
5092 fold_convert (itype, fd->loops[i].n1));
5093 /* ?? We could probably use CEIL_DIV_EXPR instead of
5094 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5095 generate the same code in the end because generically we
5096 don't know that the values involved must be negative for
5097 GT?? */
5098 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5099 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5100 fold_build1 (NEGATE_EXPR, itype, t),
5101 fold_build1 (NEGATE_EXPR, itype,
5102 fold_convert (itype,
5103 fd->loops[i].step)));
5104 else
5105 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5106 fold_convert (itype, fd->loops[i].step));
5107 t = fold_convert (type, t);
5108 if (TREE_CODE (t) == INTEGER_CST)
5109 counts[i] = t;
5110 else
5112 counts[i] = create_tmp_reg (type, ".count");
5113 expand_omp_build_assign (gsi, counts[i], t);
5115 if (SSA_VAR_P (fd->loop.n2))
5117 if (i == 0)
5118 t = counts[0];
5119 else
5120 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5121 expand_omp_build_assign (gsi, fd->loop.n2, t);
5127 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5128 T = V;
5129 V3 = N31 + (T % count3) * STEP3;
5130 T = T / count3;
5131 V2 = N21 + (T % count2) * STEP2;
5132 T = T / count2;
5133 V1 = N11 + T * STEP1;
5134 if this loop doesn't have an inner loop construct combined with it.
5135 If it does have an inner loop construct combined with it and the
5136 iteration count isn't known constant, store values from counts array
5137 into its _looptemp_ temporaries instead. */
5139 static void
5140 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5141 tree *counts, gimple inner_stmt, tree startvar)
5143 int i;
5144 if (gimple_omp_for_combined_p (fd->for_stmt))
5146 /* If fd->loop.n2 is constant, then no propagation of the counts
5147 is needed, they are constant. */
5148 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5149 return;
5151 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5152 ? gimple_omp_parallel_clauses (inner_stmt)
5153 : gimple_omp_for_clauses (inner_stmt);
5154 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5155 isn't supposed to be handled, as the inner loop doesn't
5156 use it. */
5157 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5158 gcc_assert (innerc);
5159 for (i = 0; i < fd->collapse; i++)
5161 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5162 OMP_CLAUSE__LOOPTEMP_);
5163 gcc_assert (innerc);
5164 if (i)
5166 tree tem = OMP_CLAUSE_DECL (innerc);
5167 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5168 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5169 false, GSI_CONTINUE_LINKING);
5170 gimple stmt = gimple_build_assign (tem, t);
5171 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5174 return;
5177 tree type = TREE_TYPE (fd->loop.v);
5178 tree tem = create_tmp_reg (type, ".tem");
5179 gimple stmt = gimple_build_assign (tem, startvar);
5180 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5182 for (i = fd->collapse - 1; i >= 0; i--)
5184 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5185 itype = vtype;
5186 if (POINTER_TYPE_P (vtype))
5187 itype = signed_type_for (vtype);
5188 if (i != 0)
5189 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5190 else
5191 t = tem;
5192 t = fold_convert (itype, t);
5193 t = fold_build2 (MULT_EXPR, itype, t,
5194 fold_convert (itype, fd->loops[i].step));
5195 if (POINTER_TYPE_P (vtype))
5196 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5197 else
5198 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5199 t = force_gimple_operand_gsi (gsi, t,
5200 DECL_P (fd->loops[i].v)
5201 && TREE_ADDRESSABLE (fd->loops[i].v),
5202 NULL_TREE, false,
5203 GSI_CONTINUE_LINKING);
5204 stmt = gimple_build_assign (fd->loops[i].v, t);
5205 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5206 if (i != 0)
5208 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5209 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5210 false, GSI_CONTINUE_LINKING);
5211 stmt = gimple_build_assign (tem, t);
5212 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5218 /* Helper function for expand_omp_for_*. Generate code like:
5219 L10:
5220 V3 += STEP3;
5221 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5222 L11:
5223 V3 = N31;
5224 V2 += STEP2;
5225 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5226 L12:
5227 V2 = N21;
5228 V1 += STEP1;
5229 goto BODY_BB; */
5231 static basic_block
5232 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5233 basic_block body_bb)
5235 basic_block last_bb, bb, collapse_bb = NULL;
5236 int i;
5237 gimple_stmt_iterator gsi;
5238 edge e;
5239 tree t;
5240 gimple stmt;
5242 last_bb = cont_bb;
5243 for (i = fd->collapse - 1; i >= 0; i--)
5245 tree vtype = TREE_TYPE (fd->loops[i].v);
5247 bb = create_empty_bb (last_bb);
5248 add_bb_to_loop (bb, last_bb->loop_father);
5249 gsi = gsi_start_bb (bb);
5251 if (i < fd->collapse - 1)
5253 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5254 e->probability = REG_BR_PROB_BASE / 8;
5256 t = fd->loops[i + 1].n1;
5257 t = force_gimple_operand_gsi (&gsi, t,
5258 DECL_P (fd->loops[i + 1].v)
5259 && TREE_ADDRESSABLE (fd->loops[i
5260 + 1].v),
5261 NULL_TREE, false,
5262 GSI_CONTINUE_LINKING);
5263 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5264 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5266 else
5267 collapse_bb = bb;
5269 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5271 if (POINTER_TYPE_P (vtype))
5272 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5273 else
5274 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5275 t = force_gimple_operand_gsi (&gsi, t,
5276 DECL_P (fd->loops[i].v)
5277 && TREE_ADDRESSABLE (fd->loops[i].v),
5278 NULL_TREE, false, GSI_CONTINUE_LINKING);
5279 stmt = gimple_build_assign (fd->loops[i].v, t);
5280 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5282 if (i > 0)
5284 t = fd->loops[i].n2;
5285 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5286 false, GSI_CONTINUE_LINKING);
5287 tree v = fd->loops[i].v;
5288 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5289 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5290 false, GSI_CONTINUE_LINKING);
5291 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5292 stmt = gimple_build_cond_empty (t);
5293 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5294 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5295 e->probability = REG_BR_PROB_BASE * 7 / 8;
5297 else
5298 make_edge (bb, body_bb, EDGE_FALLTHRU);
5299 last_bb = bb;
5302 return collapse_bb;
5306 /* A subroutine of expand_omp_for. Generate code for a parallel
5307 loop with any schedule. Given parameters:
5309 for (V = N1; V cond N2; V += STEP) BODY;
5311 where COND is "<" or ">", we generate pseudocode
5313 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5314 if (more) goto L0; else goto L3;
5316 V = istart0;
5317 iend = iend0;
5319 BODY;
5320 V += STEP;
5321 if (V cond iend) goto L1; else goto L2;
5323 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5326 If this is a combined omp parallel loop, instead of the call to
5327 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5328 If this is gimple_omp_for_combined_p loop, then instead of assigning
5329 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5330 inner GIMPLE_OMP_FOR and V += STEP; and
5331 if (V cond iend) goto L1; else goto L2; are removed.
5333 For collapsed loops, given parameters:
5334 collapse(3)
5335 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5336 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5337 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5338 BODY;
5340 we generate pseudocode
5342 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5343 if (cond3 is <)
5344 adj = STEP3 - 1;
5345 else
5346 adj = STEP3 + 1;
5347 count3 = (adj + N32 - N31) / STEP3;
5348 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5349 if (cond2 is <)
5350 adj = STEP2 - 1;
5351 else
5352 adj = STEP2 + 1;
5353 count2 = (adj + N22 - N21) / STEP2;
5354 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5355 if (cond1 is <)
5356 adj = STEP1 - 1;
5357 else
5358 adj = STEP1 + 1;
5359 count1 = (adj + N12 - N11) / STEP1;
5360 count = count1 * count2 * count3;
5361 goto Z1;
5363 count = 0;
5365 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5366 if (more) goto L0; else goto L3;
5368 V = istart0;
5369 T = V;
5370 V3 = N31 + (T % count3) * STEP3;
5371 T = T / count3;
5372 V2 = N21 + (T % count2) * STEP2;
5373 T = T / count2;
5374 V1 = N11 + T * STEP1;
5375 iend = iend0;
5377 BODY;
5378 V += 1;
5379 if (V < iend) goto L10; else goto L2;
5380 L10:
5381 V3 += STEP3;
5382 if (V3 cond3 N32) goto L1; else goto L11;
5383 L11:
5384 V3 = N31;
5385 V2 += STEP2;
5386 if (V2 cond2 N22) goto L1; else goto L12;
5387 L12:
5388 V2 = N21;
5389 V1 += STEP1;
5390 goto L1;
5392 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5397 static void
5398 expand_omp_for_generic (struct omp_region *region,
5399 struct omp_for_data *fd,
5400 enum built_in_function start_fn,
5401 enum built_in_function next_fn,
5402 gimple inner_stmt)
5404 tree type, istart0, iend0, iend;
5405 tree t, vmain, vback, bias = NULL_TREE;
5406 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5407 basic_block l2_bb = NULL, l3_bb = NULL;
5408 gimple_stmt_iterator gsi;
5409 gimple stmt;
5410 bool in_combined_parallel = is_combined_parallel (region);
5411 bool broken_loop = region->cont == NULL;
5412 edge e, ne;
5413 tree *counts = NULL;
5414 int i;
5416 gcc_assert (!broken_loop || !in_combined_parallel);
5417 gcc_assert (fd->iter_type == long_integer_type_node
5418 || !in_combined_parallel);
5420 type = TREE_TYPE (fd->loop.v);
5421 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5422 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5423 TREE_ADDRESSABLE (istart0) = 1;
5424 TREE_ADDRESSABLE (iend0) = 1;
5426 /* See if we need to bias by LLONG_MIN. */
5427 if (fd->iter_type == long_long_unsigned_type_node
5428 && TREE_CODE (type) == INTEGER_TYPE
5429 && !TYPE_UNSIGNED (type))
5431 tree n1, n2;
5433 if (fd->loop.cond_code == LT_EXPR)
5435 n1 = fd->loop.n1;
5436 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5438 else
5440 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5441 n2 = fd->loop.n1;
5443 if (TREE_CODE (n1) != INTEGER_CST
5444 || TREE_CODE (n2) != INTEGER_CST
5445 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5446 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5449 entry_bb = region->entry;
5450 cont_bb = region->cont;
5451 collapse_bb = NULL;
5452 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5453 gcc_assert (broken_loop
5454 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5455 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5456 l1_bb = single_succ (l0_bb);
5457 if (!broken_loop)
5459 l2_bb = create_empty_bb (cont_bb);
5460 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5461 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5463 else
5464 l2_bb = NULL;
5465 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5466 exit_bb = region->exit;
5468 gsi = gsi_last_bb (entry_bb);
5470 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5471 if (fd->collapse > 1)
5473 int first_zero_iter = -1;
5474 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5476 counts = XALLOCAVEC (tree, fd->collapse);
5477 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5478 zero_iter_bb, first_zero_iter,
5479 l2_dom_bb);
5481 if (zero_iter_bb)
5483 /* Some counts[i] vars might be uninitialized if
5484 some loop has zero iterations. But the body shouldn't
5485 be executed in that case, so just avoid uninit warnings. */
5486 for (i = first_zero_iter; i < fd->collapse; i++)
5487 if (SSA_VAR_P (counts[i]))
5488 TREE_NO_WARNING (counts[i]) = 1;
5489 gsi_prev (&gsi);
5490 e = split_block (entry_bb, gsi_stmt (gsi));
5491 entry_bb = e->dest;
5492 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5493 gsi = gsi_last_bb (entry_bb);
5494 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5495 get_immediate_dominator (CDI_DOMINATORS,
5496 zero_iter_bb));
5499 if (in_combined_parallel)
5501 /* In a combined parallel loop, emit a call to
5502 GOMP_loop_foo_next. */
5503 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5504 build_fold_addr_expr (istart0),
5505 build_fold_addr_expr (iend0));
5507 else
5509 tree t0, t1, t2, t3, t4;
5510 /* If this is not a combined parallel loop, emit a call to
5511 GOMP_loop_foo_start in ENTRY_BB. */
5512 t4 = build_fold_addr_expr (iend0);
5513 t3 = build_fold_addr_expr (istart0);
5514 t2 = fold_convert (fd->iter_type, fd->loop.step);
5515 t1 = fd->loop.n2;
5516 t0 = fd->loop.n1;
5517 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5519 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5520 OMP_CLAUSE__LOOPTEMP_);
5521 gcc_assert (innerc);
5522 t0 = OMP_CLAUSE_DECL (innerc);
5523 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5524 OMP_CLAUSE__LOOPTEMP_);
5525 gcc_assert (innerc);
5526 t1 = OMP_CLAUSE_DECL (innerc);
5528 if (POINTER_TYPE_P (TREE_TYPE (t0))
5529 && TYPE_PRECISION (TREE_TYPE (t0))
5530 != TYPE_PRECISION (fd->iter_type))
5532 /* Avoid casting pointers to integer of a different size. */
5533 tree itype = signed_type_for (type);
5534 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5535 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5537 else
5539 t1 = fold_convert (fd->iter_type, t1);
5540 t0 = fold_convert (fd->iter_type, t0);
5542 if (bias)
5544 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5545 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5547 if (fd->iter_type == long_integer_type_node)
5549 if (fd->chunk_size)
5551 t = fold_convert (fd->iter_type, fd->chunk_size);
5552 t = build_call_expr (builtin_decl_explicit (start_fn),
5553 6, t0, t1, t2, t, t3, t4);
5555 else
5556 t = build_call_expr (builtin_decl_explicit (start_fn),
5557 5, t0, t1, t2, t3, t4);
5559 else
5561 tree t5;
5562 tree c_bool_type;
5563 tree bfn_decl;
5565 /* The GOMP_loop_ull_*start functions have additional boolean
5566 argument, true for < loops and false for > loops.
5567 In Fortran, the C bool type can be different from
5568 boolean_type_node. */
5569 bfn_decl = builtin_decl_explicit (start_fn);
5570 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5571 t5 = build_int_cst (c_bool_type,
5572 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5573 if (fd->chunk_size)
5575 tree bfn_decl = builtin_decl_explicit (start_fn);
5576 t = fold_convert (fd->iter_type, fd->chunk_size);
5577 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5579 else
5580 t = build_call_expr (builtin_decl_explicit (start_fn),
5581 6, t5, t0, t1, t2, t3, t4);
5584 if (TREE_TYPE (t) != boolean_type_node)
5585 t = fold_build2 (NE_EXPR, boolean_type_node,
5586 t, build_int_cst (TREE_TYPE (t), 0));
5587 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5588 true, GSI_SAME_STMT);
5589 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5591 /* Remove the GIMPLE_OMP_FOR statement. */
5592 gsi_remove (&gsi, true);
5594 /* Iteration setup for sequential loop goes in L0_BB. */
5595 tree startvar = fd->loop.v;
5596 tree endvar = NULL_TREE;
5598 if (gimple_omp_for_combined_p (fd->for_stmt))
5600 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5601 && gimple_omp_for_kind (inner_stmt)
5602 == GF_OMP_FOR_KIND_SIMD);
5603 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5604 OMP_CLAUSE__LOOPTEMP_);
5605 gcc_assert (innerc);
5606 startvar = OMP_CLAUSE_DECL (innerc);
5607 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5608 OMP_CLAUSE__LOOPTEMP_);
5609 gcc_assert (innerc);
5610 endvar = OMP_CLAUSE_DECL (innerc);
5613 gsi = gsi_start_bb (l0_bb);
5614 t = istart0;
5615 if (bias)
5616 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5617 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5618 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5619 t = fold_convert (TREE_TYPE (startvar), t);
5620 t = force_gimple_operand_gsi (&gsi, t,
5621 DECL_P (startvar)
5622 && TREE_ADDRESSABLE (startvar),
5623 NULL_TREE, false, GSI_CONTINUE_LINKING);
5624 stmt = gimple_build_assign (startvar, t);
5625 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5627 t = iend0;
5628 if (bias)
5629 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5630 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5631 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5632 t = fold_convert (TREE_TYPE (startvar), t);
5633 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5634 false, GSI_CONTINUE_LINKING);
5635 if (endvar)
5637 stmt = gimple_build_assign (endvar, iend);
5638 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5639 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
5640 stmt = gimple_build_assign (fd->loop.v, iend);
5641 else
5642 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend,
5643 NULL_TREE);
5644 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5646 if (fd->collapse > 1)
5647 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5649 if (!broken_loop)
5651 /* Code to control the increment and predicate for the sequential
5652 loop goes in the CONT_BB. */
5653 gsi = gsi_last_bb (cont_bb);
5654 stmt = gsi_stmt (gsi);
5655 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5656 vmain = gimple_omp_continue_control_use (stmt);
5657 vback = gimple_omp_continue_control_def (stmt);
5659 if (!gimple_omp_for_combined_p (fd->for_stmt))
5661 if (POINTER_TYPE_P (type))
5662 t = fold_build_pointer_plus (vmain, fd->loop.step);
5663 else
5664 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5665 t = force_gimple_operand_gsi (&gsi, t,
5666 DECL_P (vback)
5667 && TREE_ADDRESSABLE (vback),
5668 NULL_TREE, true, GSI_SAME_STMT);
5669 stmt = gimple_build_assign (vback, t);
5670 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5672 t = build2 (fd->loop.cond_code, boolean_type_node,
5673 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5674 iend);
5675 stmt = gimple_build_cond_empty (t);
5676 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5679 /* Remove GIMPLE_OMP_CONTINUE. */
5680 gsi_remove (&gsi, true);
5682 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5683 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5685 /* Emit code to get the next parallel iteration in L2_BB. */
5686 gsi = gsi_start_bb (l2_bb);
5688 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5689 build_fold_addr_expr (istart0),
5690 build_fold_addr_expr (iend0));
5691 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5692 false, GSI_CONTINUE_LINKING);
5693 if (TREE_TYPE (t) != boolean_type_node)
5694 t = fold_build2 (NE_EXPR, boolean_type_node,
5695 t, build_int_cst (TREE_TYPE (t), 0));
5696 stmt = gimple_build_cond_empty (t);
5697 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5700 /* Add the loop cleanup function. */
5701 gsi = gsi_last_bb (exit_bb);
5702 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5703 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5704 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5705 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5706 else
5707 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5708 stmt = gimple_build_call (t, 0);
5709 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5710 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5711 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5712 gsi_remove (&gsi, true);
5714 /* Connect the new blocks. */
5715 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5716 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5718 if (!broken_loop)
5720 gimple_seq phis;
5722 e = find_edge (cont_bb, l3_bb);
5723 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5725 phis = phi_nodes (l3_bb);
5726 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5728 gimple phi = gsi_stmt (gsi);
5729 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5730 PHI_ARG_DEF_FROM_EDGE (phi, e));
5732 remove_edge (e);
5734 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5735 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5736 e = find_edge (cont_bb, l1_bb);
5737 if (gimple_omp_for_combined_p (fd->for_stmt))
5739 remove_edge (e);
5740 e = NULL;
5742 else if (fd->collapse > 1)
5744 remove_edge (e);
5745 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5747 else
5748 e->flags = EDGE_TRUE_VALUE;
5749 if (e)
5751 e->probability = REG_BR_PROB_BASE * 7 / 8;
5752 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5754 else
5756 e = find_edge (cont_bb, l2_bb);
5757 e->flags = EDGE_FALLTHRU;
5759 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5761 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5762 recompute_dominator (CDI_DOMINATORS, l2_bb));
5763 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5764 recompute_dominator (CDI_DOMINATORS, l3_bb));
5765 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5766 recompute_dominator (CDI_DOMINATORS, l0_bb));
5767 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5768 recompute_dominator (CDI_DOMINATORS, l1_bb));
5770 struct loop *outer_loop = alloc_loop ();
5771 outer_loop->header = l0_bb;
5772 outer_loop->latch = l2_bb;
5773 add_loop (outer_loop, l0_bb->loop_father);
5775 if (!gimple_omp_for_combined_p (fd->for_stmt))
5777 struct loop *loop = alloc_loop ();
5778 loop->header = l1_bb;
5779 /* The loop may have multiple latches. */
5780 add_loop (loop, outer_loop);
5786 /* A subroutine of expand_omp_for. Generate code for a parallel
5787 loop with static schedule and no specified chunk size. Given
5788 parameters:
5790 for (V = N1; V cond N2; V += STEP) BODY;
5792 where COND is "<" or ">", we generate pseudocode
5794 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5795 if (cond is <)
5796 adj = STEP - 1;
5797 else
5798 adj = STEP + 1;
5799 if ((__typeof (V)) -1 > 0 && cond is >)
5800 n = -(adj + N2 - N1) / -STEP;
5801 else
5802 n = (adj + N2 - N1) / STEP;
5803 q = n / nthreads;
5804 tt = n % nthreads;
5805 if (threadid < tt) goto L3; else goto L4;
5807 tt = 0;
5808 q = q + 1;
5810 s0 = q * threadid + tt;
5811 e0 = s0 + q;
5812 V = s0 * STEP + N1;
5813 if (s0 >= e0) goto L2; else goto L0;
5815 e = e0 * STEP + N1;
5817 BODY;
5818 V += STEP;
5819 if (V cond e) goto L1;
5823 static void
5824 expand_omp_for_static_nochunk (struct omp_region *region,
5825 struct omp_for_data *fd,
5826 gimple inner_stmt)
5828 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
5829 tree type, itype, vmain, vback;
5830 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
5831 basic_block body_bb, cont_bb, collapse_bb = NULL;
5832 basic_block fin_bb;
5833 gimple_stmt_iterator gsi;
5834 gimple stmt;
5835 edge ep;
5836 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
5837 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
5838 bool broken_loop = region->cont == NULL;
5839 tree *counts = NULL;
5840 tree n1, n2, step;
5842 itype = type = TREE_TYPE (fd->loop.v);
5843 if (POINTER_TYPE_P (type))
5844 itype = signed_type_for (type);
5846 entry_bb = region->entry;
5847 cont_bb = region->cont;
5848 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5849 fin_bb = BRANCH_EDGE (entry_bb)->dest;
5850 gcc_assert (broken_loop
5851 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
5852 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5853 body_bb = single_succ (seq_start_bb);
5854 if (!broken_loop)
5856 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
5857 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5859 exit_bb = region->exit;
5861 /* Iteration space partitioning goes in ENTRY_BB. */
5862 gsi = gsi_last_bb (entry_bb);
5863 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5865 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
5867 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
5868 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
5871 if (fd->collapse > 1)
5873 int first_zero_iter = -1;
5874 basic_block l2_dom_bb = NULL;
5876 counts = XALLOCAVEC (tree, fd->collapse);
5877 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5878 fin_bb, first_zero_iter,
5879 l2_dom_bb);
5880 t = NULL_TREE;
5882 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
5883 t = integer_one_node;
5884 else
5885 t = fold_binary (fd->loop.cond_code, boolean_type_node,
5886 fold_convert (type, fd->loop.n1),
5887 fold_convert (type, fd->loop.n2));
5888 if (fd->collapse == 1
5889 && TYPE_UNSIGNED (type)
5890 && (t == NULL_TREE || !integer_onep (t)))
5892 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5893 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5894 true, GSI_SAME_STMT);
5895 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5896 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5897 true, GSI_SAME_STMT);
5898 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
5899 NULL_TREE, NULL_TREE);
5900 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5901 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5902 expand_omp_regimplify_p, NULL, NULL)
5903 || walk_tree (gimple_cond_rhs_ptr (stmt),
5904 expand_omp_regimplify_p, NULL, NULL))
5906 gsi = gsi_for_stmt (stmt);
5907 gimple_regimplify_operands (stmt, &gsi);
5909 ep = split_block (entry_bb, stmt);
5910 ep->flags = EDGE_TRUE_VALUE;
5911 entry_bb = ep->dest;
5912 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
5913 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
5914 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
5915 if (gimple_in_ssa_p (cfun))
5917 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
5918 for (gsi = gsi_start_phis (fin_bb);
5919 !gsi_end_p (gsi); gsi_next (&gsi))
5921 gimple phi = gsi_stmt (gsi);
5922 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
5923 ep, UNKNOWN_LOCATION);
5926 gsi = gsi_last_bb (entry_bb);
5929 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
5930 t = fold_convert (itype, t);
5931 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5932 true, GSI_SAME_STMT);
5934 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
5935 t = fold_convert (itype, t);
5936 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5937 true, GSI_SAME_STMT);
5939 n1 = fd->loop.n1;
5940 n2 = fd->loop.n2;
5941 step = fd->loop.step;
5942 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5944 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5945 OMP_CLAUSE__LOOPTEMP_);
5946 gcc_assert (innerc);
5947 n1 = OMP_CLAUSE_DECL (innerc);
5948 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5949 OMP_CLAUSE__LOOPTEMP_);
5950 gcc_assert (innerc);
5951 n2 = OMP_CLAUSE_DECL (innerc);
5953 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
5954 true, NULL_TREE, true, GSI_SAME_STMT);
5955 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
5956 true, NULL_TREE, true, GSI_SAME_STMT);
5957 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
5958 true, NULL_TREE, true, GSI_SAME_STMT);
5960 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
5961 t = fold_build2 (PLUS_EXPR, itype, step, t);
5962 t = fold_build2 (PLUS_EXPR, itype, t, n2);
5963 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
5964 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
5965 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5966 fold_build1 (NEGATE_EXPR, itype, t),
5967 fold_build1 (NEGATE_EXPR, itype, step));
5968 else
5969 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
5970 t = fold_convert (itype, t);
5971 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5973 q = create_tmp_reg (itype, "q");
5974 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
5975 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5976 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
5978 tt = create_tmp_reg (itype, "tt");
5979 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
5980 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5981 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
5983 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
5984 stmt = gimple_build_cond_empty (t);
5985 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5987 second_bb = split_block (entry_bb, stmt)->dest;
5988 gsi = gsi_last_bb (second_bb);
5989 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5991 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
5992 GSI_SAME_STMT);
5993 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
5994 build_int_cst (itype, 1));
5995 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5997 third_bb = split_block (second_bb, stmt)->dest;
5998 gsi = gsi_last_bb (third_bb);
5999 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6001 t = build2 (MULT_EXPR, itype, q, threadid);
6002 t = build2 (PLUS_EXPR, itype, t, tt);
6003 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6005 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6006 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6008 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6009 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6011 /* Remove the GIMPLE_OMP_FOR statement. */
6012 gsi_remove (&gsi, true);
6014 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6015 gsi = gsi_start_bb (seq_start_bb);
6017 tree startvar = fd->loop.v;
6018 tree endvar = NULL_TREE;
6020 if (gimple_omp_for_combined_p (fd->for_stmt))
6022 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6023 ? gimple_omp_parallel_clauses (inner_stmt)
6024 : gimple_omp_for_clauses (inner_stmt);
6025 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6026 gcc_assert (innerc);
6027 startvar = OMP_CLAUSE_DECL (innerc);
6028 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6029 OMP_CLAUSE__LOOPTEMP_);
6030 gcc_assert (innerc);
6031 endvar = OMP_CLAUSE_DECL (innerc);
6033 t = fold_convert (itype, s0);
6034 t = fold_build2 (MULT_EXPR, itype, t, step);
6035 if (POINTER_TYPE_P (type))
6036 t = fold_build_pointer_plus (n1, t);
6037 else
6038 t = fold_build2 (PLUS_EXPR, type, t, n1);
6039 t = fold_convert (TREE_TYPE (startvar), t);
6040 t = force_gimple_operand_gsi (&gsi, t,
6041 DECL_P (startvar)
6042 && TREE_ADDRESSABLE (startvar),
6043 NULL_TREE, false, GSI_CONTINUE_LINKING);
6044 stmt = gimple_build_assign (startvar, t);
6045 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6047 t = fold_convert (itype, e0);
6048 t = fold_build2 (MULT_EXPR, itype, t, step);
6049 if (POINTER_TYPE_P (type))
6050 t = fold_build_pointer_plus (n1, t);
6051 else
6052 t = fold_build2 (PLUS_EXPR, type, t, n1);
6053 t = fold_convert (TREE_TYPE (startvar), t);
6054 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6055 false, GSI_CONTINUE_LINKING);
6056 if (endvar)
6058 stmt = gimple_build_assign (endvar, e);
6059 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6060 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6061 stmt = gimple_build_assign (fd->loop.v, e);
6062 else
6063 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6064 NULL_TREE);
6065 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6067 if (fd->collapse > 1)
6068 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6070 if (!broken_loop)
6072 /* The code controlling the sequential loop replaces the
6073 GIMPLE_OMP_CONTINUE. */
6074 gsi = gsi_last_bb (cont_bb);
6075 stmt = gsi_stmt (gsi);
6076 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6077 vmain = gimple_omp_continue_control_use (stmt);
6078 vback = gimple_omp_continue_control_def (stmt);
6080 if (!gimple_omp_for_combined_p (fd->for_stmt))
6082 if (POINTER_TYPE_P (type))
6083 t = fold_build_pointer_plus (vmain, step);
6084 else
6085 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6086 t = force_gimple_operand_gsi (&gsi, t,
6087 DECL_P (vback)
6088 && TREE_ADDRESSABLE (vback),
6089 NULL_TREE, true, GSI_SAME_STMT);
6090 stmt = gimple_build_assign (vback, t);
6091 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6093 t = build2 (fd->loop.cond_code, boolean_type_node,
6094 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6095 ? t : vback, e);
6096 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6099 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6100 gsi_remove (&gsi, true);
6102 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6103 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6106 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6107 gsi = gsi_last_bb (exit_bb);
6108 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6110 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6111 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6113 gsi_remove (&gsi, true);
6115 /* Connect all the blocks. */
6116 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6117 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6118 ep = find_edge (entry_bb, second_bb);
6119 ep->flags = EDGE_TRUE_VALUE;
6120 ep->probability = REG_BR_PROB_BASE / 4;
6121 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6122 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6124 if (!broken_loop)
6126 ep = find_edge (cont_bb, body_bb);
6127 if (gimple_omp_for_combined_p (fd->for_stmt))
6129 remove_edge (ep);
6130 ep = NULL;
6132 else if (fd->collapse > 1)
6134 remove_edge (ep);
6135 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6137 else
6138 ep->flags = EDGE_TRUE_VALUE;
6139 find_edge (cont_bb, fin_bb)->flags
6140 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6143 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6144 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6145 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6147 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6148 recompute_dominator (CDI_DOMINATORS, body_bb));
6149 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6150 recompute_dominator (CDI_DOMINATORS, fin_bb));
6152 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6154 struct loop *loop = alloc_loop ();
6155 loop->header = body_bb;
6156 if (collapse_bb == NULL)
6157 loop->latch = cont_bb;
6158 add_loop (loop, body_bb->loop_father);
6163 /* A subroutine of expand_omp_for. Generate code for a parallel
6164 loop with static schedule and a specified chunk size. Given
6165 parameters:
6167 for (V = N1; V cond N2; V += STEP) BODY;
6169 where COND is "<" or ">", we generate pseudocode
6171 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6172 if (cond is <)
6173 adj = STEP - 1;
6174 else
6175 adj = STEP + 1;
6176 if ((__typeof (V)) -1 > 0 && cond is >)
6177 n = -(adj + N2 - N1) / -STEP;
6178 else
6179 n = (adj + N2 - N1) / STEP;
6180 trip = 0;
6181 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6182 here so that V is defined
6183 if the loop is not entered
6185 s0 = (trip * nthreads + threadid) * CHUNK;
6186 e0 = min(s0 + CHUNK, n);
6187 if (s0 < n) goto L1; else goto L4;
6189 V = s0 * STEP + N1;
6190 e = e0 * STEP + N1;
6192 BODY;
6193 V += STEP;
6194 if (V cond e) goto L2; else goto L3;
6196 trip += 1;
6197 goto L0;
6201 static void
6202 expand_omp_for_static_chunk (struct omp_region *region,
6203 struct omp_for_data *fd, gimple inner_stmt)
6205 tree n, s0, e0, e, t;
6206 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6207 tree type, itype, vmain, vback, vextra;
6208 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6209 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6210 gimple_stmt_iterator gsi;
6211 gimple stmt;
6212 edge se;
6213 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6214 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6215 bool broken_loop = region->cont == NULL;
6216 tree *counts = NULL;
6217 tree n1, n2, step;
6219 itype = type = TREE_TYPE (fd->loop.v);
6220 if (POINTER_TYPE_P (type))
6221 itype = signed_type_for (type);
6223 entry_bb = region->entry;
6224 se = split_block (entry_bb, last_stmt (entry_bb));
6225 entry_bb = se->src;
6226 iter_part_bb = se->dest;
6227 cont_bb = region->cont;
6228 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6229 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6230 gcc_assert (broken_loop
6231 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6232 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6233 body_bb = single_succ (seq_start_bb);
6234 if (!broken_loop)
6236 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6237 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6238 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6240 exit_bb = region->exit;
6242 /* Trip and adjustment setup goes in ENTRY_BB. */
6243 gsi = gsi_last_bb (entry_bb);
6244 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6246 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6248 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6249 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6252 if (fd->collapse > 1)
6254 int first_zero_iter = -1;
6255 basic_block l2_dom_bb = NULL;
6257 counts = XALLOCAVEC (tree, fd->collapse);
6258 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6259 fin_bb, first_zero_iter,
6260 l2_dom_bb);
6261 t = NULL_TREE;
6263 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6264 t = integer_one_node;
6265 else
6266 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6267 fold_convert (type, fd->loop.n1),
6268 fold_convert (type, fd->loop.n2));
6269 if (fd->collapse == 1
6270 && TYPE_UNSIGNED (type)
6271 && (t == NULL_TREE || !integer_onep (t)))
6273 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6274 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6275 true, GSI_SAME_STMT);
6276 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6277 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6278 true, GSI_SAME_STMT);
6279 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6280 NULL_TREE, NULL_TREE);
6281 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6282 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6283 expand_omp_regimplify_p, NULL, NULL)
6284 || walk_tree (gimple_cond_rhs_ptr (stmt),
6285 expand_omp_regimplify_p, NULL, NULL))
6287 gsi = gsi_for_stmt (stmt);
6288 gimple_regimplify_operands (stmt, &gsi);
6290 se = split_block (entry_bb, stmt);
6291 se->flags = EDGE_TRUE_VALUE;
6292 entry_bb = se->dest;
6293 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6294 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6295 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6296 if (gimple_in_ssa_p (cfun))
6298 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6299 for (gsi = gsi_start_phis (fin_bb);
6300 !gsi_end_p (gsi); gsi_next (&gsi))
6302 gimple phi = gsi_stmt (gsi);
6303 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6304 se, UNKNOWN_LOCATION);
6307 gsi = gsi_last_bb (entry_bb);
6310 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6311 t = fold_convert (itype, t);
6312 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6313 true, GSI_SAME_STMT);
6315 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6316 t = fold_convert (itype, t);
6317 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6318 true, GSI_SAME_STMT);
6320 n1 = fd->loop.n1;
6321 n2 = fd->loop.n2;
6322 step = fd->loop.step;
6323 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6325 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6326 OMP_CLAUSE__LOOPTEMP_);
6327 gcc_assert (innerc);
6328 n1 = OMP_CLAUSE_DECL (innerc);
6329 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6330 OMP_CLAUSE__LOOPTEMP_);
6331 gcc_assert (innerc);
6332 n2 = OMP_CLAUSE_DECL (innerc);
6334 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6335 true, NULL_TREE, true, GSI_SAME_STMT);
6336 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6337 true, NULL_TREE, true, GSI_SAME_STMT);
6338 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6339 true, NULL_TREE, true, GSI_SAME_STMT);
6340 fd->chunk_size
6341 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
6342 true, NULL_TREE, true, GSI_SAME_STMT);
6344 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6345 t = fold_build2 (PLUS_EXPR, itype, step, t);
6346 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6347 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6348 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6349 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6350 fold_build1 (NEGATE_EXPR, itype, t),
6351 fold_build1 (NEGATE_EXPR, itype, step));
6352 else
6353 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6354 t = fold_convert (itype, t);
6355 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6356 true, GSI_SAME_STMT);
6358 trip_var = create_tmp_reg (itype, ".trip");
6359 if (gimple_in_ssa_p (cfun))
6361 trip_init = make_ssa_name (trip_var, NULL);
6362 trip_main = make_ssa_name (trip_var, NULL);
6363 trip_back = make_ssa_name (trip_var, NULL);
6365 else
6367 trip_init = trip_var;
6368 trip_main = trip_var;
6369 trip_back = trip_var;
6372 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6373 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6375 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6376 t = fold_build2 (MULT_EXPR, itype, t, step);
6377 if (POINTER_TYPE_P (type))
6378 t = fold_build_pointer_plus (n1, t);
6379 else
6380 t = fold_build2 (PLUS_EXPR, type, t, n1);
6381 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6382 true, GSI_SAME_STMT);
6384 /* Remove the GIMPLE_OMP_FOR. */
6385 gsi_remove (&gsi, true);
6387 /* Iteration space partitioning goes in ITER_PART_BB. */
6388 gsi = gsi_last_bb (iter_part_bb);
6390 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6391 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6392 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6393 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6394 false, GSI_CONTINUE_LINKING);
6396 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6397 t = fold_build2 (MIN_EXPR, itype, t, n);
6398 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6399 false, GSI_CONTINUE_LINKING);
6401 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6402 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6404 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6405 gsi = gsi_start_bb (seq_start_bb);
6407 tree startvar = fd->loop.v;
6408 tree endvar = NULL_TREE;
6410 if (gimple_omp_for_combined_p (fd->for_stmt))
6412 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6413 ? gimple_omp_parallel_clauses (inner_stmt)
6414 : gimple_omp_for_clauses (inner_stmt);
6415 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6416 gcc_assert (innerc);
6417 startvar = OMP_CLAUSE_DECL (innerc);
6418 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6419 OMP_CLAUSE__LOOPTEMP_);
6420 gcc_assert (innerc);
6421 endvar = OMP_CLAUSE_DECL (innerc);
6424 t = fold_convert (itype, s0);
6425 t = fold_build2 (MULT_EXPR, itype, t, step);
6426 if (POINTER_TYPE_P (type))
6427 t = fold_build_pointer_plus (n1, t);
6428 else
6429 t = fold_build2 (PLUS_EXPR, type, t, n1);
6430 t = fold_convert (TREE_TYPE (startvar), t);
6431 t = force_gimple_operand_gsi (&gsi, t,
6432 DECL_P (startvar)
6433 && TREE_ADDRESSABLE (startvar),
6434 NULL_TREE, false, GSI_CONTINUE_LINKING);
6435 stmt = gimple_build_assign (startvar, t);
6436 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6438 t = fold_convert (itype, e0);
6439 t = fold_build2 (MULT_EXPR, itype, t, step);
6440 if (POINTER_TYPE_P (type))
6441 t = fold_build_pointer_plus (n1, t);
6442 else
6443 t = fold_build2 (PLUS_EXPR, type, t, n1);
6444 t = fold_convert (TREE_TYPE (startvar), t);
6445 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6446 false, GSI_CONTINUE_LINKING);
6447 if (endvar)
6449 stmt = gimple_build_assign (endvar, e);
6450 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6451 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6452 stmt = gimple_build_assign (fd->loop.v, e);
6453 else
6454 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6455 NULL_TREE);
6456 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6458 if (fd->collapse > 1)
6459 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6461 if (!broken_loop)
6463 /* The code controlling the sequential loop goes in CONT_BB,
6464 replacing the GIMPLE_OMP_CONTINUE. */
6465 gsi = gsi_last_bb (cont_bb);
6466 stmt = gsi_stmt (gsi);
6467 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6468 vmain = gimple_omp_continue_control_use (stmt);
6469 vback = gimple_omp_continue_control_def (stmt);
6471 if (!gimple_omp_for_combined_p (fd->for_stmt))
6473 if (POINTER_TYPE_P (type))
6474 t = fold_build_pointer_plus (vmain, step);
6475 else
6476 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6477 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
6478 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6479 true, GSI_SAME_STMT);
6480 stmt = gimple_build_assign (vback, t);
6481 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6483 t = build2 (fd->loop.cond_code, boolean_type_node,
6484 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6485 ? t : vback, e);
6486 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6489 /* Remove GIMPLE_OMP_CONTINUE. */
6490 gsi_remove (&gsi, true);
6492 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6493 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6495 /* Trip update code goes into TRIP_UPDATE_BB. */
6496 gsi = gsi_start_bb (trip_update_bb);
6498 t = build_int_cst (itype, 1);
6499 t = build2 (PLUS_EXPR, itype, trip_main, t);
6500 stmt = gimple_build_assign (trip_back, t);
6501 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6504 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6505 gsi = gsi_last_bb (exit_bb);
6506 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6508 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6509 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6511 gsi_remove (&gsi, true);
6513 /* Connect the new blocks. */
6514 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6515 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6517 if (!broken_loop)
6519 se = find_edge (cont_bb, body_bb);
6520 if (gimple_omp_for_combined_p (fd->for_stmt))
6522 remove_edge (se);
6523 se = NULL;
6525 else if (fd->collapse > 1)
6527 remove_edge (se);
6528 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6530 else
6531 se->flags = EDGE_TRUE_VALUE;
6532 find_edge (cont_bb, trip_update_bb)->flags
6533 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6535 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6538 if (gimple_in_ssa_p (cfun))
6540 gimple_stmt_iterator psi;
6541 gimple phi;
6542 edge re, ene;
6543 edge_var_map_vector *head;
6544 edge_var_map *vm;
6545 size_t i;
6547 gcc_assert (fd->collapse == 1 && !broken_loop);
6549 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6550 remove arguments of the phi nodes in fin_bb. We need to create
6551 appropriate phi nodes in iter_part_bb instead. */
6552 se = single_pred_edge (fin_bb);
6553 re = single_succ_edge (trip_update_bb);
6554 head = redirect_edge_var_map_vector (re);
6555 ene = single_succ_edge (entry_bb);
6557 psi = gsi_start_phis (fin_bb);
6558 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6559 gsi_next (&psi), ++i)
6561 gimple nphi;
6562 source_location locus;
6564 phi = gsi_stmt (psi);
6565 t = gimple_phi_result (phi);
6566 gcc_assert (t == redirect_edge_var_map_result (vm));
6567 nphi = create_phi_node (t, iter_part_bb);
6569 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6570 locus = gimple_phi_arg_location_from_edge (phi, se);
6572 /* A special case -- fd->loop.v is not yet computed in
6573 iter_part_bb, we need to use vextra instead. */
6574 if (t == fd->loop.v)
6575 t = vextra;
6576 add_phi_arg (nphi, t, ene, locus);
6577 locus = redirect_edge_var_map_location (vm);
6578 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6580 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6581 redirect_edge_var_map_clear (re);
6582 while (1)
6584 psi = gsi_start_phis (fin_bb);
6585 if (gsi_end_p (psi))
6586 break;
6587 remove_phi_node (&psi, false);
6590 /* Make phi node for trip. */
6591 phi = create_phi_node (trip_main, iter_part_bb);
6592 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6593 UNKNOWN_LOCATION);
6594 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6595 UNKNOWN_LOCATION);
6598 if (!broken_loop)
6599 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6600 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6601 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6602 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6603 recompute_dominator (CDI_DOMINATORS, fin_bb));
6604 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6605 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6606 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6607 recompute_dominator (CDI_DOMINATORS, body_bb));
6609 if (!broken_loop)
6611 struct loop *trip_loop = alloc_loop ();
6612 trip_loop->header = iter_part_bb;
6613 trip_loop->latch = trip_update_bb;
6614 add_loop (trip_loop, iter_part_bb->loop_father);
6616 if (!gimple_omp_for_combined_p (fd->for_stmt))
6618 struct loop *loop = alloc_loop ();
6619 loop->header = body_bb;
6620 if (collapse_bb == NULL)
6621 loop->latch = cont_bb;
6622 add_loop (loop, trip_loop);
6628 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6629 loop. Given parameters:
6631 for (V = N1; V cond N2; V += STEP) BODY;
6633 where COND is "<" or ">", we generate pseudocode
6635 V = N1;
6636 goto L1;
6638 BODY;
6639 V += STEP;
6641 if (V cond N2) goto L0; else goto L2;
6644 For collapsed loops, given parameters:
6645 collapse(3)
6646 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6647 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6648 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6649 BODY;
6651 we generate pseudocode
6653 if (cond3 is <)
6654 adj = STEP3 - 1;
6655 else
6656 adj = STEP3 + 1;
6657 count3 = (adj + N32 - N31) / STEP3;
6658 if (cond2 is <)
6659 adj = STEP2 - 1;
6660 else
6661 adj = STEP2 + 1;
6662 count2 = (adj + N22 - N21) / STEP2;
6663 if (cond1 is <)
6664 adj = STEP1 - 1;
6665 else
6666 adj = STEP1 + 1;
6667 count1 = (adj + N12 - N11) / STEP1;
6668 count = count1 * count2 * count3;
6669 V = 0;
6670 V1 = N11;
6671 V2 = N21;
6672 V3 = N31;
6673 goto L1;
6675 BODY;
6676 V += 1;
6677 V3 += STEP3;
6678 V2 += (V3 cond3 N32) ? 0 : STEP2;
6679 V3 = (V3 cond3 N32) ? V3 : N31;
6680 V1 += (V2 cond2 N22) ? 0 : STEP1;
6681 V2 = (V2 cond2 N22) ? V2 : N21;
6683 if (V < count) goto L0; else goto L2;
6688 static void
6689 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
6691 tree type, t;
6692 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
6693 gimple_stmt_iterator gsi;
6694 gimple stmt;
6695 bool broken_loop = region->cont == NULL;
6696 edge e, ne;
6697 tree *counts = NULL;
6698 int i;
6699 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6700 OMP_CLAUSE_SAFELEN);
6701 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6702 OMP_CLAUSE__SIMDUID_);
6703 tree n1, n2;
6705 type = TREE_TYPE (fd->loop.v);
6706 entry_bb = region->entry;
6707 cont_bb = region->cont;
6708 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6709 gcc_assert (broken_loop
6710 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6711 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6712 if (!broken_loop)
6714 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6715 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6716 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6717 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6719 else
6721 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6722 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6723 l2_bb = single_succ (l1_bb);
6725 exit_bb = region->exit;
6726 l2_dom_bb = NULL;
6728 gsi = gsi_last_bb (entry_bb);
6730 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6731 /* Not needed in SSA form right now. */
6732 gcc_assert (!gimple_in_ssa_p (cfun));
6733 if (fd->collapse > 1)
6735 int first_zero_iter = -1;
6736 basic_block zero_iter_bb = l2_bb;
6738 counts = XALLOCAVEC (tree, fd->collapse);
6739 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6740 zero_iter_bb, first_zero_iter,
6741 l2_dom_bb);
6743 if (l2_dom_bb == NULL)
6744 l2_dom_bb = l1_bb;
6746 n1 = fd->loop.n1;
6747 n2 = fd->loop.n2;
6748 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6750 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6751 OMP_CLAUSE__LOOPTEMP_);
6752 gcc_assert (innerc);
6753 n1 = OMP_CLAUSE_DECL (innerc);
6754 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6755 OMP_CLAUSE__LOOPTEMP_);
6756 gcc_assert (innerc);
6757 n2 = OMP_CLAUSE_DECL (innerc);
6758 expand_omp_build_assign (&gsi, fd->loop.v,
6759 fold_convert (type, n1));
6760 if (fd->collapse > 1)
6762 gsi_prev (&gsi);
6763 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
6764 gsi_next (&gsi);
6767 else
6769 expand_omp_build_assign (&gsi, fd->loop.v,
6770 fold_convert (type, fd->loop.n1));
6771 if (fd->collapse > 1)
6772 for (i = 0; i < fd->collapse; i++)
6774 tree itype = TREE_TYPE (fd->loops[i].v);
6775 if (POINTER_TYPE_P (itype))
6776 itype = signed_type_for (itype);
6777 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
6778 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6782 /* Remove the GIMPLE_OMP_FOR statement. */
6783 gsi_remove (&gsi, true);
6785 if (!broken_loop)
6787 /* Code to control the increment goes in the CONT_BB. */
6788 gsi = gsi_last_bb (cont_bb);
6789 stmt = gsi_stmt (gsi);
6790 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6792 if (POINTER_TYPE_P (type))
6793 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
6794 else
6795 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
6796 expand_omp_build_assign (&gsi, fd->loop.v, t);
6798 if (fd->collapse > 1)
6800 i = fd->collapse - 1;
6801 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
6803 t = fold_convert (sizetype, fd->loops[i].step);
6804 t = fold_build_pointer_plus (fd->loops[i].v, t);
6806 else
6808 t = fold_convert (TREE_TYPE (fd->loops[i].v),
6809 fd->loops[i].step);
6810 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
6811 fd->loops[i].v, t);
6813 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6815 for (i = fd->collapse - 1; i > 0; i--)
6817 tree itype = TREE_TYPE (fd->loops[i].v);
6818 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
6819 if (POINTER_TYPE_P (itype2))
6820 itype2 = signed_type_for (itype2);
6821 t = build3 (COND_EXPR, itype2,
6822 build2 (fd->loops[i].cond_code, boolean_type_node,
6823 fd->loops[i].v,
6824 fold_convert (itype, fd->loops[i].n2)),
6825 build_int_cst (itype2, 0),
6826 fold_convert (itype2, fd->loops[i - 1].step));
6827 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
6828 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
6829 else
6830 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
6831 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
6833 t = build3 (COND_EXPR, itype,
6834 build2 (fd->loops[i].cond_code, boolean_type_node,
6835 fd->loops[i].v,
6836 fold_convert (itype, fd->loops[i].n2)),
6837 fd->loops[i].v,
6838 fold_convert (itype, fd->loops[i].n1));
6839 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6843 /* Remove GIMPLE_OMP_CONTINUE. */
6844 gsi_remove (&gsi, true);
6847 /* Emit the condition in L1_BB. */
6848 gsi = gsi_start_bb (l1_bb);
6850 t = fold_convert (type, n2);
6851 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6852 false, GSI_CONTINUE_LINKING);
6853 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
6854 stmt = gimple_build_cond_empty (t);
6855 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6856 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
6857 NULL, NULL)
6858 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
6859 NULL, NULL))
6861 gsi = gsi_for_stmt (stmt);
6862 gimple_regimplify_operands (stmt, &gsi);
6865 /* Remove GIMPLE_OMP_RETURN. */
6866 gsi = gsi_last_bb (exit_bb);
6867 gsi_remove (&gsi, true);
6869 /* Connect the new blocks. */
6870 remove_edge (FALLTHRU_EDGE (entry_bb));
6872 if (!broken_loop)
6874 remove_edge (BRANCH_EDGE (entry_bb));
6875 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6877 e = BRANCH_EDGE (l1_bb);
6878 ne = FALLTHRU_EDGE (l1_bb);
6879 e->flags = EDGE_TRUE_VALUE;
6881 else
6883 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6885 ne = single_succ_edge (l1_bb);
6886 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6889 ne->flags = EDGE_FALSE_VALUE;
6890 e->probability = REG_BR_PROB_BASE * 7 / 8;
6891 ne->probability = REG_BR_PROB_BASE / 8;
6893 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6894 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6895 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6897 if (!broken_loop)
6899 struct loop *loop = alloc_loop ();
6900 loop->header = l1_bb;
6901 loop->latch = cont_bb;
6902 add_loop (loop, l1_bb->loop_father);
6903 if (safelen == NULL_TREE)
6904 loop->safelen = INT_MAX;
6905 else
6907 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
6908 if (TREE_CODE (safelen) != INTEGER_CST)
6909 loop->safelen = 0;
6910 else if (!tree_fits_uhwi_p (safelen)
6911 || tree_to_uhwi (safelen) > INT_MAX)
6912 loop->safelen = INT_MAX;
6913 else
6914 loop->safelen = tree_to_uhwi (safelen);
6915 if (loop->safelen == 1)
6916 loop->safelen = 0;
6918 if (simduid)
6920 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
6921 cfun->has_simduid_loops = true;
6923 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
6924 the loop. */
6925 if ((flag_tree_loop_vectorize
6926 || (!global_options_set.x_flag_tree_loop_vectorize
6927 && !global_options_set.x_flag_tree_vectorize))
6928 && flag_tree_loop_optimize
6929 && loop->safelen > 1)
6931 loop->force_vectorize = true;
6932 cfun->has_force_vectorize_loops = true;
6938 /* Expand the OpenMP loop defined by REGION. */
6940 static void
6941 expand_omp_for (struct omp_region *region, gimple inner_stmt)
6943 struct omp_for_data fd;
6944 struct omp_for_data_loop *loops;
6946 loops
6947 = (struct omp_for_data_loop *)
6948 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
6949 * sizeof (struct omp_for_data_loop));
6950 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
6951 region->sched_kind = fd.sched_kind;
6953 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
6954 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6955 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6956 if (region->cont)
6958 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
6959 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6960 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6962 else
6963 /* If there isn't a continue then this is a degerate case where
6964 the introduction of abnormal edges during lowering will prevent
6965 original loops from being detected. Fix that up. */
6966 loops_state_set (LOOPS_NEED_FIXUP);
6968 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
6969 expand_omp_simd (region, &fd);
6970 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
6971 && !fd.have_ordered)
6973 if (fd.chunk_size == NULL)
6974 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
6975 else
6976 expand_omp_for_static_chunk (region, &fd, inner_stmt);
6978 else
6980 int fn_index, start_ix, next_ix;
6982 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
6983 == GF_OMP_FOR_KIND_FOR);
6984 if (fd.chunk_size == NULL
6985 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
6986 fd.chunk_size = integer_zero_node;
6987 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6988 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
6989 ? 3 : fd.sched_kind;
6990 fn_index += fd.have_ordered * 4;
6991 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
6992 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
6993 if (fd.iter_type == long_long_unsigned_type_node)
6995 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
6996 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
6997 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
6998 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7000 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7001 (enum built_in_function) next_ix, inner_stmt);
7004 if (gimple_in_ssa_p (cfun))
7005 update_ssa (TODO_update_ssa_only_virtuals);
7009 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7011 v = GOMP_sections_start (n);
7013 switch (v)
7015 case 0:
7016 goto L2;
7017 case 1:
7018 section 1;
7019 goto L1;
7020 case 2:
7022 case n:
7024 default:
7025 abort ();
7028 v = GOMP_sections_next ();
7029 goto L0;
7031 reduction;
7033 If this is a combined parallel sections, replace the call to
7034 GOMP_sections_start with call to GOMP_sections_next. */
7036 static void
7037 expand_omp_sections (struct omp_region *region)
7039 tree t, u, vin = NULL, vmain, vnext, l2;
7040 unsigned len;
7041 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7042 gimple_stmt_iterator si, switch_si;
7043 gimple sections_stmt, stmt, cont;
7044 edge_iterator ei;
7045 edge e;
7046 struct omp_region *inner;
7047 unsigned i, casei;
7048 bool exit_reachable = region->cont != NULL;
7050 gcc_assert (region->exit != NULL);
7051 entry_bb = region->entry;
7052 l0_bb = single_succ (entry_bb);
7053 l1_bb = region->cont;
7054 l2_bb = region->exit;
7055 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7056 l2 = gimple_block_label (l2_bb);
7057 else
7059 /* This can happen if there are reductions. */
7060 len = EDGE_COUNT (l0_bb->succs);
7061 gcc_assert (len > 0);
7062 e = EDGE_SUCC (l0_bb, len - 1);
7063 si = gsi_last_bb (e->dest);
7064 l2 = NULL_TREE;
7065 if (gsi_end_p (si)
7066 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7067 l2 = gimple_block_label (e->dest);
7068 else
7069 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7071 si = gsi_last_bb (e->dest);
7072 if (gsi_end_p (si)
7073 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7075 l2 = gimple_block_label (e->dest);
7076 break;
7080 if (exit_reachable)
7081 default_bb = create_empty_bb (l1_bb->prev_bb);
7082 else
7083 default_bb = create_empty_bb (l0_bb);
7085 /* We will build a switch() with enough cases for all the
7086 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7087 and a default case to abort if something goes wrong. */
7088 len = EDGE_COUNT (l0_bb->succs);
7090 /* Use vec::quick_push on label_vec throughout, since we know the size
7091 in advance. */
7092 auto_vec<tree> label_vec (len);
7094 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7095 GIMPLE_OMP_SECTIONS statement. */
7096 si = gsi_last_bb (entry_bb);
7097 sections_stmt = gsi_stmt (si);
7098 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7099 vin = gimple_omp_sections_control (sections_stmt);
7100 if (!is_combined_parallel (region))
7102 /* If we are not inside a combined parallel+sections region,
7103 call GOMP_sections_start. */
7104 t = build_int_cst (unsigned_type_node, len - 1);
7105 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7106 stmt = gimple_build_call (u, 1, t);
7108 else
7110 /* Otherwise, call GOMP_sections_next. */
7111 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7112 stmt = gimple_build_call (u, 0);
7114 gimple_call_set_lhs (stmt, vin);
7115 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7116 gsi_remove (&si, true);
7118 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7119 L0_BB. */
7120 switch_si = gsi_last_bb (l0_bb);
7121 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7122 if (exit_reachable)
7124 cont = last_stmt (l1_bb);
7125 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7126 vmain = gimple_omp_continue_control_use (cont);
7127 vnext = gimple_omp_continue_control_def (cont);
7129 else
7131 vmain = vin;
7132 vnext = NULL_TREE;
7135 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7136 label_vec.quick_push (t);
7137 i = 1;
7139 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7140 for (inner = region->inner, casei = 1;
7141 inner;
7142 inner = inner->next, i++, casei++)
7144 basic_block s_entry_bb, s_exit_bb;
7146 /* Skip optional reduction region. */
7147 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7149 --i;
7150 --casei;
7151 continue;
7154 s_entry_bb = inner->entry;
7155 s_exit_bb = inner->exit;
7157 t = gimple_block_label (s_entry_bb);
7158 u = build_int_cst (unsigned_type_node, casei);
7159 u = build_case_label (u, NULL, t);
7160 label_vec.quick_push (u);
7162 si = gsi_last_bb (s_entry_bb);
7163 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7164 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7165 gsi_remove (&si, true);
7166 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7168 if (s_exit_bb == NULL)
7169 continue;
7171 si = gsi_last_bb (s_exit_bb);
7172 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7173 gsi_remove (&si, true);
7175 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7178 /* Error handling code goes in DEFAULT_BB. */
7179 t = gimple_block_label (default_bb);
7180 u = build_case_label (NULL, NULL, t);
7181 make_edge (l0_bb, default_bb, 0);
7182 add_bb_to_loop (default_bb, current_loops->tree_root);
7184 stmt = gimple_build_switch (vmain, u, label_vec);
7185 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7186 gsi_remove (&switch_si, true);
7188 si = gsi_start_bb (default_bb);
7189 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7190 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7192 if (exit_reachable)
7194 tree bfn_decl;
7196 /* Code to get the next section goes in L1_BB. */
7197 si = gsi_last_bb (l1_bb);
7198 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7200 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7201 stmt = gimple_build_call (bfn_decl, 0);
7202 gimple_call_set_lhs (stmt, vnext);
7203 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7204 gsi_remove (&si, true);
7206 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7209 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7210 si = gsi_last_bb (l2_bb);
7211 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7212 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7213 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7214 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7215 else
7216 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7217 stmt = gimple_build_call (t, 0);
7218 if (gimple_omp_return_lhs (gsi_stmt (si)))
7219 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7220 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7221 gsi_remove (&si, true);
7223 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7227 /* Expand code for an OpenMP single directive. We've already expanded
7228 much of the code, here we simply place the GOMP_barrier call. */
7230 static void
7231 expand_omp_single (struct omp_region *region)
7233 basic_block entry_bb, exit_bb;
7234 gimple_stmt_iterator si;
7236 entry_bb = region->entry;
7237 exit_bb = region->exit;
7239 si = gsi_last_bb (entry_bb);
7240 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7241 gsi_remove (&si, true);
7242 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7244 si = gsi_last_bb (exit_bb);
7245 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7247 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7248 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7250 gsi_remove (&si, true);
7251 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7255 /* Generic expansion for OpenMP synchronization directives: master,
7256 ordered and critical. All we need to do here is remove the entry
7257 and exit markers for REGION. */
7259 static void
7260 expand_omp_synch (struct omp_region *region)
7262 basic_block entry_bb, exit_bb;
7263 gimple_stmt_iterator si;
7265 entry_bb = region->entry;
7266 exit_bb = region->exit;
7268 si = gsi_last_bb (entry_bb);
7269 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7270 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7271 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7272 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7273 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7274 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7275 gsi_remove (&si, true);
7276 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7278 if (exit_bb)
7280 si = gsi_last_bb (exit_bb);
7281 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7282 gsi_remove (&si, true);
7283 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7287 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7288 operation as a normal volatile load. */
7290 static bool
7291 expand_omp_atomic_load (basic_block load_bb, tree addr,
7292 tree loaded_val, int index)
7294 enum built_in_function tmpbase;
7295 gimple_stmt_iterator gsi;
7296 basic_block store_bb;
7297 location_t loc;
7298 gimple stmt;
7299 tree decl, call, type, itype;
7301 gsi = gsi_last_bb (load_bb);
7302 stmt = gsi_stmt (gsi);
7303 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7304 loc = gimple_location (stmt);
7306 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7307 is smaller than word size, then expand_atomic_load assumes that the load
7308 is atomic. We could avoid the builtin entirely in this case. */
7310 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7311 decl = builtin_decl_explicit (tmpbase);
7312 if (decl == NULL_TREE)
7313 return false;
7315 type = TREE_TYPE (loaded_val);
7316 itype = TREE_TYPE (TREE_TYPE (decl));
7318 call = build_call_expr_loc (loc, decl, 2, addr,
7319 build_int_cst (NULL,
7320 gimple_omp_atomic_seq_cst_p (stmt)
7321 ? MEMMODEL_SEQ_CST
7322 : MEMMODEL_RELAXED));
7323 if (!useless_type_conversion_p (type, itype))
7324 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7325 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7327 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7328 gsi_remove (&gsi, true);
7330 store_bb = single_succ (load_bb);
7331 gsi = gsi_last_bb (store_bb);
7332 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7333 gsi_remove (&gsi, true);
7335 if (gimple_in_ssa_p (cfun))
7336 update_ssa (TODO_update_ssa_no_phi);
7338 return true;
7341 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7342 operation as a normal volatile store. */
7344 static bool
7345 expand_omp_atomic_store (basic_block load_bb, tree addr,
7346 tree loaded_val, tree stored_val, int index)
7348 enum built_in_function tmpbase;
7349 gimple_stmt_iterator gsi;
7350 basic_block store_bb = single_succ (load_bb);
7351 location_t loc;
7352 gimple stmt;
7353 tree decl, call, type, itype;
7354 enum machine_mode imode;
7355 bool exchange;
7357 gsi = gsi_last_bb (load_bb);
7358 stmt = gsi_stmt (gsi);
7359 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7361 /* If the load value is needed, then this isn't a store but an exchange. */
7362 exchange = gimple_omp_atomic_need_value_p (stmt);
7364 gsi = gsi_last_bb (store_bb);
7365 stmt = gsi_stmt (gsi);
7366 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7367 loc = gimple_location (stmt);
7369 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7370 is smaller than word size, then expand_atomic_store assumes that the store
7371 is atomic. We could avoid the builtin entirely in this case. */
7373 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7374 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7375 decl = builtin_decl_explicit (tmpbase);
7376 if (decl == NULL_TREE)
7377 return false;
7379 type = TREE_TYPE (stored_val);
7381 /* Dig out the type of the function's second argument. */
7382 itype = TREE_TYPE (decl);
7383 itype = TYPE_ARG_TYPES (itype);
7384 itype = TREE_CHAIN (itype);
7385 itype = TREE_VALUE (itype);
7386 imode = TYPE_MODE (itype);
7388 if (exchange && !can_atomic_exchange_p (imode, true))
7389 return false;
7391 if (!useless_type_conversion_p (itype, type))
7392 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7393 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7394 build_int_cst (NULL,
7395 gimple_omp_atomic_seq_cst_p (stmt)
7396 ? MEMMODEL_SEQ_CST
7397 : MEMMODEL_RELAXED));
7398 if (exchange)
7400 if (!useless_type_conversion_p (type, itype))
7401 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7402 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7405 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7406 gsi_remove (&gsi, true);
7408 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7409 gsi = gsi_last_bb (load_bb);
7410 gsi_remove (&gsi, true);
7412 if (gimple_in_ssa_p (cfun))
7413 update_ssa (TODO_update_ssa_no_phi);
7415 return true;
7418 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7419 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7420 size of the data type, and thus usable to find the index of the builtin
7421 decl. Returns false if the expression is not of the proper form. */
7423 static bool
7424 expand_omp_atomic_fetch_op (basic_block load_bb,
7425 tree addr, tree loaded_val,
7426 tree stored_val, int index)
7428 enum built_in_function oldbase, newbase, tmpbase;
7429 tree decl, itype, call;
7430 tree lhs, rhs;
7431 basic_block store_bb = single_succ (load_bb);
7432 gimple_stmt_iterator gsi;
7433 gimple stmt;
7434 location_t loc;
7435 enum tree_code code;
7436 bool need_old, need_new;
7437 enum machine_mode imode;
7438 bool seq_cst;
7440 /* We expect to find the following sequences:
7442 load_bb:
7443 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7445 store_bb:
7446 val = tmp OP something; (or: something OP tmp)
7447 GIMPLE_OMP_STORE (val)
7449 ???FIXME: Allow a more flexible sequence.
7450 Perhaps use data flow to pick the statements.
7454 gsi = gsi_after_labels (store_bb);
7455 stmt = gsi_stmt (gsi);
7456 loc = gimple_location (stmt);
7457 if (!is_gimple_assign (stmt))
7458 return false;
7459 gsi_next (&gsi);
7460 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7461 return false;
7462 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7463 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7464 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7465 gcc_checking_assert (!need_old || !need_new);
7467 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7468 return false;
7470 /* Check for one of the supported fetch-op operations. */
7471 code = gimple_assign_rhs_code (stmt);
7472 switch (code)
7474 case PLUS_EXPR:
7475 case POINTER_PLUS_EXPR:
7476 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7477 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7478 break;
7479 case MINUS_EXPR:
7480 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7481 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7482 break;
7483 case BIT_AND_EXPR:
7484 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7485 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7486 break;
7487 case BIT_IOR_EXPR:
7488 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7489 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7490 break;
7491 case BIT_XOR_EXPR:
7492 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7493 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7494 break;
7495 default:
7496 return false;
7499 /* Make sure the expression is of the proper form. */
7500 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7501 rhs = gimple_assign_rhs2 (stmt);
7502 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7503 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7504 rhs = gimple_assign_rhs1 (stmt);
7505 else
7506 return false;
7508 tmpbase = ((enum built_in_function)
7509 ((need_new ? newbase : oldbase) + index + 1));
7510 decl = builtin_decl_explicit (tmpbase);
7511 if (decl == NULL_TREE)
7512 return false;
7513 itype = TREE_TYPE (TREE_TYPE (decl));
7514 imode = TYPE_MODE (itype);
7516 /* We could test all of the various optabs involved, but the fact of the
7517 matter is that (with the exception of i486 vs i586 and xadd) all targets
7518 that support any atomic operaton optab also implements compare-and-swap.
7519 Let optabs.c take care of expanding any compare-and-swap loop. */
7520 if (!can_compare_and_swap_p (imode, true))
7521 return false;
7523 gsi = gsi_last_bb (load_bb);
7524 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7526 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7527 It only requires that the operation happen atomically. Thus we can
7528 use the RELAXED memory model. */
7529 call = build_call_expr_loc (loc, decl, 3, addr,
7530 fold_convert_loc (loc, itype, rhs),
7531 build_int_cst (NULL,
7532 seq_cst ? MEMMODEL_SEQ_CST
7533 : MEMMODEL_RELAXED));
7535 if (need_old || need_new)
7537 lhs = need_old ? loaded_val : stored_val;
7538 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7539 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7541 else
7542 call = fold_convert_loc (loc, void_type_node, call);
7543 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7544 gsi_remove (&gsi, true);
7546 gsi = gsi_last_bb (store_bb);
7547 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7548 gsi_remove (&gsi, true);
7549 gsi = gsi_last_bb (store_bb);
7550 gsi_remove (&gsi, true);
7552 if (gimple_in_ssa_p (cfun))
7553 update_ssa (TODO_update_ssa_no_phi);
7555 return true;
7558 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7560 oldval = *addr;
7561 repeat:
7562 newval = rhs; // with oldval replacing *addr in rhs
7563 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7564 if (oldval != newval)
7565 goto repeat;
7567 INDEX is log2 of the size of the data type, and thus usable to find the
7568 index of the builtin decl. */
7570 static bool
7571 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7572 tree addr, tree loaded_val, tree stored_val,
7573 int index)
7575 tree loadedi, storedi, initial, new_storedi, old_vali;
7576 tree type, itype, cmpxchg, iaddr;
7577 gimple_stmt_iterator si;
7578 basic_block loop_header = single_succ (load_bb);
7579 gimple phi, stmt;
7580 edge e;
7581 enum built_in_function fncode;
7583 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7584 order to use the RELAXED memory model effectively. */
7585 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7586 + index + 1);
7587 cmpxchg = builtin_decl_explicit (fncode);
7588 if (cmpxchg == NULL_TREE)
7589 return false;
7590 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7591 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7593 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7594 return false;
7596 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7597 si = gsi_last_bb (load_bb);
7598 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7600 /* For floating-point values, we'll need to view-convert them to integers
7601 so that we can perform the atomic compare and swap. Simplify the
7602 following code by always setting up the "i"ntegral variables. */
7603 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7605 tree iaddr_val;
7607 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7608 true), NULL);
7609 iaddr_val
7610 = force_gimple_operand_gsi (&si,
7611 fold_convert (TREE_TYPE (iaddr), addr),
7612 false, NULL_TREE, true, GSI_SAME_STMT);
7613 stmt = gimple_build_assign (iaddr, iaddr_val);
7614 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7615 loadedi = create_tmp_var (itype, NULL);
7616 if (gimple_in_ssa_p (cfun))
7617 loadedi = make_ssa_name (loadedi, NULL);
7619 else
7621 iaddr = addr;
7622 loadedi = loaded_val;
7625 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7626 tree loaddecl = builtin_decl_explicit (fncode);
7627 if (loaddecl)
7628 initial
7629 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
7630 build_call_expr (loaddecl, 2, iaddr,
7631 build_int_cst (NULL_TREE,
7632 MEMMODEL_RELAXED)));
7633 else
7634 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
7635 build_int_cst (TREE_TYPE (iaddr), 0));
7637 initial
7638 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
7639 GSI_SAME_STMT);
7641 /* Move the value to the LOADEDI temporary. */
7642 if (gimple_in_ssa_p (cfun))
7644 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
7645 phi = create_phi_node (loadedi, loop_header);
7646 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
7647 initial);
7649 else
7650 gsi_insert_before (&si,
7651 gimple_build_assign (loadedi, initial),
7652 GSI_SAME_STMT);
7653 if (loadedi != loaded_val)
7655 gimple_stmt_iterator gsi2;
7656 tree x;
7658 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
7659 gsi2 = gsi_start_bb (loop_header);
7660 if (gimple_in_ssa_p (cfun))
7662 gimple stmt;
7663 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7664 true, GSI_SAME_STMT);
7665 stmt = gimple_build_assign (loaded_val, x);
7666 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
7668 else
7670 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
7671 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7672 true, GSI_SAME_STMT);
7675 gsi_remove (&si, true);
7677 si = gsi_last_bb (store_bb);
7678 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7680 if (iaddr == addr)
7681 storedi = stored_val;
7682 else
7683 storedi =
7684 force_gimple_operand_gsi (&si,
7685 build1 (VIEW_CONVERT_EXPR, itype,
7686 stored_val), true, NULL_TREE, true,
7687 GSI_SAME_STMT);
7689 /* Build the compare&swap statement. */
7690 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
7691 new_storedi = force_gimple_operand_gsi (&si,
7692 fold_convert (TREE_TYPE (loadedi),
7693 new_storedi),
7694 true, NULL_TREE,
7695 true, GSI_SAME_STMT);
7697 if (gimple_in_ssa_p (cfun))
7698 old_vali = loadedi;
7699 else
7701 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
7702 stmt = gimple_build_assign (old_vali, loadedi);
7703 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7705 stmt = gimple_build_assign (loadedi, new_storedi);
7706 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7709 /* Note that we always perform the comparison as an integer, even for
7710 floating point. This allows the atomic operation to properly
7711 succeed even with NaNs and -0.0. */
7712 stmt = gimple_build_cond_empty
7713 (build2 (NE_EXPR, boolean_type_node,
7714 new_storedi, old_vali));
7715 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7717 /* Update cfg. */
7718 e = single_succ_edge (store_bb);
7719 e->flags &= ~EDGE_FALLTHRU;
7720 e->flags |= EDGE_FALSE_VALUE;
7722 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
7724 /* Copy the new value to loadedi (we already did that before the condition
7725 if we are not in SSA). */
7726 if (gimple_in_ssa_p (cfun))
7728 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
7729 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
7732 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
7733 gsi_remove (&si, true);
7735 struct loop *loop = alloc_loop ();
7736 loop->header = loop_header;
7737 loop->latch = store_bb;
7738 add_loop (loop, loop_header->loop_father);
7740 if (gimple_in_ssa_p (cfun))
7741 update_ssa (TODO_update_ssa_no_phi);
7743 return true;
7746 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7748 GOMP_atomic_start ();
7749 *addr = rhs;
7750 GOMP_atomic_end ();
7752 The result is not globally atomic, but works so long as all parallel
7753 references are within #pragma omp atomic directives. According to
7754 responses received from omp@openmp.org, appears to be within spec.
7755 Which makes sense, since that's how several other compilers handle
7756 this situation as well.
7757 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
7758 expanding. STORED_VAL is the operand of the matching
7759 GIMPLE_OMP_ATOMIC_STORE.
7761 We replace
7762 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
7763 loaded_val = *addr;
7765 and replace
7766 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
7767 *addr = stored_val;
7770 static bool
7771 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
7772 tree addr, tree loaded_val, tree stored_val)
7774 gimple_stmt_iterator si;
7775 gimple stmt;
7776 tree t;
7778 si = gsi_last_bb (load_bb);
7779 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7781 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
7782 t = build_call_expr (t, 0);
7783 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7785 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
7786 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7787 gsi_remove (&si, true);
7789 si = gsi_last_bb (store_bb);
7790 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7792 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
7793 stored_val);
7794 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7796 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
7797 t = build_call_expr (t, 0);
7798 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7799 gsi_remove (&si, true);
7801 if (gimple_in_ssa_p (cfun))
7802 update_ssa (TODO_update_ssa_no_phi);
7803 return true;
7806 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
7807 using expand_omp_atomic_fetch_op. If it failed, we try to
7808 call expand_omp_atomic_pipeline, and if it fails too, the
7809 ultimate fallback is wrapping the operation in a mutex
7810 (expand_omp_atomic_mutex). REGION is the atomic region built
7811 by build_omp_regions_1(). */
7813 static void
7814 expand_omp_atomic (struct omp_region *region)
7816 basic_block load_bb = region->entry, store_bb = region->exit;
7817 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
7818 tree loaded_val = gimple_omp_atomic_load_lhs (load);
7819 tree addr = gimple_omp_atomic_load_rhs (load);
7820 tree stored_val = gimple_omp_atomic_store_val (store);
7821 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7822 HOST_WIDE_INT index;
7824 /* Make sure the type is one of the supported sizes. */
7825 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
7826 index = exact_log2 (index);
7827 if (index >= 0 && index <= 4)
7829 unsigned int align = TYPE_ALIGN_UNIT (type);
7831 /* __sync builtins require strict data alignment. */
7832 if (exact_log2 (align) >= index)
7834 /* Atomic load. */
7835 if (loaded_val == stored_val
7836 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7837 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7838 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7839 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
7840 return;
7842 /* Atomic store. */
7843 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7844 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7845 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7846 && store_bb == single_succ (load_bb)
7847 && first_stmt (store_bb) == store
7848 && expand_omp_atomic_store (load_bb, addr, loaded_val,
7849 stored_val, index))
7850 return;
7852 /* When possible, use specialized atomic update functions. */
7853 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
7854 && store_bb == single_succ (load_bb)
7855 && expand_omp_atomic_fetch_op (load_bb, addr,
7856 loaded_val, stored_val, index))
7857 return;
7859 /* If we don't have specialized __sync builtins, try and implement
7860 as a compare and swap loop. */
7861 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
7862 loaded_val, stored_val, index))
7863 return;
7867 /* The ultimate fallback is wrapping the operation in a mutex. */
7868 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
7872 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
7874 static void
7875 expand_omp_target (struct omp_region *region)
7877 basic_block entry_bb, exit_bb, new_bb;
7878 struct function *child_cfun = NULL;
7879 tree child_fn = NULL_TREE, block, t;
7880 gimple_stmt_iterator gsi;
7881 gimple entry_stmt, stmt;
7882 edge e;
7884 entry_stmt = last_stmt (region->entry);
7885 new_bb = region->entry;
7886 int kind = gimple_omp_target_kind (entry_stmt);
7887 if (kind == GF_OMP_TARGET_KIND_REGION)
7889 child_fn = gimple_omp_target_child_fn (entry_stmt);
7890 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7893 entry_bb = region->entry;
7894 exit_bb = region->exit;
7896 if (kind == GF_OMP_TARGET_KIND_REGION)
7898 unsigned srcidx, dstidx, num;
7900 /* If the target region needs data sent from the parent
7901 function, then the very first statement (except possible
7902 tree profile counter updates) of the parallel body
7903 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7904 &.OMP_DATA_O is passed as an argument to the child function,
7905 we need to replace it with the argument as seen by the child
7906 function.
7908 In most cases, this will end up being the identity assignment
7909 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7910 a function call that has been inlined, the original PARM_DECL
7911 .OMP_DATA_I may have been converted into a different local
7912 variable. In which case, we need to keep the assignment. */
7913 if (gimple_omp_target_data_arg (entry_stmt))
7915 basic_block entry_succ_bb = single_succ (entry_bb);
7916 gimple_stmt_iterator gsi;
7917 tree arg;
7918 gimple tgtcopy_stmt = NULL;
7919 tree sender
7920 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
7922 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7924 gcc_assert (!gsi_end_p (gsi));
7925 stmt = gsi_stmt (gsi);
7926 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7927 continue;
7929 if (gimple_num_ops (stmt) == 2)
7931 tree arg = gimple_assign_rhs1 (stmt);
7933 /* We're ignoring the subcode because we're
7934 effectively doing a STRIP_NOPS. */
7936 if (TREE_CODE (arg) == ADDR_EXPR
7937 && TREE_OPERAND (arg, 0) == sender)
7939 tgtcopy_stmt = stmt;
7940 break;
7945 gcc_assert (tgtcopy_stmt != NULL);
7946 arg = DECL_ARGUMENTS (child_fn);
7948 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
7949 gsi_remove (&gsi, true);
7952 /* Declare local variables needed in CHILD_CFUN. */
7953 block = DECL_INITIAL (child_fn);
7954 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7955 /* The gimplifier could record temporaries in target block
7956 rather than in containing function's local_decls chain,
7957 which would mean cgraph missed finalizing them. Do it now. */
7958 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7959 if (TREE_CODE (t) == VAR_DECL
7960 && TREE_STATIC (t)
7961 && !DECL_EXTERNAL (t))
7962 varpool_finalize_decl (t);
7963 DECL_SAVED_TREE (child_fn) = NULL;
7964 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7965 gimple_set_body (child_fn, NULL);
7966 TREE_USED (block) = 1;
7968 /* Reset DECL_CONTEXT on function arguments. */
7969 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7970 DECL_CONTEXT (t) = child_fn;
7972 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
7973 so that it can be moved to the child function. */
7974 gsi = gsi_last_bb (entry_bb);
7975 stmt = gsi_stmt (gsi);
7976 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
7977 && gimple_omp_target_kind (stmt)
7978 == GF_OMP_TARGET_KIND_REGION);
7979 gsi_remove (&gsi, true);
7980 e = split_block (entry_bb, stmt);
7981 entry_bb = e->dest;
7982 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7984 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
7985 if (exit_bb)
7987 gsi = gsi_last_bb (exit_bb);
7988 gcc_assert (!gsi_end_p (gsi)
7989 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7990 stmt = gimple_build_return (NULL);
7991 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7992 gsi_remove (&gsi, true);
7995 /* Move the target region into CHILD_CFUN. */
7997 block = gimple_block (entry_stmt);
7999 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8000 if (exit_bb)
8001 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8002 /* When the OMP expansion process cannot guarantee an up-to-date
8003 loop tree arrange for the child function to fixup loops. */
8004 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8005 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8007 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8008 num = vec_safe_length (child_cfun->local_decls);
8009 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8011 t = (*child_cfun->local_decls)[srcidx];
8012 if (DECL_CONTEXT (t) == cfun->decl)
8013 continue;
8014 if (srcidx != dstidx)
8015 (*child_cfun->local_decls)[dstidx] = t;
8016 dstidx++;
8018 if (dstidx != num)
8019 vec_safe_truncate (child_cfun->local_decls, dstidx);
8021 /* Inform the callgraph about the new function. */
8022 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8023 cgraph_add_new_function (child_fn, true);
8025 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8026 fixed in a following pass. */
8027 push_cfun (child_cfun);
8028 rebuild_cgraph_edges ();
8030 /* Some EH regions might become dead, see PR34608. If
8031 pass_cleanup_cfg isn't the first pass to happen with the
8032 new child, these dead EH edges might cause problems.
8033 Clean them up now. */
8034 if (flag_exceptions)
8036 basic_block bb;
8037 bool changed = false;
8039 FOR_EACH_BB_FN (bb, cfun)
8040 changed |= gimple_purge_dead_eh_edges (bb);
8041 if (changed)
8042 cleanup_tree_cfg ();
8044 pop_cfun ();
8047 /* Emit a library call to launch the target region, or do data
8048 transfers. */
8049 tree t1, t2, t3, t4, device, cond, c, clauses;
8050 enum built_in_function start_ix;
8051 location_t clause_loc;
8053 clauses = gimple_omp_target_clauses (entry_stmt);
8055 if (kind == GF_OMP_TARGET_KIND_REGION)
8056 start_ix = BUILT_IN_GOMP_TARGET;
8057 else if (kind == GF_OMP_TARGET_KIND_DATA)
8058 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8059 else
8060 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8062 /* By default, the value of DEVICE is -1 (let runtime library choose)
8063 and there is no conditional. */
8064 cond = NULL_TREE;
8065 device = build_int_cst (integer_type_node, -1);
8067 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8068 if (c)
8069 cond = OMP_CLAUSE_IF_EXPR (c);
8071 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8072 if (c)
8074 device = OMP_CLAUSE_DEVICE_ID (c);
8075 clause_loc = OMP_CLAUSE_LOCATION (c);
8077 else
8078 clause_loc = gimple_location (entry_stmt);
8080 /* Ensure 'device' is of the correct type. */
8081 device = fold_convert_loc (clause_loc, integer_type_node, device);
8083 /* If we found the clause 'if (cond)', build
8084 (cond ? device : -2). */
8085 if (cond)
8087 cond = gimple_boolify (cond);
8089 basic_block cond_bb, then_bb, else_bb;
8090 edge e;
8091 tree tmp_var;
8093 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8094 if (kind != GF_OMP_TARGET_KIND_REGION)
8096 gsi = gsi_last_bb (new_bb);
8097 gsi_prev (&gsi);
8098 e = split_block (new_bb, gsi_stmt (gsi));
8100 else
8101 e = split_block (new_bb, NULL);
8102 cond_bb = e->src;
8103 new_bb = e->dest;
8104 remove_edge (e);
8106 then_bb = create_empty_bb (cond_bb);
8107 else_bb = create_empty_bb (then_bb);
8108 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8109 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8111 stmt = gimple_build_cond_empty (cond);
8112 gsi = gsi_last_bb (cond_bb);
8113 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8115 gsi = gsi_start_bb (then_bb);
8116 stmt = gimple_build_assign (tmp_var, device);
8117 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8119 gsi = gsi_start_bb (else_bb);
8120 stmt = gimple_build_assign (tmp_var,
8121 build_int_cst (integer_type_node, -2));
8122 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8124 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8125 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8126 add_bb_to_loop (then_bb, cond_bb->loop_father);
8127 add_bb_to_loop (else_bb, cond_bb->loop_father);
8128 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8129 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8131 device = tmp_var;
8134 gsi = gsi_last_bb (new_bb);
8135 t = gimple_omp_target_data_arg (entry_stmt);
8136 if (t == NULL)
8138 t1 = size_zero_node;
8139 t2 = build_zero_cst (ptr_type_node);
8140 t3 = t2;
8141 t4 = t2;
8143 else
8145 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8146 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8147 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8148 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8149 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8152 gimple g;
8153 /* FIXME: This will be address of
8154 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8155 symbol, as soon as the linker plugin is able to create it for us. */
8156 tree openmp_target = build_zero_cst (ptr_type_node);
8157 if (kind == GF_OMP_TARGET_KIND_REGION)
8159 tree fnaddr = build_fold_addr_expr (child_fn);
8160 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8161 device, fnaddr, openmp_target, t1, t2, t3, t4);
8163 else
8164 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8165 device, openmp_target, t1, t2, t3, t4);
8166 gimple_set_location (g, gimple_location (entry_stmt));
8167 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8168 if (kind != GF_OMP_TARGET_KIND_REGION)
8170 g = gsi_stmt (gsi);
8171 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8172 gsi_remove (&gsi, true);
8174 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8176 gsi = gsi_last_bb (region->exit);
8177 g = gsi_stmt (gsi);
8178 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8179 gsi_remove (&gsi, true);
8184 /* Expand the parallel region tree rooted at REGION. Expansion
8185 proceeds in depth-first order. Innermost regions are expanded
8186 first. This way, parallel regions that require a new function to
8187 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8188 internal dependencies in their body. */
8190 static void
8191 expand_omp (struct omp_region *region)
8193 while (region)
8195 location_t saved_location;
8196 gimple inner_stmt = NULL;
8198 /* First, determine whether this is a combined parallel+workshare
8199 region. */
8200 if (region->type == GIMPLE_OMP_PARALLEL)
8201 determine_parallel_type (region);
8203 if (region->type == GIMPLE_OMP_FOR
8204 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8205 inner_stmt = last_stmt (region->inner->entry);
8207 if (region->inner)
8208 expand_omp (region->inner);
8210 saved_location = input_location;
8211 if (gimple_has_location (last_stmt (region->entry)))
8212 input_location = gimple_location (last_stmt (region->entry));
8214 switch (region->type)
8216 case GIMPLE_OMP_PARALLEL:
8217 case GIMPLE_OMP_TASK:
8218 expand_omp_taskreg (region);
8219 break;
8221 case GIMPLE_OMP_FOR:
8222 expand_omp_for (region, inner_stmt);
8223 break;
8225 case GIMPLE_OMP_SECTIONS:
8226 expand_omp_sections (region);
8227 break;
8229 case GIMPLE_OMP_SECTION:
8230 /* Individual omp sections are handled together with their
8231 parent GIMPLE_OMP_SECTIONS region. */
8232 break;
8234 case GIMPLE_OMP_SINGLE:
8235 expand_omp_single (region);
8236 break;
8238 case GIMPLE_OMP_MASTER:
8239 case GIMPLE_OMP_TASKGROUP:
8240 case GIMPLE_OMP_ORDERED:
8241 case GIMPLE_OMP_CRITICAL:
8242 case GIMPLE_OMP_TEAMS:
8243 expand_omp_synch (region);
8244 break;
8246 case GIMPLE_OMP_ATOMIC_LOAD:
8247 expand_omp_atomic (region);
8248 break;
8250 case GIMPLE_OMP_TARGET:
8251 expand_omp_target (region);
8252 break;
8254 default:
8255 gcc_unreachable ();
8258 input_location = saved_location;
8259 region = region->next;
8264 /* Helper for build_omp_regions. Scan the dominator tree starting at
8265 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8266 true, the function ends once a single tree is built (otherwise, whole
8267 forest of OMP constructs may be built). */
8269 static void
8270 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8271 bool single_tree)
8273 gimple_stmt_iterator gsi;
8274 gimple stmt;
8275 basic_block son;
8277 gsi = gsi_last_bb (bb);
8278 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8280 struct omp_region *region;
8281 enum gimple_code code;
8283 stmt = gsi_stmt (gsi);
8284 code = gimple_code (stmt);
8285 if (code == GIMPLE_OMP_RETURN)
8287 /* STMT is the return point out of region PARENT. Mark it
8288 as the exit point and make PARENT the immediately
8289 enclosing region. */
8290 gcc_assert (parent);
8291 region = parent;
8292 region->exit = bb;
8293 parent = parent->outer;
8295 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8297 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8298 GIMPLE_OMP_RETURN, but matches with
8299 GIMPLE_OMP_ATOMIC_LOAD. */
8300 gcc_assert (parent);
8301 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8302 region = parent;
8303 region->exit = bb;
8304 parent = parent->outer;
8307 else if (code == GIMPLE_OMP_CONTINUE)
8309 gcc_assert (parent);
8310 parent->cont = bb;
8312 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8314 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8315 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8318 else if (code == GIMPLE_OMP_TARGET
8319 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8320 new_omp_region (bb, code, parent);
8321 else
8323 /* Otherwise, this directive becomes the parent for a new
8324 region. */
8325 region = new_omp_region (bb, code, parent);
8326 parent = region;
8330 if (single_tree && !parent)
8331 return;
8333 for (son = first_dom_son (CDI_DOMINATORS, bb);
8334 son;
8335 son = next_dom_son (CDI_DOMINATORS, son))
8336 build_omp_regions_1 (son, parent, single_tree);
8339 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8340 root_omp_region. */
8342 static void
8343 build_omp_regions_root (basic_block root)
8345 gcc_assert (root_omp_region == NULL);
8346 build_omp_regions_1 (root, NULL, true);
8347 gcc_assert (root_omp_region != NULL);
8350 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8352 void
8353 omp_expand_local (basic_block head)
8355 build_omp_regions_root (head);
8356 if (dump_file && (dump_flags & TDF_DETAILS))
8358 fprintf (dump_file, "\nOMP region tree\n\n");
8359 dump_omp_region (dump_file, root_omp_region, 0);
8360 fprintf (dump_file, "\n");
8363 remove_exit_barriers (root_omp_region);
8364 expand_omp (root_omp_region);
8366 free_omp_regions ();
8369 /* Scan the CFG and build a tree of OMP regions. Return the root of
8370 the OMP region tree. */
8372 static void
8373 build_omp_regions (void)
8375 gcc_assert (root_omp_region == NULL);
8376 calculate_dominance_info (CDI_DOMINATORS);
8377 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8380 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8382 static unsigned int
8383 execute_expand_omp (void)
8385 build_omp_regions ();
8387 if (!root_omp_region)
8388 return 0;
8390 if (dump_file)
8392 fprintf (dump_file, "\nOMP region tree\n\n");
8393 dump_omp_region (dump_file, root_omp_region, 0);
8394 fprintf (dump_file, "\n");
8397 remove_exit_barriers (root_omp_region);
8399 expand_omp (root_omp_region);
8401 cleanup_tree_cfg ();
8403 free_omp_regions ();
8405 return 0;
8408 /* OMP expansion -- the default pass, run before creation of SSA form. */
8410 namespace {
8412 const pass_data pass_data_expand_omp =
8414 GIMPLE_PASS, /* type */
8415 "ompexp", /* name */
8416 OPTGROUP_NONE, /* optinfo_flags */
8417 TV_NONE, /* tv_id */
8418 PROP_gimple_any, /* properties_required */
8419 0, /* properties_provided */
8420 0, /* properties_destroyed */
8421 0, /* todo_flags_start */
8422 0, /* todo_flags_finish */
8425 class pass_expand_omp : public gimple_opt_pass
8427 public:
8428 pass_expand_omp (gcc::context *ctxt)
8429 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8432 /* opt_pass methods: */
8433 virtual bool gate (function *)
8435 return ((flag_openmp != 0 || flag_openmp_simd != 0
8436 || flag_cilkplus != 0) && !seen_error ());
8439 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8441 }; // class pass_expand_omp
8443 } // anon namespace
8445 gimple_opt_pass *
8446 make_pass_expand_omp (gcc::context *ctxt)
8448 return new pass_expand_omp (ctxt);
8451 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8453 /* If ctx is a worksharing context inside of a cancellable parallel
8454 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8455 and conditional branch to parallel's cancel_label to handle
8456 cancellation in the implicit barrier. */
8458 static void
8459 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8461 gimple omp_return = gimple_seq_last_stmt (*body);
8462 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8463 if (gimple_omp_return_nowait_p (omp_return))
8464 return;
8465 if (ctx->outer
8466 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8467 && ctx->outer->cancellable)
8469 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8470 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8471 tree lhs = create_tmp_var (c_bool_type, NULL);
8472 gimple_omp_return_set_lhs (omp_return, lhs);
8473 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8474 gimple g = gimple_build_cond (NE_EXPR, lhs,
8475 fold_convert (c_bool_type,
8476 boolean_false_node),
8477 ctx->outer->cancel_label, fallthru_label);
8478 gimple_seq_add_stmt (body, g);
8479 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8483 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8484 CTX is the enclosing OMP context for the current statement. */
8486 static void
8487 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8489 tree block, control;
8490 gimple_stmt_iterator tgsi;
8491 gimple stmt, new_stmt, bind, t;
8492 gimple_seq ilist, dlist, olist, new_body;
8494 stmt = gsi_stmt (*gsi_p);
8496 push_gimplify_context ();
8498 dlist = NULL;
8499 ilist = NULL;
8500 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8501 &ilist, &dlist, ctx, NULL);
8503 new_body = gimple_omp_body (stmt);
8504 gimple_omp_set_body (stmt, NULL);
8505 tgsi = gsi_start (new_body);
8506 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8508 omp_context *sctx;
8509 gimple sec_start;
8511 sec_start = gsi_stmt (tgsi);
8512 sctx = maybe_lookup_ctx (sec_start);
8513 gcc_assert (sctx);
8515 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8516 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8517 GSI_CONTINUE_LINKING);
8518 gimple_omp_set_body (sec_start, NULL);
8520 if (gsi_one_before_end_p (tgsi))
8522 gimple_seq l = NULL;
8523 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8524 &l, ctx);
8525 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8526 gimple_omp_section_set_last (sec_start);
8529 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8530 GSI_CONTINUE_LINKING);
8533 block = make_node (BLOCK);
8534 bind = gimple_build_bind (NULL, new_body, block);
8536 olist = NULL;
8537 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8539 block = make_node (BLOCK);
8540 new_stmt = gimple_build_bind (NULL, NULL, block);
8541 gsi_replace (gsi_p, new_stmt, true);
8543 pop_gimplify_context (new_stmt);
8544 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8545 BLOCK_VARS (block) = gimple_bind_vars (bind);
8546 if (BLOCK_VARS (block))
8547 TREE_USED (block) = 1;
8549 new_body = NULL;
8550 gimple_seq_add_seq (&new_body, ilist);
8551 gimple_seq_add_stmt (&new_body, stmt);
8552 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8553 gimple_seq_add_stmt (&new_body, bind);
8555 control = create_tmp_var (unsigned_type_node, ".section");
8556 t = gimple_build_omp_continue (control, control);
8557 gimple_omp_sections_set_control (stmt, control);
8558 gimple_seq_add_stmt (&new_body, t);
8560 gimple_seq_add_seq (&new_body, olist);
8561 if (ctx->cancellable)
8562 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8563 gimple_seq_add_seq (&new_body, dlist);
8565 new_body = maybe_catch_exception (new_body);
8567 t = gimple_build_omp_return
8568 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8569 OMP_CLAUSE_NOWAIT));
8570 gimple_seq_add_stmt (&new_body, t);
8571 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8573 gimple_bind_set_body (new_stmt, new_body);
8577 /* A subroutine of lower_omp_single. Expand the simple form of
8578 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8580 if (GOMP_single_start ())
8581 BODY;
8582 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8584 FIXME. It may be better to delay expanding the logic of this until
8585 pass_expand_omp. The expanded logic may make the job more difficult
8586 to a synchronization analysis pass. */
8588 static void
8589 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8591 location_t loc = gimple_location (single_stmt);
8592 tree tlabel = create_artificial_label (loc);
8593 tree flabel = create_artificial_label (loc);
8594 gimple call, cond;
8595 tree lhs, decl;
8597 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8598 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8599 call = gimple_build_call (decl, 0);
8600 gimple_call_set_lhs (call, lhs);
8601 gimple_seq_add_stmt (pre_p, call);
8603 cond = gimple_build_cond (EQ_EXPR, lhs,
8604 fold_convert_loc (loc, TREE_TYPE (lhs),
8605 boolean_true_node),
8606 tlabel, flabel);
8607 gimple_seq_add_stmt (pre_p, cond);
8608 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8609 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8610 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8614 /* A subroutine of lower_omp_single. Expand the simple form of
8615 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8617 #pragma omp single copyprivate (a, b, c)
8619 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8622 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8624 BODY;
8625 copyout.a = a;
8626 copyout.b = b;
8627 copyout.c = c;
8628 GOMP_single_copy_end (&copyout);
8630 else
8632 a = copyout_p->a;
8633 b = copyout_p->b;
8634 c = copyout_p->c;
8636 GOMP_barrier ();
8639 FIXME. It may be better to delay expanding the logic of this until
8640 pass_expand_omp. The expanded logic may make the job more difficult
8641 to a synchronization analysis pass. */
8643 static void
8644 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
8646 tree ptr_type, t, l0, l1, l2, bfn_decl;
8647 gimple_seq copyin_seq;
8648 location_t loc = gimple_location (single_stmt);
8650 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8652 ptr_type = build_pointer_type (ctx->record_type);
8653 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8655 l0 = create_artificial_label (loc);
8656 l1 = create_artificial_label (loc);
8657 l2 = create_artificial_label (loc);
8659 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8660 t = build_call_expr_loc (loc, bfn_decl, 0);
8661 t = fold_convert_loc (loc, ptr_type, t);
8662 gimplify_assign (ctx->receiver_decl, t, pre_p);
8664 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8665 build_int_cst (ptr_type, 0));
8666 t = build3 (COND_EXPR, void_type_node, t,
8667 build_and_jump (&l0), build_and_jump (&l1));
8668 gimplify_and_add (t, pre_p);
8670 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8672 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8674 copyin_seq = NULL;
8675 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8676 &copyin_seq, ctx);
8678 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8679 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8680 t = build_call_expr_loc (loc, bfn_decl, 1, t);
8681 gimplify_and_add (t, pre_p);
8683 t = build_and_jump (&l2);
8684 gimplify_and_add (t, pre_p);
8686 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8688 gimple_seq_add_seq (pre_p, copyin_seq);
8690 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8694 /* Expand code for an OpenMP single directive. */
8696 static void
8697 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8699 tree block;
8700 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
8701 gimple_seq bind_body, bind_body_tail = NULL, dlist;
8703 push_gimplify_context ();
8705 block = make_node (BLOCK);
8706 bind = gimple_build_bind (NULL, NULL, block);
8707 gsi_replace (gsi_p, bind, true);
8708 bind_body = NULL;
8709 dlist = NULL;
8710 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8711 &bind_body, &dlist, ctx, NULL);
8712 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8714 gimple_seq_add_stmt (&bind_body, single_stmt);
8716 if (ctx->record_type)
8717 lower_omp_single_copy (single_stmt, &bind_body, ctx);
8718 else
8719 lower_omp_single_simple (single_stmt, &bind_body);
8721 gimple_omp_set_body (single_stmt, NULL);
8723 gimple_seq_add_seq (&bind_body, dlist);
8725 bind_body = maybe_catch_exception (bind_body);
8727 t = gimple_build_omp_return
8728 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
8729 OMP_CLAUSE_NOWAIT));
8730 gimple_seq_add_stmt (&bind_body_tail, t);
8731 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
8732 if (ctx->record_type)
8734 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8735 tree clobber = build_constructor (ctx->record_type, NULL);
8736 TREE_THIS_VOLATILE (clobber) = 1;
8737 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8738 clobber), GSI_SAME_STMT);
8740 gimple_seq_add_seq (&bind_body, bind_body_tail);
8741 gimple_bind_set_body (bind, bind_body);
8743 pop_gimplify_context (bind);
8745 gimple_bind_append_vars (bind, ctx->block_vars);
8746 BLOCK_VARS (block) = ctx->block_vars;
8747 if (BLOCK_VARS (block))
8748 TREE_USED (block) = 1;
8752 /* Expand code for an OpenMP master directive. */
8754 static void
8755 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8757 tree block, lab = NULL, x, bfn_decl;
8758 gimple stmt = gsi_stmt (*gsi_p), bind;
8759 location_t loc = gimple_location (stmt);
8760 gimple_seq tseq;
8762 push_gimplify_context ();
8764 block = make_node (BLOCK);
8765 bind = gimple_build_bind (NULL, NULL, block);
8766 gsi_replace (gsi_p, bind, true);
8767 gimple_bind_add_stmt (bind, stmt);
8769 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8770 x = build_call_expr_loc (loc, bfn_decl, 0);
8771 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
8772 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
8773 tseq = NULL;
8774 gimplify_and_add (x, &tseq);
8775 gimple_bind_add_seq (bind, tseq);
8777 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8778 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8779 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8780 gimple_omp_set_body (stmt, NULL);
8782 gimple_bind_add_stmt (bind, gimple_build_label (lab));
8784 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8786 pop_gimplify_context (bind);
8788 gimple_bind_append_vars (bind, ctx->block_vars);
8789 BLOCK_VARS (block) = ctx->block_vars;
8793 /* Expand code for an OpenMP taskgroup directive. */
8795 static void
8796 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8798 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8799 tree block = make_node (BLOCK);
8801 bind = gimple_build_bind (NULL, NULL, block);
8802 gsi_replace (gsi_p, bind, true);
8803 gimple_bind_add_stmt (bind, stmt);
8805 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
8807 gimple_bind_add_stmt (bind, x);
8809 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8810 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8811 gimple_omp_set_body (stmt, NULL);
8813 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8815 gimple_bind_append_vars (bind, ctx->block_vars);
8816 BLOCK_VARS (block) = ctx->block_vars;
8820 /* Expand code for an OpenMP ordered directive. */
8822 static void
8823 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8825 tree block;
8826 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8828 push_gimplify_context ();
8830 block = make_node (BLOCK);
8831 bind = gimple_build_bind (NULL, NULL, block);
8832 gsi_replace (gsi_p, bind, true);
8833 gimple_bind_add_stmt (bind, stmt);
8835 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
8837 gimple_bind_add_stmt (bind, x);
8839 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8840 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8841 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8842 gimple_omp_set_body (stmt, NULL);
8844 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
8845 gimple_bind_add_stmt (bind, x);
8847 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8849 pop_gimplify_context (bind);
8851 gimple_bind_append_vars (bind, ctx->block_vars);
8852 BLOCK_VARS (block) = gimple_bind_vars (bind);
8856 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
8857 substitution of a couple of function calls. But in the NAMED case,
8858 requires that languages coordinate a symbol name. It is therefore
8859 best put here in common code. */
8861 static GTY((param1_is (tree), param2_is (tree)))
8862 splay_tree critical_name_mutexes;
8864 static void
8865 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8867 tree block;
8868 tree name, lock, unlock;
8869 gimple stmt = gsi_stmt (*gsi_p), bind;
8870 location_t loc = gimple_location (stmt);
8871 gimple_seq tbody;
8873 name = gimple_omp_critical_name (stmt);
8874 if (name)
8876 tree decl;
8877 splay_tree_node n;
8879 if (!critical_name_mutexes)
8880 critical_name_mutexes
8881 = splay_tree_new_ggc (splay_tree_compare_pointers,
8882 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
8883 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
8885 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
8886 if (n == NULL)
8888 char *new_str;
8890 decl = create_tmp_var_raw (ptr_type_node, NULL);
8892 new_str = ACONCAT ((".gomp_critical_user_",
8893 IDENTIFIER_POINTER (name), NULL));
8894 DECL_NAME (decl) = get_identifier (new_str);
8895 TREE_PUBLIC (decl) = 1;
8896 TREE_STATIC (decl) = 1;
8897 DECL_COMMON (decl) = 1;
8898 DECL_ARTIFICIAL (decl) = 1;
8899 DECL_IGNORED_P (decl) = 1;
8900 varpool_finalize_decl (decl);
8902 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
8903 (splay_tree_value) decl);
8905 else
8906 decl = (tree) n->value;
8908 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
8909 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
8911 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
8912 unlock = build_call_expr_loc (loc, unlock, 1,
8913 build_fold_addr_expr_loc (loc, decl));
8915 else
8917 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
8918 lock = build_call_expr_loc (loc, lock, 0);
8920 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
8921 unlock = build_call_expr_loc (loc, unlock, 0);
8924 push_gimplify_context ();
8926 block = make_node (BLOCK);
8927 bind = gimple_build_bind (NULL, NULL, block);
8928 gsi_replace (gsi_p, bind, true);
8929 gimple_bind_add_stmt (bind, stmt);
8931 tbody = gimple_bind_body (bind);
8932 gimplify_and_add (lock, &tbody);
8933 gimple_bind_set_body (bind, tbody);
8935 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8936 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8937 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8938 gimple_omp_set_body (stmt, NULL);
8940 tbody = gimple_bind_body (bind);
8941 gimplify_and_add (unlock, &tbody);
8942 gimple_bind_set_body (bind, tbody);
8944 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8946 pop_gimplify_context (bind);
8947 gimple_bind_append_vars (bind, ctx->block_vars);
8948 BLOCK_VARS (block) = gimple_bind_vars (bind);
8952 /* A subroutine of lower_omp_for. Generate code to emit the predicate
8953 for a lastprivate clause. Given a loop control predicate of (V
8954 cond N2), we gate the clause on (!(V cond N2)). The lowered form
8955 is appended to *DLIST, iterator initialization is appended to
8956 *BODY_P. */
8958 static void
8959 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
8960 gimple_seq *dlist, struct omp_context *ctx)
8962 tree clauses, cond, vinit;
8963 enum tree_code cond_code;
8964 gimple_seq stmts;
8966 cond_code = fd->loop.cond_code;
8967 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
8969 /* When possible, use a strict equality expression. This can let VRP
8970 type optimizations deduce the value and remove a copy. */
8971 if (tree_fits_shwi_p (fd->loop.step))
8973 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
8974 if (step == 1 || step == -1)
8975 cond_code = EQ_EXPR;
8978 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
8980 clauses = gimple_omp_for_clauses (fd->for_stmt);
8981 stmts = NULL;
8982 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
8983 if (!gimple_seq_empty_p (stmts))
8985 gimple_seq_add_seq (&stmts, *dlist);
8986 *dlist = stmts;
8988 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
8989 vinit = fd->loop.n1;
8990 if (cond_code == EQ_EXPR
8991 && tree_fits_shwi_p (fd->loop.n2)
8992 && ! integer_zerop (fd->loop.n2))
8993 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
8994 else
8995 vinit = unshare_expr (vinit);
8997 /* Initialize the iterator variable, so that threads that don't execute
8998 any iterations don't execute the lastprivate clauses by accident. */
8999 gimplify_assign (fd->loop.v, vinit, body_p);
9004 /* Lower code for an OpenMP loop directive. */
9006 static void
9007 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9009 tree *rhs_p, block;
9010 struct omp_for_data fd, *fdp = NULL;
9011 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
9012 gimple_seq omp_for_body, body, dlist;
9013 size_t i;
9015 push_gimplify_context ();
9017 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
9019 block = make_node (BLOCK);
9020 new_stmt = gimple_build_bind (NULL, NULL, block);
9021 /* Replace at gsi right away, so that 'stmt' is no member
9022 of a sequence anymore as we're going to add to to a different
9023 one below. */
9024 gsi_replace (gsi_p, new_stmt, true);
9026 /* Move declaration of temporaries in the loop body before we make
9027 it go away. */
9028 omp_for_body = gimple_omp_body (stmt);
9029 if (!gimple_seq_empty_p (omp_for_body)
9030 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9032 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
9033 tree vars = gimple_bind_vars (inner_bind);
9034 gimple_bind_append_vars (new_stmt, vars);
9035 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9036 keep them on the inner_bind and it's block. */
9037 gimple_bind_set_vars (inner_bind, NULL_TREE);
9038 if (gimple_bind_block (inner_bind))
9039 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9042 if (gimple_omp_for_combined_into_p (stmt))
9044 extract_omp_for_data (stmt, &fd, NULL);
9045 fdp = &fd;
9047 /* We need two temporaries with fd.loop.v type (istart/iend)
9048 and then (fd.collapse - 1) temporaries with the same
9049 type for count2 ... countN-1 vars if not constant. */
9050 size_t count = 2;
9051 tree type = fd.iter_type;
9052 if (fd.collapse > 1
9053 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9054 count += fd.collapse - 1;
9055 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9056 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9057 tree clauses = *pc;
9058 if (parallel_for)
9059 outerc
9060 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9061 OMP_CLAUSE__LOOPTEMP_);
9062 for (i = 0; i < count; i++)
9064 tree temp;
9065 if (parallel_for)
9067 gcc_assert (outerc);
9068 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9069 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9070 OMP_CLAUSE__LOOPTEMP_);
9072 else
9074 temp = create_tmp_var (type, NULL);
9075 insert_decl_map (&ctx->outer->cb, temp, temp);
9077 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9078 OMP_CLAUSE_DECL (*pc) = temp;
9079 pc = &OMP_CLAUSE_CHAIN (*pc);
9081 *pc = clauses;
9084 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9085 dlist = NULL;
9086 body = NULL;
9087 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9088 fdp);
9089 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9091 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9093 /* Lower the header expressions. At this point, we can assume that
9094 the header is of the form:
9096 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9098 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9099 using the .omp_data_s mapping, if needed. */
9100 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9102 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9103 if (!is_gimple_min_invariant (*rhs_p))
9104 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9106 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9107 if (!is_gimple_min_invariant (*rhs_p))
9108 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9110 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9111 if (!is_gimple_min_invariant (*rhs_p))
9112 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9115 /* Once lowered, extract the bounds and clauses. */
9116 extract_omp_for_data (stmt, &fd, NULL);
9118 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9120 gimple_seq_add_stmt (&body, stmt);
9121 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9123 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9124 fd.loop.v));
9126 /* After the loop, add exit clauses. */
9127 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9129 if (ctx->cancellable)
9130 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9132 gimple_seq_add_seq (&body, dlist);
9134 body = maybe_catch_exception (body);
9136 /* Region exit marker goes at the end of the loop body. */
9137 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9138 maybe_add_implicit_barrier_cancel (ctx, &body);
9139 pop_gimplify_context (new_stmt);
9141 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9142 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9143 if (BLOCK_VARS (block))
9144 TREE_USED (block) = 1;
9146 gimple_bind_set_body (new_stmt, body);
9147 gimple_omp_set_body (stmt, NULL);
9148 gimple_omp_for_set_pre_body (stmt, NULL);
9151 /* Callback for walk_stmts. Check if the current statement only contains
9152 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9154 static tree
9155 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9156 bool *handled_ops_p,
9157 struct walk_stmt_info *wi)
9159 int *info = (int *) wi->info;
9160 gimple stmt = gsi_stmt (*gsi_p);
9162 *handled_ops_p = true;
9163 switch (gimple_code (stmt))
9165 WALK_SUBSTMTS;
9167 case GIMPLE_OMP_FOR:
9168 case GIMPLE_OMP_SECTIONS:
9169 *info = *info == 0 ? 1 : -1;
9170 break;
9171 default:
9172 *info = -1;
9173 break;
9175 return NULL;
9178 struct omp_taskcopy_context
9180 /* This field must be at the beginning, as we do "inheritance": Some
9181 callback functions for tree-inline.c (e.g., omp_copy_decl)
9182 receive a copy_body_data pointer that is up-casted to an
9183 omp_context pointer. */
9184 copy_body_data cb;
9185 omp_context *ctx;
9188 static tree
9189 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9191 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9193 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9194 return create_tmp_var (TREE_TYPE (var), NULL);
9196 return var;
9199 static tree
9200 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9202 tree name, new_fields = NULL, type, f;
9204 type = lang_hooks.types.make_type (RECORD_TYPE);
9205 name = DECL_NAME (TYPE_NAME (orig_type));
9206 name = build_decl (gimple_location (tcctx->ctx->stmt),
9207 TYPE_DECL, name, type);
9208 TYPE_NAME (type) = name;
9210 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9212 tree new_f = copy_node (f);
9213 DECL_CONTEXT (new_f) = type;
9214 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9215 TREE_CHAIN (new_f) = new_fields;
9216 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9217 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9218 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9219 &tcctx->cb, NULL);
9220 new_fields = new_f;
9221 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
9223 TYPE_FIELDS (type) = nreverse (new_fields);
9224 layout_type (type);
9225 return type;
9228 /* Create task copyfn. */
9230 static void
9231 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9233 struct function *child_cfun;
9234 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9235 tree record_type, srecord_type, bind, list;
9236 bool record_needs_remap = false, srecord_needs_remap = false;
9237 splay_tree_node n;
9238 struct omp_taskcopy_context tcctx;
9239 location_t loc = gimple_location (task_stmt);
9241 child_fn = gimple_omp_task_copy_fn (task_stmt);
9242 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9243 gcc_assert (child_cfun->cfg == NULL);
9244 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9246 /* Reset DECL_CONTEXT on function arguments. */
9247 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9248 DECL_CONTEXT (t) = child_fn;
9250 /* Populate the function. */
9251 push_gimplify_context ();
9252 push_cfun (child_cfun);
9254 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9255 TREE_SIDE_EFFECTS (bind) = 1;
9256 list = NULL;
9257 DECL_SAVED_TREE (child_fn) = bind;
9258 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9260 /* Remap src and dst argument types if needed. */
9261 record_type = ctx->record_type;
9262 srecord_type = ctx->srecord_type;
9263 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9264 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9266 record_needs_remap = true;
9267 break;
9269 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9270 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9272 srecord_needs_remap = true;
9273 break;
9276 if (record_needs_remap || srecord_needs_remap)
9278 memset (&tcctx, '\0', sizeof (tcctx));
9279 tcctx.cb.src_fn = ctx->cb.src_fn;
9280 tcctx.cb.dst_fn = child_fn;
9281 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
9282 gcc_checking_assert (tcctx.cb.src_node);
9283 tcctx.cb.dst_node = tcctx.cb.src_node;
9284 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9285 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9286 tcctx.cb.eh_lp_nr = 0;
9287 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9288 tcctx.cb.decl_map = pointer_map_create ();
9289 tcctx.ctx = ctx;
9291 if (record_needs_remap)
9292 record_type = task_copyfn_remap_type (&tcctx, record_type);
9293 if (srecord_needs_remap)
9294 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9296 else
9297 tcctx.cb.decl_map = NULL;
9299 arg = DECL_ARGUMENTS (child_fn);
9300 TREE_TYPE (arg) = build_pointer_type (record_type);
9301 sarg = DECL_CHAIN (arg);
9302 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9304 /* First pass: initialize temporaries used in record_type and srecord_type
9305 sizes and field offsets. */
9306 if (tcctx.cb.decl_map)
9307 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9308 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9310 tree *p;
9312 decl = OMP_CLAUSE_DECL (c);
9313 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
9314 if (p == NULL)
9315 continue;
9316 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9317 sf = (tree) n->value;
9318 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9319 src = build_simple_mem_ref_loc (loc, sarg);
9320 src = omp_build_component_ref (src, sf);
9321 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9322 append_to_statement_list (t, &list);
9325 /* Second pass: copy shared var pointers and copy construct non-VLA
9326 firstprivate vars. */
9327 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9328 switch (OMP_CLAUSE_CODE (c))
9330 case OMP_CLAUSE_SHARED:
9331 decl = OMP_CLAUSE_DECL (c);
9332 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9333 if (n == NULL)
9334 break;
9335 f = (tree) n->value;
9336 if (tcctx.cb.decl_map)
9337 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9338 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9339 sf = (tree) n->value;
9340 if (tcctx.cb.decl_map)
9341 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9342 src = build_simple_mem_ref_loc (loc, sarg);
9343 src = omp_build_component_ref (src, sf);
9344 dst = build_simple_mem_ref_loc (loc, arg);
9345 dst = omp_build_component_ref (dst, f);
9346 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9347 append_to_statement_list (t, &list);
9348 break;
9349 case OMP_CLAUSE_FIRSTPRIVATE:
9350 decl = OMP_CLAUSE_DECL (c);
9351 if (is_variable_sized (decl))
9352 break;
9353 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9354 if (n == NULL)
9355 break;
9356 f = (tree) n->value;
9357 if (tcctx.cb.decl_map)
9358 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9359 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9360 if (n != NULL)
9362 sf = (tree) n->value;
9363 if (tcctx.cb.decl_map)
9364 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9365 src = build_simple_mem_ref_loc (loc, sarg);
9366 src = omp_build_component_ref (src, sf);
9367 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9368 src = build_simple_mem_ref_loc (loc, src);
9370 else
9371 src = decl;
9372 dst = build_simple_mem_ref_loc (loc, arg);
9373 dst = omp_build_component_ref (dst, f);
9374 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9375 append_to_statement_list (t, &list);
9376 break;
9377 case OMP_CLAUSE_PRIVATE:
9378 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9379 break;
9380 decl = OMP_CLAUSE_DECL (c);
9381 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9382 f = (tree) n->value;
9383 if (tcctx.cb.decl_map)
9384 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9385 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9386 if (n != NULL)
9388 sf = (tree) n->value;
9389 if (tcctx.cb.decl_map)
9390 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9391 src = build_simple_mem_ref_loc (loc, sarg);
9392 src = omp_build_component_ref (src, sf);
9393 if (use_pointer_for_field (decl, NULL))
9394 src = build_simple_mem_ref_loc (loc, src);
9396 else
9397 src = decl;
9398 dst = build_simple_mem_ref_loc (loc, arg);
9399 dst = omp_build_component_ref (dst, f);
9400 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9401 append_to_statement_list (t, &list);
9402 break;
9403 default:
9404 break;
9407 /* Last pass: handle VLA firstprivates. */
9408 if (tcctx.cb.decl_map)
9409 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9410 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9412 tree ind, ptr, df;
9414 decl = OMP_CLAUSE_DECL (c);
9415 if (!is_variable_sized (decl))
9416 continue;
9417 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9418 if (n == NULL)
9419 continue;
9420 f = (tree) n->value;
9421 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9422 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9423 ind = DECL_VALUE_EXPR (decl);
9424 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9425 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9426 n = splay_tree_lookup (ctx->sfield_map,
9427 (splay_tree_key) TREE_OPERAND (ind, 0));
9428 sf = (tree) n->value;
9429 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9430 src = build_simple_mem_ref_loc (loc, sarg);
9431 src = omp_build_component_ref (src, sf);
9432 src = build_simple_mem_ref_loc (loc, src);
9433 dst = build_simple_mem_ref_loc (loc, arg);
9434 dst = omp_build_component_ref (dst, f);
9435 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9436 append_to_statement_list (t, &list);
9437 n = splay_tree_lookup (ctx->field_map,
9438 (splay_tree_key) TREE_OPERAND (ind, 0));
9439 df = (tree) n->value;
9440 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
9441 ptr = build_simple_mem_ref_loc (loc, arg);
9442 ptr = omp_build_component_ref (ptr, df);
9443 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9444 build_fold_addr_expr_loc (loc, dst));
9445 append_to_statement_list (t, &list);
9448 t = build1 (RETURN_EXPR, void_type_node, NULL);
9449 append_to_statement_list (t, &list);
9451 if (tcctx.cb.decl_map)
9452 pointer_map_destroy (tcctx.cb.decl_map);
9453 pop_gimplify_context (NULL);
9454 BIND_EXPR_BODY (bind) = list;
9455 pop_cfun ();
9458 static void
9459 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9461 tree c, clauses;
9462 gimple g;
9463 size_t n_in = 0, n_out = 0, idx = 2, i;
9465 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9466 OMP_CLAUSE_DEPEND);
9467 gcc_assert (clauses);
9468 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9469 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9470 switch (OMP_CLAUSE_DEPEND_KIND (c))
9472 case OMP_CLAUSE_DEPEND_IN:
9473 n_in++;
9474 break;
9475 case OMP_CLAUSE_DEPEND_OUT:
9476 case OMP_CLAUSE_DEPEND_INOUT:
9477 n_out++;
9478 break;
9479 default:
9480 gcc_unreachable ();
9482 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9483 tree array = create_tmp_var (type, NULL);
9484 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9485 NULL_TREE);
9486 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9487 gimple_seq_add_stmt (iseq, g);
9488 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9489 NULL_TREE);
9490 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9491 gimple_seq_add_stmt (iseq, g);
9492 for (i = 0; i < 2; i++)
9494 if ((i ? n_in : n_out) == 0)
9495 continue;
9496 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9497 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9498 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9500 tree t = OMP_CLAUSE_DECL (c);
9501 t = fold_convert (ptr_type_node, t);
9502 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9503 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9504 NULL_TREE, NULL_TREE);
9505 g = gimple_build_assign (r, t);
9506 gimple_seq_add_stmt (iseq, g);
9509 tree *p = gimple_omp_task_clauses_ptr (stmt);
9510 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9511 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9512 OMP_CLAUSE_CHAIN (c) = *p;
9513 *p = c;
9514 tree clobber = build_constructor (type, NULL);
9515 TREE_THIS_VOLATILE (clobber) = 1;
9516 g = gimple_build_assign (array, clobber);
9517 gimple_seq_add_stmt (oseq, g);
9520 /* Lower the OpenMP parallel or task directive in the current statement
9521 in GSI_P. CTX holds context information for the directive. */
9523 static void
9524 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9526 tree clauses;
9527 tree child_fn, t;
9528 gimple stmt = gsi_stmt (*gsi_p);
9529 gimple par_bind, bind, dep_bind = NULL;
9530 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9531 location_t loc = gimple_location (stmt);
9533 clauses = gimple_omp_taskreg_clauses (stmt);
9534 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9535 par_body = gimple_bind_body (par_bind);
9536 child_fn = ctx->cb.dst_fn;
9537 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9538 && !gimple_omp_parallel_combined_p (stmt))
9540 struct walk_stmt_info wi;
9541 int ws_num = 0;
9543 memset (&wi, 0, sizeof (wi));
9544 wi.info = &ws_num;
9545 wi.val_only = true;
9546 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9547 if (ws_num == 1)
9548 gimple_omp_parallel_set_combined_p (stmt, true);
9550 gimple_seq dep_ilist = NULL;
9551 gimple_seq dep_olist = NULL;
9552 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9553 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9555 push_gimplify_context ();
9556 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9557 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9560 if (ctx->srecord_type)
9561 create_task_copyfn (stmt, ctx);
9563 push_gimplify_context ();
9565 par_olist = NULL;
9566 par_ilist = NULL;
9567 par_rlist = NULL;
9568 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9569 lower_omp (&par_body, ctx);
9570 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9571 lower_reduction_clauses (clauses, &par_rlist, ctx);
9573 /* Declare all the variables created by mapping and the variables
9574 declared in the scope of the parallel body. */
9575 record_vars_into (ctx->block_vars, child_fn);
9576 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9578 if (ctx->record_type)
9580 ctx->sender_decl
9581 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9582 : ctx->record_type, ".omp_data_o");
9583 DECL_NAMELESS (ctx->sender_decl) = 1;
9584 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9585 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9588 olist = NULL;
9589 ilist = NULL;
9590 lower_send_clauses (clauses, &ilist, &olist, ctx);
9591 lower_send_shared_vars (&ilist, &olist, ctx);
9593 if (ctx->record_type)
9595 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9596 TREE_THIS_VOLATILE (clobber) = 1;
9597 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9598 clobber));
9601 /* Once all the expansions are done, sequence all the different
9602 fragments inside gimple_omp_body. */
9604 new_body = NULL;
9606 if (ctx->record_type)
9608 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9609 /* fixup_child_record_type might have changed receiver_decl's type. */
9610 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9611 gimple_seq_add_stmt (&new_body,
9612 gimple_build_assign (ctx->receiver_decl, t));
9615 gimple_seq_add_seq (&new_body, par_ilist);
9616 gimple_seq_add_seq (&new_body, par_body);
9617 gimple_seq_add_seq (&new_body, par_rlist);
9618 if (ctx->cancellable)
9619 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9620 gimple_seq_add_seq (&new_body, par_olist);
9621 new_body = maybe_catch_exception (new_body);
9622 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9623 gimple_omp_set_body (stmt, new_body);
9625 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9626 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
9627 gimple_bind_add_seq (bind, ilist);
9628 gimple_bind_add_stmt (bind, stmt);
9629 gimple_bind_add_seq (bind, olist);
9631 pop_gimplify_context (NULL);
9633 if (dep_bind)
9635 gimple_bind_add_seq (dep_bind, dep_ilist);
9636 gimple_bind_add_stmt (dep_bind, bind);
9637 gimple_bind_add_seq (dep_bind, dep_olist);
9638 pop_gimplify_context (dep_bind);
9642 /* Lower the OpenMP target directive in the current statement
9643 in GSI_P. CTX holds context information for the directive. */
9645 static void
9646 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9648 tree clauses;
9649 tree child_fn, t, c;
9650 gimple stmt = gsi_stmt (*gsi_p);
9651 gimple tgt_bind = NULL, bind;
9652 gimple_seq tgt_body = NULL, olist, ilist, new_body;
9653 location_t loc = gimple_location (stmt);
9654 int kind = gimple_omp_target_kind (stmt);
9655 unsigned int map_cnt = 0;
9657 clauses = gimple_omp_target_clauses (stmt);
9658 if (kind == GF_OMP_TARGET_KIND_REGION)
9660 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9661 tgt_body = gimple_bind_body (tgt_bind);
9663 else if (kind == GF_OMP_TARGET_KIND_DATA)
9664 tgt_body = gimple_omp_body (stmt);
9665 child_fn = ctx->cb.dst_fn;
9667 push_gimplify_context ();
9669 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9670 switch (OMP_CLAUSE_CODE (c))
9672 tree var, x;
9674 default:
9675 break;
9676 case OMP_CLAUSE_MAP:
9677 case OMP_CLAUSE_TO:
9678 case OMP_CLAUSE_FROM:
9679 var = OMP_CLAUSE_DECL (c);
9680 if (!DECL_P (var))
9682 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
9683 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9684 map_cnt++;
9685 continue;
9688 if (DECL_SIZE (var)
9689 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
9691 tree var2 = DECL_VALUE_EXPR (var);
9692 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
9693 var2 = TREE_OPERAND (var2, 0);
9694 gcc_assert (DECL_P (var2));
9695 var = var2;
9698 if (!maybe_lookup_field (var, ctx))
9699 continue;
9701 if (kind == GF_OMP_TARGET_KIND_REGION)
9703 x = build_receiver_ref (var, true, ctx);
9704 tree new_var = lookup_decl (var, ctx);
9705 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9706 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9707 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9708 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
9709 x = build_simple_mem_ref (x);
9710 SET_DECL_VALUE_EXPR (new_var, x);
9711 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
9713 map_cnt++;
9716 if (kind == GF_OMP_TARGET_KIND_REGION)
9718 target_nesting_level++;
9719 lower_omp (&tgt_body, ctx);
9720 target_nesting_level--;
9722 else if (kind == GF_OMP_TARGET_KIND_DATA)
9723 lower_omp (&tgt_body, ctx);
9725 if (kind == GF_OMP_TARGET_KIND_REGION)
9727 /* Declare all the variables created by mapping and the variables
9728 declared in the scope of the target body. */
9729 record_vars_into (ctx->block_vars, child_fn);
9730 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
9733 olist = NULL;
9734 ilist = NULL;
9735 if (ctx->record_type)
9737 ctx->sender_decl
9738 = create_tmp_var (ctx->record_type, ".omp_data_arr");
9739 DECL_NAMELESS (ctx->sender_decl) = 1;
9740 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9741 t = make_tree_vec (3);
9742 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
9743 TREE_VEC_ELT (t, 1)
9744 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
9745 ".omp_data_sizes");
9746 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
9747 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
9748 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
9749 TREE_VEC_ELT (t, 2)
9750 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
9751 map_cnt),
9752 ".omp_data_kinds");
9753 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
9754 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
9755 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
9756 gimple_omp_target_set_data_arg (stmt, t);
9758 vec<constructor_elt, va_gc> *vsize;
9759 vec<constructor_elt, va_gc> *vkind;
9760 vec_alloc (vsize, map_cnt);
9761 vec_alloc (vkind, map_cnt);
9762 unsigned int map_idx = 0;
9764 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9765 switch (OMP_CLAUSE_CODE (c))
9767 tree ovar, nc;
9769 default:
9770 break;
9771 case OMP_CLAUSE_MAP:
9772 case OMP_CLAUSE_TO:
9773 case OMP_CLAUSE_FROM:
9774 nc = c;
9775 ovar = OMP_CLAUSE_DECL (c);
9776 if (!DECL_P (ovar))
9778 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9779 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9781 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
9782 == get_base_address (ovar));
9783 nc = OMP_CLAUSE_CHAIN (c);
9784 ovar = OMP_CLAUSE_DECL (nc);
9786 else
9788 tree x = build_sender_ref (ovar, ctx);
9789 tree v
9790 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
9791 gimplify_assign (x, v, &ilist);
9792 nc = NULL_TREE;
9795 else
9797 if (DECL_SIZE (ovar)
9798 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
9800 tree ovar2 = DECL_VALUE_EXPR (ovar);
9801 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
9802 ovar2 = TREE_OPERAND (ovar2, 0);
9803 gcc_assert (DECL_P (ovar2));
9804 ovar = ovar2;
9806 if (!maybe_lookup_field (ovar, ctx))
9807 continue;
9810 if (nc)
9812 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
9813 tree x = build_sender_ref (ovar, ctx);
9814 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9815 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9816 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9817 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
9819 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9820 tree avar
9821 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
9822 mark_addressable (avar);
9823 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
9824 avar = build_fold_addr_expr (avar);
9825 gimplify_assign (x, avar, &ilist);
9827 else if (is_gimple_reg (var))
9829 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9830 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
9831 mark_addressable (avar);
9832 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
9833 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
9834 gimplify_assign (avar, var, &ilist);
9835 avar = build_fold_addr_expr (avar);
9836 gimplify_assign (x, avar, &ilist);
9837 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
9838 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
9839 && !TYPE_READONLY (TREE_TYPE (var)))
9841 x = build_sender_ref (ovar, ctx);
9842 x = build_simple_mem_ref (x);
9843 gimplify_assign (var, x, &olist);
9846 else
9848 var = build_fold_addr_expr (var);
9849 gimplify_assign (x, var, &ilist);
9852 tree s = OMP_CLAUSE_SIZE (c);
9853 if (s == NULL_TREE)
9854 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
9855 s = fold_convert (size_type_node, s);
9856 tree purpose = size_int (map_idx++);
9857 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
9858 if (TREE_CODE (s) != INTEGER_CST)
9859 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
9861 unsigned char tkind = 0;
9862 switch (OMP_CLAUSE_CODE (c))
9864 case OMP_CLAUSE_MAP:
9865 tkind = OMP_CLAUSE_MAP_KIND (c);
9866 break;
9867 case OMP_CLAUSE_TO:
9868 tkind = OMP_CLAUSE_MAP_TO;
9869 break;
9870 case OMP_CLAUSE_FROM:
9871 tkind = OMP_CLAUSE_MAP_FROM;
9872 break;
9873 default:
9874 gcc_unreachable ();
9876 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
9877 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
9878 talign = DECL_ALIGN_UNIT (ovar);
9879 talign = ceil_log2 (talign);
9880 tkind |= talign << 3;
9881 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
9882 build_int_cst (unsigned_char_type_node,
9883 tkind));
9884 if (nc && nc != c)
9885 c = nc;
9888 gcc_assert (map_idx == map_cnt);
9890 DECL_INITIAL (TREE_VEC_ELT (t, 1))
9891 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
9892 DECL_INITIAL (TREE_VEC_ELT (t, 2))
9893 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
9894 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
9896 gimple_seq initlist = NULL;
9897 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
9898 TREE_VEC_ELT (t, 1)),
9899 &initlist, true, NULL_TREE);
9900 gimple_seq_add_seq (&ilist, initlist);
9902 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
9903 NULL);
9904 TREE_THIS_VOLATILE (clobber) = 1;
9905 gimple_seq_add_stmt (&olist,
9906 gimple_build_assign (TREE_VEC_ELT (t, 1),
9907 clobber));
9910 tree clobber = build_constructor (ctx->record_type, NULL);
9911 TREE_THIS_VOLATILE (clobber) = 1;
9912 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9913 clobber));
9916 /* Once all the expansions are done, sequence all the different
9917 fragments inside gimple_omp_body. */
9919 new_body = NULL;
9921 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
9923 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9924 /* fixup_child_record_type might have changed receiver_decl's type. */
9925 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9926 gimple_seq_add_stmt (&new_body,
9927 gimple_build_assign (ctx->receiver_decl, t));
9930 if (kind == GF_OMP_TARGET_KIND_REGION)
9932 gimple_seq_add_seq (&new_body, tgt_body);
9933 new_body = maybe_catch_exception (new_body);
9935 else if (kind == GF_OMP_TARGET_KIND_DATA)
9936 new_body = tgt_body;
9937 if (kind != GF_OMP_TARGET_KIND_UPDATE)
9939 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9940 gimple_omp_set_body (stmt, new_body);
9943 bind = gimple_build_bind (NULL, NULL,
9944 tgt_bind ? gimple_bind_block (tgt_bind)
9945 : NULL_TREE);
9946 gsi_replace (gsi_p, bind, true);
9947 gimple_bind_add_seq (bind, ilist);
9948 gimple_bind_add_stmt (bind, stmt);
9949 gimple_bind_add_seq (bind, olist);
9951 pop_gimplify_context (NULL);
9954 /* Expand code for an OpenMP teams directive. */
9956 static void
9957 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9959 gimple teams_stmt = gsi_stmt (*gsi_p);
9960 push_gimplify_context ();
9962 tree block = make_node (BLOCK);
9963 gimple bind = gimple_build_bind (NULL, NULL, block);
9964 gsi_replace (gsi_p, bind, true);
9965 gimple_seq bind_body = NULL;
9966 gimple_seq dlist = NULL;
9967 gimple_seq olist = NULL;
9969 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9970 OMP_CLAUSE_NUM_TEAMS);
9971 if (num_teams == NULL_TREE)
9972 num_teams = build_int_cst (unsigned_type_node, 0);
9973 else
9975 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
9976 num_teams = fold_convert (unsigned_type_node, num_teams);
9977 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
9979 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9980 OMP_CLAUSE_THREAD_LIMIT);
9981 if (thread_limit == NULL_TREE)
9982 thread_limit = build_int_cst (unsigned_type_node, 0);
9983 else
9985 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
9986 thread_limit = fold_convert (unsigned_type_node, thread_limit);
9987 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
9988 fb_rvalue);
9991 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
9992 &bind_body, &dlist, ctx, NULL);
9993 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
9994 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
9995 gimple_seq_add_stmt (&bind_body, teams_stmt);
9997 location_t loc = gimple_location (teams_stmt);
9998 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
9999 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10000 gimple_set_location (call, loc);
10001 gimple_seq_add_stmt (&bind_body, call);
10003 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10004 gimple_omp_set_body (teams_stmt, NULL);
10005 gimple_seq_add_seq (&bind_body, olist);
10006 gimple_seq_add_seq (&bind_body, dlist);
10007 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10008 gimple_bind_set_body (bind, bind_body);
10010 pop_gimplify_context (bind);
10012 gimple_bind_append_vars (bind, ctx->block_vars);
10013 BLOCK_VARS (block) = ctx->block_vars;
10014 if (BLOCK_VARS (block))
10015 TREE_USED (block) = 1;
10019 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10020 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10021 of OpenMP context, but with task_shared_vars set. */
10023 static tree
10024 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10025 void *data)
10027 tree t = *tp;
10029 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10030 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
10031 return t;
10033 if (task_shared_vars
10034 && DECL_P (t)
10035 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10036 return t;
10038 /* If a global variable has been privatized, TREE_CONSTANT on
10039 ADDR_EXPR might be wrong. */
10040 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10041 recompute_tree_invariant_for_addr_expr (t);
10043 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10044 return NULL_TREE;
10047 static void
10048 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10050 gimple stmt = gsi_stmt (*gsi_p);
10051 struct walk_stmt_info wi;
10053 if (gimple_has_location (stmt))
10054 input_location = gimple_location (stmt);
10056 if (task_shared_vars)
10057 memset (&wi, '\0', sizeof (wi));
10059 /* If we have issued syntax errors, avoid doing any heavy lifting.
10060 Just replace the OpenMP directives with a NOP to avoid
10061 confusing RTL expansion. */
10062 if (seen_error () && is_gimple_omp (stmt))
10064 gsi_replace (gsi_p, gimple_build_nop (), true);
10065 return;
10068 switch (gimple_code (stmt))
10070 case GIMPLE_COND:
10071 if ((ctx || task_shared_vars)
10072 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
10073 ctx ? NULL : &wi, NULL)
10074 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
10075 ctx ? NULL : &wi, NULL)))
10076 gimple_regimplify_operands (stmt, gsi_p);
10077 break;
10078 case GIMPLE_CATCH:
10079 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
10080 break;
10081 case GIMPLE_EH_FILTER:
10082 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10083 break;
10084 case GIMPLE_TRY:
10085 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10086 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10087 break;
10088 case GIMPLE_TRANSACTION:
10089 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
10090 break;
10091 case GIMPLE_BIND:
10092 lower_omp (gimple_bind_body_ptr (stmt), ctx);
10093 break;
10094 case GIMPLE_OMP_PARALLEL:
10095 case GIMPLE_OMP_TASK:
10096 ctx = maybe_lookup_ctx (stmt);
10097 gcc_assert (ctx);
10098 if (ctx->cancellable)
10099 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10100 lower_omp_taskreg (gsi_p, ctx);
10101 break;
10102 case GIMPLE_OMP_FOR:
10103 ctx = maybe_lookup_ctx (stmt);
10104 gcc_assert (ctx);
10105 if (ctx->cancellable)
10106 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10107 lower_omp_for (gsi_p, ctx);
10108 break;
10109 case GIMPLE_OMP_SECTIONS:
10110 ctx = maybe_lookup_ctx (stmt);
10111 gcc_assert (ctx);
10112 if (ctx->cancellable)
10113 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10114 lower_omp_sections (gsi_p, ctx);
10115 break;
10116 case GIMPLE_OMP_SINGLE:
10117 ctx = maybe_lookup_ctx (stmt);
10118 gcc_assert (ctx);
10119 lower_omp_single (gsi_p, ctx);
10120 break;
10121 case GIMPLE_OMP_MASTER:
10122 ctx = maybe_lookup_ctx (stmt);
10123 gcc_assert (ctx);
10124 lower_omp_master (gsi_p, ctx);
10125 break;
10126 case GIMPLE_OMP_TASKGROUP:
10127 ctx = maybe_lookup_ctx (stmt);
10128 gcc_assert (ctx);
10129 lower_omp_taskgroup (gsi_p, ctx);
10130 break;
10131 case GIMPLE_OMP_ORDERED:
10132 ctx = maybe_lookup_ctx (stmt);
10133 gcc_assert (ctx);
10134 lower_omp_ordered (gsi_p, ctx);
10135 break;
10136 case GIMPLE_OMP_CRITICAL:
10137 ctx = maybe_lookup_ctx (stmt);
10138 gcc_assert (ctx);
10139 lower_omp_critical (gsi_p, ctx);
10140 break;
10141 case GIMPLE_OMP_ATOMIC_LOAD:
10142 if ((ctx || task_shared_vars)
10143 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
10144 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10145 gimple_regimplify_operands (stmt, gsi_p);
10146 break;
10147 case GIMPLE_OMP_TARGET:
10148 ctx = maybe_lookup_ctx (stmt);
10149 gcc_assert (ctx);
10150 lower_omp_target (gsi_p, ctx);
10151 break;
10152 case GIMPLE_OMP_TEAMS:
10153 ctx = maybe_lookup_ctx (stmt);
10154 gcc_assert (ctx);
10155 lower_omp_teams (gsi_p, ctx);
10156 break;
10157 case GIMPLE_CALL:
10158 tree fndecl;
10159 fndecl = gimple_call_fndecl (stmt);
10160 if (fndecl
10161 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10162 switch (DECL_FUNCTION_CODE (fndecl))
10164 case BUILT_IN_GOMP_BARRIER:
10165 if (ctx == NULL)
10166 break;
10167 /* FALLTHRU */
10168 case BUILT_IN_GOMP_CANCEL:
10169 case BUILT_IN_GOMP_CANCELLATION_POINT:
10170 omp_context *cctx;
10171 cctx = ctx;
10172 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10173 cctx = cctx->outer;
10174 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10175 if (!cctx->cancellable)
10177 if (DECL_FUNCTION_CODE (fndecl)
10178 == BUILT_IN_GOMP_CANCELLATION_POINT)
10180 stmt = gimple_build_nop ();
10181 gsi_replace (gsi_p, stmt, false);
10183 break;
10185 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10187 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10188 gimple_call_set_fndecl (stmt, fndecl);
10189 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10191 tree lhs;
10192 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
10193 gimple_call_set_lhs (stmt, lhs);
10194 tree fallthru_label;
10195 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10196 gimple g;
10197 g = gimple_build_label (fallthru_label);
10198 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10199 g = gimple_build_cond (NE_EXPR, lhs,
10200 fold_convert (TREE_TYPE (lhs),
10201 boolean_false_node),
10202 cctx->cancel_label, fallthru_label);
10203 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10204 break;
10205 default:
10206 break;
10208 /* FALLTHRU */
10209 default:
10210 if ((ctx || task_shared_vars)
10211 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10212 ctx ? NULL : &wi))
10214 /* Just remove clobbers, this should happen only if we have
10215 "privatized" local addressable variables in SIMD regions,
10216 the clobber isn't needed in that case and gimplifying address
10217 of the ARRAY_REF into a pointer and creating MEM_REF based
10218 clobber would create worse code than we get with the clobber
10219 dropped. */
10220 if (gimple_clobber_p (stmt))
10222 gsi_replace (gsi_p, gimple_build_nop (), true);
10223 break;
10225 gimple_regimplify_operands (stmt, gsi_p);
10227 break;
10231 static void
10232 lower_omp (gimple_seq *body, omp_context *ctx)
10234 location_t saved_location = input_location;
10235 gimple_stmt_iterator gsi;
10236 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10237 lower_omp_1 (&gsi, ctx);
10238 /* During gimplification, we have not always invoked fold_stmt
10239 (gimplify.c:maybe_fold_stmt); call it now. */
10240 if (target_nesting_level)
10241 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10242 fold_stmt (&gsi);
10243 input_location = saved_location;
10246 /* Main entry point. */
10248 static unsigned int
10249 execute_lower_omp (void)
10251 gimple_seq body;
10253 /* This pass always runs, to provide PROP_gimple_lomp.
10254 But there is nothing to do unless -fopenmp is given. */
10255 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10256 return 0;
10258 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10259 delete_omp_context);
10261 body = gimple_body (current_function_decl);
10262 scan_omp (&body, NULL);
10263 gcc_assert (taskreg_nesting_level == 0);
10265 if (all_contexts->root)
10267 if (task_shared_vars)
10268 push_gimplify_context ();
10269 lower_omp (&body, NULL);
10270 if (task_shared_vars)
10271 pop_gimplify_context (NULL);
10274 if (all_contexts)
10276 splay_tree_delete (all_contexts);
10277 all_contexts = NULL;
10279 BITMAP_FREE (task_shared_vars);
10280 return 0;
10283 namespace {
10285 const pass_data pass_data_lower_omp =
10287 GIMPLE_PASS, /* type */
10288 "omplower", /* name */
10289 OPTGROUP_NONE, /* optinfo_flags */
10290 TV_NONE, /* tv_id */
10291 PROP_gimple_any, /* properties_required */
10292 PROP_gimple_lomp, /* properties_provided */
10293 0, /* properties_destroyed */
10294 0, /* todo_flags_start */
10295 0, /* todo_flags_finish */
10298 class pass_lower_omp : public gimple_opt_pass
10300 public:
10301 pass_lower_omp (gcc::context *ctxt)
10302 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10305 /* opt_pass methods: */
10306 virtual unsigned int execute (function *) { return execute_lower_omp (); }
10308 }; // class pass_lower_omp
10310 } // anon namespace
10312 gimple_opt_pass *
10313 make_pass_lower_omp (gcc::context *ctxt)
10315 return new pass_lower_omp (ctxt);
10318 /* The following is a utility to diagnose OpenMP structured block violations.
10319 It is not part of the "omplower" pass, as that's invoked too late. It
10320 should be invoked by the respective front ends after gimplification. */
10322 static splay_tree all_labels;
10324 /* Check for mismatched contexts and generate an error if needed. Return
10325 true if an error is detected. */
10327 static bool
10328 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10329 gimple branch_ctx, gimple label_ctx)
10331 if (label_ctx == branch_ctx)
10332 return false;
10336 Previously we kept track of the label's entire context in diagnose_sb_[12]
10337 so we could traverse it and issue a correct "exit" or "enter" error
10338 message upon a structured block violation.
10340 We built the context by building a list with tree_cons'ing, but there is
10341 no easy counterpart in gimple tuples. It seems like far too much work
10342 for issuing exit/enter error messages. If someone really misses the
10343 distinct error message... patches welcome.
10346 #if 0
10347 /* Try to avoid confusing the user by producing and error message
10348 with correct "exit" or "enter" verbiage. We prefer "exit"
10349 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10350 if (branch_ctx == NULL)
10351 exit_p = false;
10352 else
10354 while (label_ctx)
10356 if (TREE_VALUE (label_ctx) == branch_ctx)
10358 exit_p = false;
10359 break;
10361 label_ctx = TREE_CHAIN (label_ctx);
10365 if (exit_p)
10366 error ("invalid exit from OpenMP structured block");
10367 else
10368 error ("invalid entry to OpenMP structured block");
10369 #endif
10371 bool cilkplus_block = false;
10372 if (flag_cilkplus)
10374 if ((branch_ctx
10375 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10376 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10377 || (label_ctx
10378 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10379 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10380 cilkplus_block = true;
10383 /* If it's obvious we have an invalid entry, be specific about the error. */
10384 if (branch_ctx == NULL)
10386 if (cilkplus_block)
10387 error ("invalid entry to Cilk Plus structured block");
10388 else
10389 error ("invalid entry to OpenMP structured block");
10391 else
10393 /* Otherwise, be vague and lazy, but efficient. */
10394 if (cilkplus_block)
10395 error ("invalid branch to/from a Cilk Plus structured block");
10396 else
10397 error ("invalid branch to/from an OpenMP structured block");
10400 gsi_replace (gsi_p, gimple_build_nop (), false);
10401 return true;
10404 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10405 where each label is found. */
10407 static tree
10408 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10409 struct walk_stmt_info *wi)
10411 gimple context = (gimple) wi->info;
10412 gimple inner_context;
10413 gimple stmt = gsi_stmt (*gsi_p);
10415 *handled_ops_p = true;
10417 switch (gimple_code (stmt))
10419 WALK_SUBSTMTS;
10421 case GIMPLE_OMP_PARALLEL:
10422 case GIMPLE_OMP_TASK:
10423 case GIMPLE_OMP_SECTIONS:
10424 case GIMPLE_OMP_SINGLE:
10425 case GIMPLE_OMP_SECTION:
10426 case GIMPLE_OMP_MASTER:
10427 case GIMPLE_OMP_ORDERED:
10428 case GIMPLE_OMP_CRITICAL:
10429 case GIMPLE_OMP_TARGET:
10430 case GIMPLE_OMP_TEAMS:
10431 case GIMPLE_OMP_TASKGROUP:
10432 /* The minimal context here is just the current OMP construct. */
10433 inner_context = stmt;
10434 wi->info = inner_context;
10435 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10436 wi->info = context;
10437 break;
10439 case GIMPLE_OMP_FOR:
10440 inner_context = stmt;
10441 wi->info = inner_context;
10442 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10443 walk them. */
10444 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10445 diagnose_sb_1, NULL, wi);
10446 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10447 wi->info = context;
10448 break;
10450 case GIMPLE_LABEL:
10451 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10452 (splay_tree_value) context);
10453 break;
10455 default:
10456 break;
10459 return NULL_TREE;
10462 /* Pass 2: Check each branch and see if its context differs from that of
10463 the destination label's context. */
10465 static tree
10466 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10467 struct walk_stmt_info *wi)
10469 gimple context = (gimple) wi->info;
10470 splay_tree_node n;
10471 gimple stmt = gsi_stmt (*gsi_p);
10473 *handled_ops_p = true;
10475 switch (gimple_code (stmt))
10477 WALK_SUBSTMTS;
10479 case GIMPLE_OMP_PARALLEL:
10480 case GIMPLE_OMP_TASK:
10481 case GIMPLE_OMP_SECTIONS:
10482 case GIMPLE_OMP_SINGLE:
10483 case GIMPLE_OMP_SECTION:
10484 case GIMPLE_OMP_MASTER:
10485 case GIMPLE_OMP_ORDERED:
10486 case GIMPLE_OMP_CRITICAL:
10487 case GIMPLE_OMP_TARGET:
10488 case GIMPLE_OMP_TEAMS:
10489 case GIMPLE_OMP_TASKGROUP:
10490 wi->info = stmt;
10491 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10492 wi->info = context;
10493 break;
10495 case GIMPLE_OMP_FOR:
10496 wi->info = stmt;
10497 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10498 walk them. */
10499 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10500 diagnose_sb_2, NULL, wi);
10501 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10502 wi->info = context;
10503 break;
10505 case GIMPLE_COND:
10507 tree lab = gimple_cond_true_label (stmt);
10508 if (lab)
10510 n = splay_tree_lookup (all_labels,
10511 (splay_tree_key) lab);
10512 diagnose_sb_0 (gsi_p, context,
10513 n ? (gimple) n->value : NULL);
10515 lab = gimple_cond_false_label (stmt);
10516 if (lab)
10518 n = splay_tree_lookup (all_labels,
10519 (splay_tree_key) lab);
10520 diagnose_sb_0 (gsi_p, context,
10521 n ? (gimple) n->value : NULL);
10524 break;
10526 case GIMPLE_GOTO:
10528 tree lab = gimple_goto_dest (stmt);
10529 if (TREE_CODE (lab) != LABEL_DECL)
10530 break;
10532 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10533 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10535 break;
10537 case GIMPLE_SWITCH:
10539 unsigned int i;
10540 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10542 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10543 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10544 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10545 break;
10548 break;
10550 case GIMPLE_RETURN:
10551 diagnose_sb_0 (gsi_p, context, NULL);
10552 break;
10554 default:
10555 break;
10558 return NULL_TREE;
10561 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10562 codes. */
10563 bool
10564 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
10565 int *region_idx)
10567 gimple last = last_stmt (bb);
10568 enum gimple_code code = gimple_code (last);
10569 struct omp_region *cur_region = *region;
10570 bool fallthru = false;
10572 switch (code)
10574 case GIMPLE_OMP_PARALLEL:
10575 case GIMPLE_OMP_TASK:
10576 case GIMPLE_OMP_FOR:
10577 case GIMPLE_OMP_SINGLE:
10578 case GIMPLE_OMP_TEAMS:
10579 case GIMPLE_OMP_MASTER:
10580 case GIMPLE_OMP_TASKGROUP:
10581 case GIMPLE_OMP_ORDERED:
10582 case GIMPLE_OMP_CRITICAL:
10583 case GIMPLE_OMP_SECTION:
10584 cur_region = new_omp_region (bb, code, cur_region);
10585 fallthru = true;
10586 break;
10588 case GIMPLE_OMP_TARGET:
10589 cur_region = new_omp_region (bb, code, cur_region);
10590 fallthru = true;
10591 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10592 cur_region = cur_region->outer;
10593 break;
10595 case GIMPLE_OMP_SECTIONS:
10596 cur_region = new_omp_region (bb, code, cur_region);
10597 fallthru = true;
10598 break;
10600 case GIMPLE_OMP_SECTIONS_SWITCH:
10601 fallthru = false;
10602 break;
10604 case GIMPLE_OMP_ATOMIC_LOAD:
10605 case GIMPLE_OMP_ATOMIC_STORE:
10606 fallthru = true;
10607 break;
10609 case GIMPLE_OMP_RETURN:
10610 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10611 somewhere other than the next block. This will be
10612 created later. */
10613 cur_region->exit = bb;
10614 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
10615 cur_region = cur_region->outer;
10616 break;
10618 case GIMPLE_OMP_CONTINUE:
10619 cur_region->cont = bb;
10620 switch (cur_region->type)
10622 case GIMPLE_OMP_FOR:
10623 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
10624 succs edges as abnormal to prevent splitting
10625 them. */
10626 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
10627 /* Make the loopback edge. */
10628 make_edge (bb, single_succ (cur_region->entry),
10629 EDGE_ABNORMAL);
10631 /* Create an edge from GIMPLE_OMP_FOR to exit, which
10632 corresponds to the case that the body of the loop
10633 is not executed at all. */
10634 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
10635 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
10636 fallthru = false;
10637 break;
10639 case GIMPLE_OMP_SECTIONS:
10640 /* Wire up the edges into and out of the nested sections. */
10642 basic_block switch_bb = single_succ (cur_region->entry);
10644 struct omp_region *i;
10645 for (i = cur_region->inner; i ; i = i->next)
10647 gcc_assert (i->type == GIMPLE_OMP_SECTION);
10648 make_edge (switch_bb, i->entry, 0);
10649 make_edge (i->exit, bb, EDGE_FALLTHRU);
10652 /* Make the loopback edge to the block with
10653 GIMPLE_OMP_SECTIONS_SWITCH. */
10654 make_edge (bb, switch_bb, 0);
10656 /* Make the edge from the switch to exit. */
10657 make_edge (switch_bb, bb->next_bb, 0);
10658 fallthru = false;
10660 break;
10662 default:
10663 gcc_unreachable ();
10665 break;
10667 default:
10668 gcc_unreachable ();
10671 if (*region != cur_region)
10673 *region = cur_region;
10674 if (cur_region)
10675 *region_idx = cur_region->entry->index;
10676 else
10677 *region_idx = 0;
10680 return fallthru;
10683 static unsigned int
10684 diagnose_omp_structured_block_errors (void)
10686 struct walk_stmt_info wi;
10687 gimple_seq body = gimple_body (current_function_decl);
10689 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
10691 memset (&wi, 0, sizeof (wi));
10692 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
10694 memset (&wi, 0, sizeof (wi));
10695 wi.want_locations = true;
10696 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
10698 gimple_set_body (current_function_decl, body);
10700 splay_tree_delete (all_labels);
10701 all_labels = NULL;
10703 return 0;
10706 namespace {
10708 const pass_data pass_data_diagnose_omp_blocks =
10710 GIMPLE_PASS, /* type */
10711 "*diagnose_omp_blocks", /* name */
10712 OPTGROUP_NONE, /* optinfo_flags */
10713 TV_NONE, /* tv_id */
10714 PROP_gimple_any, /* properties_required */
10715 0, /* properties_provided */
10716 0, /* properties_destroyed */
10717 0, /* todo_flags_start */
10718 0, /* todo_flags_finish */
10721 class pass_diagnose_omp_blocks : public gimple_opt_pass
10723 public:
10724 pass_diagnose_omp_blocks (gcc::context *ctxt)
10725 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
10728 /* opt_pass methods: */
10729 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
10730 virtual unsigned int execute (function *)
10732 return diagnose_omp_structured_block_errors ();
10735 }; // class pass_diagnose_omp_blocks
10737 } // anon namespace
10739 gimple_opt_pass *
10740 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
10742 return new pass_diagnose_omp_blocks (ctxt);
10745 /* SIMD clone supporting code. */
10747 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
10748 of arguments to reserve space for. */
10750 static struct cgraph_simd_clone *
10751 simd_clone_struct_alloc (int nargs)
10753 struct cgraph_simd_clone *clone_info;
10754 size_t len = (sizeof (struct cgraph_simd_clone)
10755 + nargs * sizeof (struct cgraph_simd_clone_arg));
10756 clone_info = (struct cgraph_simd_clone *)
10757 ggc_internal_cleared_alloc (len);
10758 return clone_info;
10761 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
10763 static inline void
10764 simd_clone_struct_copy (struct cgraph_simd_clone *to,
10765 struct cgraph_simd_clone *from)
10767 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
10768 + ((from->nargs - from->inbranch)
10769 * sizeof (struct cgraph_simd_clone_arg))));
10772 /* Return vector of parameter types of function FNDECL. This uses
10773 TYPE_ARG_TYPES if available, otherwise falls back to types of
10774 DECL_ARGUMENTS types. */
10776 vec<tree>
10777 simd_clone_vector_of_formal_parm_types (tree fndecl)
10779 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
10780 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
10781 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
10782 unsigned int i;
10783 tree arg;
10784 FOR_EACH_VEC_ELT (args, i, arg)
10785 args[i] = TREE_TYPE (args[i]);
10786 return args;
10789 /* Given a simd function in NODE, extract the simd specific
10790 information from the OMP clauses passed in CLAUSES, and return
10791 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
10792 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
10793 otherwise set to FALSE. */
10795 static struct cgraph_simd_clone *
10796 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
10797 bool *inbranch_specified)
10799 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
10800 tree t;
10801 int n;
10802 *inbranch_specified = false;
10804 n = args.length ();
10805 if (n > 0 && args.last () == void_type_node)
10806 n--;
10808 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
10809 be cloned have a distinctive artificial label in addition to "omp
10810 declare simd". */
10811 bool cilk_clone
10812 = (flag_cilkplus
10813 && lookup_attribute ("cilk simd function",
10814 DECL_ATTRIBUTES (node->decl)));
10816 /* Allocate one more than needed just in case this is an in-branch
10817 clone which will require a mask argument. */
10818 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
10819 clone_info->nargs = n;
10820 clone_info->cilk_elemental = cilk_clone;
10822 if (!clauses)
10824 args.release ();
10825 return clone_info;
10827 clauses = TREE_VALUE (clauses);
10828 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
10829 return clone_info;
10831 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
10833 switch (OMP_CLAUSE_CODE (t))
10835 case OMP_CLAUSE_INBRANCH:
10836 clone_info->inbranch = 1;
10837 *inbranch_specified = true;
10838 break;
10839 case OMP_CLAUSE_NOTINBRANCH:
10840 clone_info->inbranch = 0;
10841 *inbranch_specified = true;
10842 break;
10843 case OMP_CLAUSE_SIMDLEN:
10844 clone_info->simdlen
10845 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
10846 break;
10847 case OMP_CLAUSE_LINEAR:
10849 tree decl = OMP_CLAUSE_DECL (t);
10850 tree step = OMP_CLAUSE_LINEAR_STEP (t);
10851 int argno = TREE_INT_CST_LOW (decl);
10852 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
10854 clone_info->args[argno].arg_type
10855 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
10856 clone_info->args[argno].linear_step = tree_to_shwi (step);
10857 gcc_assert (clone_info->args[argno].linear_step >= 0
10858 && clone_info->args[argno].linear_step < n);
10860 else
10862 if (POINTER_TYPE_P (args[argno]))
10863 step = fold_convert (ssizetype, step);
10864 if (!tree_fits_shwi_p (step))
10866 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10867 "ignoring large linear step");
10868 args.release ();
10869 return NULL;
10871 else if (integer_zerop (step))
10873 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10874 "ignoring zero linear step");
10875 args.release ();
10876 return NULL;
10878 else
10880 clone_info->args[argno].arg_type
10881 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
10882 clone_info->args[argno].linear_step = tree_to_shwi (step);
10885 break;
10887 case OMP_CLAUSE_UNIFORM:
10889 tree decl = OMP_CLAUSE_DECL (t);
10890 int argno = tree_to_uhwi (decl);
10891 clone_info->args[argno].arg_type
10892 = SIMD_CLONE_ARG_TYPE_UNIFORM;
10893 break;
10895 case OMP_CLAUSE_ALIGNED:
10897 tree decl = OMP_CLAUSE_DECL (t);
10898 int argno = tree_to_uhwi (decl);
10899 clone_info->args[argno].alignment
10900 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
10901 break;
10903 default:
10904 break;
10907 args.release ();
10908 return clone_info;
10911 /* Given a SIMD clone in NODE, calculate the characteristic data
10912 type and return the coresponding type. The characteristic data
10913 type is computed as described in the Intel Vector ABI. */
10915 static tree
10916 simd_clone_compute_base_data_type (struct cgraph_node *node,
10917 struct cgraph_simd_clone *clone_info)
10919 tree type = integer_type_node;
10920 tree fndecl = node->decl;
10922 /* a) For non-void function, the characteristic data type is the
10923 return type. */
10924 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
10925 type = TREE_TYPE (TREE_TYPE (fndecl));
10927 /* b) If the function has any non-uniform, non-linear parameters,
10928 then the characteristic data type is the type of the first
10929 such parameter. */
10930 else
10932 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
10933 for (unsigned int i = 0; i < clone_info->nargs; ++i)
10934 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
10936 type = map[i];
10937 break;
10939 map.release ();
10942 /* c) If the characteristic data type determined by a) or b) above
10943 is struct, union, or class type which is pass-by-value (except
10944 for the type that maps to the built-in complex data type), the
10945 characteristic data type is int. */
10946 if (RECORD_OR_UNION_TYPE_P (type)
10947 && !aggregate_value_p (type, NULL)
10948 && TREE_CODE (type) != COMPLEX_TYPE)
10949 return integer_type_node;
10951 /* d) If none of the above three classes is applicable, the
10952 characteristic data type is int. */
10954 return type;
10956 /* e) For Intel Xeon Phi native and offload compilation, if the
10957 resulting characteristic data type is 8-bit or 16-bit integer
10958 data type, the characteristic data type is int. */
10959 /* Well, we don't handle Xeon Phi yet. */
10962 static tree
10963 simd_clone_mangle (struct cgraph_node *node,
10964 struct cgraph_simd_clone *clone_info)
10966 char vecsize_mangle = clone_info->vecsize_mangle;
10967 char mask = clone_info->inbranch ? 'M' : 'N';
10968 unsigned int simdlen = clone_info->simdlen;
10969 unsigned int n;
10970 pretty_printer pp;
10972 gcc_assert (vecsize_mangle && simdlen);
10974 pp_string (&pp, "_ZGV");
10975 pp_character (&pp, vecsize_mangle);
10976 pp_character (&pp, mask);
10977 pp_decimal_int (&pp, simdlen);
10979 for (n = 0; n < clone_info->nargs; ++n)
10981 struct cgraph_simd_clone_arg arg = clone_info->args[n];
10983 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
10984 pp_character (&pp, 'u');
10985 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
10987 gcc_assert (arg.linear_step != 0);
10988 pp_character (&pp, 'l');
10989 if (arg.linear_step > 1)
10990 pp_unsigned_wide_integer (&pp, arg.linear_step);
10991 else if (arg.linear_step < 0)
10993 pp_character (&pp, 'n');
10994 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
10995 arg.linear_step));
10998 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11000 pp_character (&pp, 's');
11001 pp_unsigned_wide_integer (&pp, arg.linear_step);
11003 else
11004 pp_character (&pp, 'v');
11005 if (arg.alignment)
11007 pp_character (&pp, 'a');
11008 pp_decimal_int (&pp, arg.alignment);
11012 pp_underscore (&pp);
11013 pp_string (&pp,
11014 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11015 const char *str = pp_formatted_text (&pp);
11017 /* If there already is a SIMD clone with the same mangled name, don't
11018 add another one. This can happen e.g. for
11019 #pragma omp declare simd
11020 #pragma omp declare simd simdlen(8)
11021 int foo (int, int);
11022 if the simdlen is assumed to be 8 for the first one, etc. */
11023 for (struct cgraph_node *clone = node->simd_clones; clone;
11024 clone = clone->simdclone->next_clone)
11025 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11026 str) == 0)
11027 return NULL_TREE;
11029 return get_identifier (str);
11032 /* Create a simd clone of OLD_NODE and return it. */
11034 static struct cgraph_node *
11035 simd_clone_create (struct cgraph_node *old_node)
11037 struct cgraph_node *new_node;
11038 if (old_node->definition)
11040 if (!cgraph_function_with_gimple_body_p (old_node))
11041 return NULL;
11042 cgraph_get_body (old_node);
11043 new_node = cgraph_function_versioning (old_node, vNULL, NULL, NULL,
11044 false, NULL, NULL, "simdclone");
11046 else
11048 tree old_decl = old_node->decl;
11049 tree new_decl = copy_node (old_node->decl);
11050 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11051 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11052 SET_DECL_RTL (new_decl, NULL);
11053 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11054 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11055 new_node
11056 = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL);
11057 cgraph_call_function_insertion_hooks (new_node);
11059 if (new_node == NULL)
11060 return new_node;
11062 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11064 /* The function cgraph_function_versioning () will force the new
11065 symbol local. Undo this, and inherit external visability from
11066 the old node. */
11067 new_node->local.local = old_node->local.local;
11068 new_node->externally_visible = old_node->externally_visible;
11070 return new_node;
11073 /* Adjust the return type of the given function to its appropriate
11074 vector counterpart. Returns a simd array to be used throughout the
11075 function as a return value. */
11077 static tree
11078 simd_clone_adjust_return_type (struct cgraph_node *node)
11080 tree fndecl = node->decl;
11081 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11082 unsigned int veclen;
11083 tree t;
11085 /* Adjust the function return type. */
11086 if (orig_rettype == void_type_node)
11087 return NULL_TREE;
11088 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11089 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11090 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11091 veclen = node->simdclone->vecsize_int;
11092 else
11093 veclen = node->simdclone->vecsize_float;
11094 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11095 if (veclen > node->simdclone->simdlen)
11096 veclen = node->simdclone->simdlen;
11097 if (veclen == node->simdclone->simdlen)
11098 TREE_TYPE (TREE_TYPE (fndecl))
11099 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11100 node->simdclone->simdlen);
11101 else
11103 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11104 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11105 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11107 if (!node->definition)
11108 return NULL_TREE;
11110 t = DECL_RESULT (fndecl);
11111 /* Adjust the DECL_RESULT. */
11112 gcc_assert (TREE_TYPE (t) != void_type_node);
11113 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11114 relayout_decl (t);
11116 tree atype = build_array_type_nelts (orig_rettype,
11117 node->simdclone->simdlen);
11118 if (veclen != node->simdclone->simdlen)
11119 return build1 (VIEW_CONVERT_EXPR, atype, t);
11121 /* Set up a SIMD array to use as the return value. */
11122 tree retval = create_tmp_var_raw (atype, "retval");
11123 gimple_add_tmp_var (retval);
11124 return retval;
11127 /* Each vector argument has a corresponding array to be used locally
11128 as part of the eventual loop. Create such temporary array and
11129 return it.
11131 PREFIX is the prefix to be used for the temporary.
11133 TYPE is the inner element type.
11135 SIMDLEN is the number of elements. */
11137 static tree
11138 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11140 tree atype = build_array_type_nelts (type, simdlen);
11141 tree avar = create_tmp_var_raw (atype, prefix);
11142 gimple_add_tmp_var (avar);
11143 return avar;
11146 /* Modify the function argument types to their corresponding vector
11147 counterparts if appropriate. Also, create one array for each simd
11148 argument to be used locally when using the function arguments as
11149 part of the loop.
11151 NODE is the function whose arguments are to be adjusted.
11153 Returns an adjustment vector that will be filled describing how the
11154 argument types will be adjusted. */
11156 static ipa_parm_adjustment_vec
11157 simd_clone_adjust_argument_types (struct cgraph_node *node)
11159 vec<tree> args;
11160 ipa_parm_adjustment_vec adjustments;
11162 if (node->definition)
11163 args = ipa_get_vector_of_formal_parms (node->decl);
11164 else
11165 args = simd_clone_vector_of_formal_parm_types (node->decl);
11166 adjustments.create (args.length ());
11167 unsigned i, j, veclen;
11168 struct ipa_parm_adjustment adj;
11169 for (i = 0; i < node->simdclone->nargs; ++i)
11171 memset (&adj, 0, sizeof (adj));
11172 tree parm = args[i];
11173 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11174 adj.base_index = i;
11175 adj.base = parm;
11177 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11178 node->simdclone->args[i].orig_type = parm_type;
11180 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11182 /* No adjustment necessary for scalar arguments. */
11183 adj.op = IPA_PARM_OP_COPY;
11185 else
11187 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11188 veclen = node->simdclone->vecsize_int;
11189 else
11190 veclen = node->simdclone->vecsize_float;
11191 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11192 if (veclen > node->simdclone->simdlen)
11193 veclen = node->simdclone->simdlen;
11194 adj.arg_prefix = "simd";
11195 adj.type = build_vector_type (parm_type, veclen);
11196 node->simdclone->args[i].vector_type = adj.type;
11197 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11199 adjustments.safe_push (adj);
11200 if (j == veclen)
11202 memset (&adj, 0, sizeof (adj));
11203 adj.op = IPA_PARM_OP_NEW;
11204 adj.arg_prefix = "simd";
11205 adj.base_index = i;
11206 adj.type = node->simdclone->args[i].vector_type;
11210 if (node->definition)
11211 node->simdclone->args[i].simd_array
11212 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11213 parm_type, node->simdclone->simdlen);
11215 adjustments.safe_push (adj);
11218 if (node->simdclone->inbranch)
11220 tree base_type
11221 = simd_clone_compute_base_data_type (node->simdclone->origin,
11222 node->simdclone);
11224 memset (&adj, 0, sizeof (adj));
11225 adj.op = IPA_PARM_OP_NEW;
11226 adj.arg_prefix = "mask";
11228 adj.base_index = i;
11229 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11230 veclen = node->simdclone->vecsize_int;
11231 else
11232 veclen = node->simdclone->vecsize_float;
11233 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11234 if (veclen > node->simdclone->simdlen)
11235 veclen = node->simdclone->simdlen;
11236 adj.type = build_vector_type (base_type, veclen);
11237 adjustments.safe_push (adj);
11239 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11240 adjustments.safe_push (adj);
11242 /* We have previously allocated one extra entry for the mask. Use
11243 it and fill it. */
11244 struct cgraph_simd_clone *sc = node->simdclone;
11245 sc->nargs++;
11246 if (node->definition)
11248 sc->args[i].orig_arg
11249 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11250 sc->args[i].simd_array
11251 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11253 sc->args[i].orig_type = base_type;
11254 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11257 if (node->definition)
11258 ipa_modify_formal_parameters (node->decl, adjustments);
11259 else
11261 tree new_arg_types = NULL_TREE, new_reversed;
11262 bool last_parm_void = false;
11263 if (args.length () > 0 && args.last () == void_type_node)
11264 last_parm_void = true;
11266 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11267 j = adjustments.length ();
11268 for (i = 0; i < j; i++)
11270 struct ipa_parm_adjustment *adj = &adjustments[i];
11271 tree ptype;
11272 if (adj->op == IPA_PARM_OP_COPY)
11273 ptype = args[adj->base_index];
11274 else
11275 ptype = adj->type;
11276 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11278 new_reversed = nreverse (new_arg_types);
11279 if (last_parm_void)
11281 if (new_reversed)
11282 TREE_CHAIN (new_arg_types) = void_list_node;
11283 else
11284 new_reversed = void_list_node;
11287 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11288 TYPE_ARG_TYPES (new_type) = new_reversed;
11289 TREE_TYPE (node->decl) = new_type;
11291 adjustments.release ();
11293 args.release ();
11294 return adjustments;
11297 /* Initialize and copy the function arguments in NODE to their
11298 corresponding local simd arrays. Returns a fresh gimple_seq with
11299 the instruction sequence generated. */
11301 static gimple_seq
11302 simd_clone_init_simd_arrays (struct cgraph_node *node,
11303 ipa_parm_adjustment_vec adjustments)
11305 gimple_seq seq = NULL;
11306 unsigned i = 0, j = 0, k;
11308 for (tree arg = DECL_ARGUMENTS (node->decl);
11309 arg;
11310 arg = DECL_CHAIN (arg), i++, j++)
11312 if (adjustments[j].op == IPA_PARM_OP_COPY)
11313 continue;
11315 node->simdclone->args[i].vector_arg = arg;
11317 tree array = node->simdclone->args[i].simd_array;
11318 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11320 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11321 tree ptr = build_fold_addr_expr (array);
11322 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11323 build_int_cst (ptype, 0));
11324 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11325 gimplify_and_add (t, &seq);
11327 else
11329 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11330 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11331 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11333 tree ptr = build_fold_addr_expr (array);
11334 int elemsize;
11335 if (k)
11337 arg = DECL_CHAIN (arg);
11338 j++;
11340 elemsize
11341 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11342 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11343 build_int_cst (ptype, k * elemsize));
11344 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11345 gimplify_and_add (t, &seq);
11349 return seq;
11352 /* Callback info for ipa_simd_modify_stmt_ops below. */
11354 struct modify_stmt_info {
11355 ipa_parm_adjustment_vec adjustments;
11356 gimple stmt;
11357 /* True if the parent statement was modified by
11358 ipa_simd_modify_stmt_ops. */
11359 bool modified;
11362 /* Callback for walk_gimple_op.
11364 Adjust operands from a given statement as specified in the
11365 adjustments vector in the callback data. */
11367 static tree
11368 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11370 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11371 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11372 tree *orig_tp = tp;
11373 if (TREE_CODE (*tp) == ADDR_EXPR)
11374 tp = &TREE_OPERAND (*tp, 0);
11375 struct ipa_parm_adjustment *cand = NULL;
11376 if (TREE_CODE (*tp) == PARM_DECL)
11377 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11378 else
11380 if (TYPE_P (*tp))
11381 *walk_subtrees = 0;
11384 tree repl = NULL_TREE;
11385 if (cand)
11386 repl = unshare_expr (cand->new_decl);
11387 else
11389 if (tp != orig_tp)
11391 *walk_subtrees = 0;
11392 bool modified = info->modified;
11393 info->modified = false;
11394 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11395 if (!info->modified)
11397 info->modified = modified;
11398 return NULL_TREE;
11400 info->modified = modified;
11401 repl = *tp;
11403 else
11404 return NULL_TREE;
11407 if (tp != orig_tp)
11409 repl = build_fold_addr_expr (repl);
11410 gimple stmt
11411 = gimple_build_assign (make_ssa_name (TREE_TYPE (repl), NULL), repl);
11412 repl = gimple_assign_lhs (stmt);
11413 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11414 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11415 *orig_tp = repl;
11417 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11419 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11420 *tp = vce;
11422 else
11423 *tp = repl;
11425 info->modified = true;
11426 return NULL_TREE;
11429 /* Traverse the function body and perform all modifications as
11430 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11431 modified such that the replacement/reduction value will now be an
11432 offset into the corresponding simd_array.
11434 This function will replace all function argument uses with their
11435 corresponding simd array elements, and ajust the return values
11436 accordingly. */
11438 static void
11439 ipa_simd_modify_function_body (struct cgraph_node *node,
11440 ipa_parm_adjustment_vec adjustments,
11441 tree retval_array, tree iter)
11443 basic_block bb;
11444 unsigned int i, j, l;
11446 /* Re-use the adjustments array, but this time use it to replace
11447 every function argument use to an offset into the corresponding
11448 simd_array. */
11449 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11451 if (!node->simdclone->args[i].vector_arg)
11452 continue;
11454 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11455 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11456 adjustments[j].new_decl
11457 = build4 (ARRAY_REF,
11458 basetype,
11459 node->simdclone->args[i].simd_array,
11460 iter,
11461 NULL_TREE, NULL_TREE);
11462 if (adjustments[j].op == IPA_PARM_OP_NONE
11463 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11464 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11467 l = adjustments.length ();
11468 for (i = 1; i < num_ssa_names; i++)
11470 tree name = ssa_name (i);
11471 if (name
11472 && SSA_NAME_VAR (name)
11473 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11475 for (j = 0; j < l; j++)
11476 if (SSA_NAME_VAR (name) == adjustments[j].base
11477 && adjustments[j].new_decl)
11479 tree base_var;
11480 if (adjustments[j].new_ssa_base == NULL_TREE)
11482 base_var
11483 = copy_var_decl (adjustments[j].base,
11484 DECL_NAME (adjustments[j].base),
11485 TREE_TYPE (adjustments[j].base));
11486 adjustments[j].new_ssa_base = base_var;
11488 else
11489 base_var = adjustments[j].new_ssa_base;
11490 if (SSA_NAME_IS_DEFAULT_DEF (name))
11492 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11493 gimple_stmt_iterator gsi = gsi_after_labels (bb);
11494 tree new_decl = unshare_expr (adjustments[j].new_decl);
11495 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
11496 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11497 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
11498 gimple stmt = gimple_build_assign (name, new_decl);
11499 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11501 else
11502 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11507 struct modify_stmt_info info;
11508 info.adjustments = adjustments;
11510 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
11512 gimple_stmt_iterator gsi;
11514 gsi = gsi_start_bb (bb);
11515 while (!gsi_end_p (gsi))
11517 gimple stmt = gsi_stmt (gsi);
11518 info.stmt = stmt;
11519 struct walk_stmt_info wi;
11521 memset (&wi, 0, sizeof (wi));
11522 info.modified = false;
11523 wi.info = &info;
11524 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
11526 if (gimple_code (stmt) == GIMPLE_RETURN)
11528 tree retval = gimple_return_retval (stmt);
11529 if (!retval)
11531 gsi_remove (&gsi, true);
11532 continue;
11535 /* Replace `return foo' with `retval_array[iter] = foo'. */
11536 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
11537 retval_array, iter, NULL, NULL);
11538 stmt = gimple_build_assign (ref, retval);
11539 gsi_replace (&gsi, stmt, true);
11540 info.modified = true;
11543 if (info.modified)
11545 update_stmt (stmt);
11546 if (maybe_clean_eh_stmt (stmt))
11547 gimple_purge_dead_eh_edges (gimple_bb (stmt));
11549 gsi_next (&gsi);
11554 /* Adjust the argument types in NODE to their appropriate vector
11555 counterparts. */
11557 static void
11558 simd_clone_adjust (struct cgraph_node *node)
11560 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
11562 targetm.simd_clone.adjust (node);
11564 tree retval = simd_clone_adjust_return_type (node);
11565 ipa_parm_adjustment_vec adjustments
11566 = simd_clone_adjust_argument_types (node);
11568 push_gimplify_context ();
11570 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
11572 /* Adjust all uses of vector arguments accordingly. Adjust all
11573 return values accordingly. */
11574 tree iter = create_tmp_var (unsigned_type_node, "iter");
11575 tree iter1 = make_ssa_name (iter, NULL);
11576 tree iter2 = make_ssa_name (iter, NULL);
11577 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
11579 /* Initialize the iteration variable. */
11580 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11581 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
11582 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
11583 /* Insert the SIMD array and iv initialization at function
11584 entry. */
11585 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
11587 pop_gimplify_context (NULL);
11589 /* Create a new BB right before the original exit BB, to hold the
11590 iteration increment and the condition/branch. */
11591 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
11592 basic_block incr_bb = create_empty_bb (orig_exit);
11593 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11594 flag. Set it now to be a FALLTHRU_EDGE. */
11595 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
11596 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
11597 for (unsigned i = 0;
11598 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
11600 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
11601 redirect_edge_succ (e, incr_bb);
11603 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
11604 e->probability = REG_BR_PROB_BASE;
11605 gsi = gsi_last_bb (incr_bb);
11606 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
11607 build_int_cst (unsigned_type_node,
11608 1));
11609 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11611 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
11612 struct loop *loop = alloc_loop ();
11613 cfun->has_force_vectorize_loops = true;
11614 loop->safelen = node->simdclone->simdlen;
11615 loop->force_vectorize = true;
11616 loop->header = body_bb;
11617 add_bb_to_loop (incr_bb, loop);
11619 /* Branch around the body if the mask applies. */
11620 if (node->simdclone->inbranch)
11622 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
11623 tree mask_array
11624 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
11625 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
11626 tree aref = build4 (ARRAY_REF,
11627 TREE_TYPE (TREE_TYPE (mask_array)),
11628 mask_array, iter1,
11629 NULL, NULL);
11630 g = gimple_build_assign (mask, aref);
11631 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11632 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
11633 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
11635 aref = build1 (VIEW_CONVERT_EXPR,
11636 build_nonstandard_integer_type (bitsize, 0), mask);
11637 mask = make_ssa_name (TREE_TYPE (aref), NULL);
11638 g = gimple_build_assign (mask, aref);
11639 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11642 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
11643 NULL, NULL);
11644 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11645 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
11646 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
11649 /* Generate the condition. */
11650 g = gimple_build_cond (LT_EXPR,
11651 iter2,
11652 build_int_cst (unsigned_type_node,
11653 node->simdclone->simdlen),
11654 NULL, NULL);
11655 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11656 e = split_block (incr_bb, gsi_stmt (gsi));
11657 basic_block latch_bb = e->dest;
11658 basic_block new_exit_bb = e->dest;
11659 new_exit_bb = split_block (latch_bb, NULL)->dest;
11660 loop->latch = latch_bb;
11662 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
11664 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
11665 /* The successor of incr_bb is already pointing to latch_bb; just
11666 change the flags.
11667 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
11668 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
11670 gimple phi = create_phi_node (iter1, body_bb);
11671 edge preheader_edge = find_edge (entry_bb, body_bb);
11672 edge latch_edge = single_succ_edge (latch_bb);
11673 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
11674 UNKNOWN_LOCATION);
11675 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11677 /* Generate the new return. */
11678 gsi = gsi_last_bb (new_exit_bb);
11679 if (retval
11680 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
11681 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
11682 retval = TREE_OPERAND (retval, 0);
11683 else if (retval)
11685 retval = build1 (VIEW_CONVERT_EXPR,
11686 TREE_TYPE (TREE_TYPE (node->decl)),
11687 retval);
11688 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
11689 false, GSI_CONTINUE_LINKING);
11691 g = gimple_build_return (retval);
11692 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11694 /* Handle aligned clauses by replacing default defs of the aligned
11695 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
11696 lhs. Handle linear by adding PHIs. */
11697 for (unsigned i = 0; i < node->simdclone->nargs; i++)
11698 if (node->simdclone->args[i].alignment
11699 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
11700 && (node->simdclone->args[i].alignment
11701 & (node->simdclone->args[i].alignment - 1)) == 0
11702 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
11703 == POINTER_TYPE)
11705 unsigned int alignment = node->simdclone->args[i].alignment;
11706 tree orig_arg = node->simdclone->args[i].orig_arg;
11707 tree def = ssa_default_def (cfun, orig_arg);
11708 if (def && !has_zero_uses (def))
11710 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
11711 gimple_seq seq = NULL;
11712 bool need_cvt = false;
11713 gimple call
11714 = gimple_build_call (fn, 2, def, size_int (alignment));
11715 g = call;
11716 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
11717 ptr_type_node))
11718 need_cvt = true;
11719 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
11720 gimple_call_set_lhs (g, t);
11721 gimple_seq_add_stmt_without_update (&seq, g);
11722 if (need_cvt)
11724 t = make_ssa_name (orig_arg, NULL);
11725 g = gimple_build_assign_with_ops (NOP_EXPR, t,
11726 gimple_call_lhs (g),
11727 NULL_TREE);
11728 gimple_seq_add_stmt_without_update (&seq, g);
11730 gsi_insert_seq_on_edge_immediate
11731 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
11733 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11734 int freq = compute_call_stmt_bb_frequency (current_function_decl,
11735 entry_bb);
11736 cgraph_create_edge (node, cgraph_get_create_node (fn),
11737 call, entry_bb->count, freq);
11739 imm_use_iterator iter;
11740 use_operand_p use_p;
11741 gimple use_stmt;
11742 tree repl = gimple_get_lhs (g);
11743 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11744 if (is_gimple_debug (use_stmt) || use_stmt == call)
11745 continue;
11746 else
11747 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11748 SET_USE (use_p, repl);
11751 else if (node->simdclone->args[i].arg_type
11752 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11754 tree orig_arg = node->simdclone->args[i].orig_arg;
11755 tree def = ssa_default_def (cfun, orig_arg);
11756 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11757 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
11758 if (def && !has_zero_uses (def))
11760 iter1 = make_ssa_name (orig_arg, NULL);
11761 iter2 = make_ssa_name (orig_arg, NULL);
11762 phi = create_phi_node (iter1, body_bb);
11763 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
11764 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11765 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11766 ? PLUS_EXPR : POINTER_PLUS_EXPR;
11767 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11768 ? TREE_TYPE (orig_arg) : sizetype;
11769 tree addcst
11770 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
11771 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
11772 gsi = gsi_last_bb (incr_bb);
11773 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
11775 imm_use_iterator iter;
11776 use_operand_p use_p;
11777 gimple use_stmt;
11778 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11779 if (use_stmt == phi)
11780 continue;
11781 else
11782 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11783 SET_USE (use_p, iter1);
11787 calculate_dominance_info (CDI_DOMINATORS);
11788 add_loop (loop, loop->header->loop_father);
11789 update_ssa (TODO_update_ssa);
11791 pop_cfun ();
11794 /* If the function in NODE is tagged as an elemental SIMD function,
11795 create the appropriate SIMD clones. */
11797 static void
11798 expand_simd_clones (struct cgraph_node *node)
11800 tree attr = lookup_attribute ("omp declare simd",
11801 DECL_ATTRIBUTES (node->decl));
11802 if (attr == NULL_TREE
11803 || node->global.inlined_to
11804 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
11805 return;
11807 /* Ignore
11808 #pragma omp declare simd
11809 extern int foo ();
11810 in C, there we don't know the argument types at all. */
11811 if (!node->definition
11812 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
11813 return;
11817 /* Start with parsing the "omp declare simd" attribute(s). */
11818 bool inbranch_clause_specified;
11819 struct cgraph_simd_clone *clone_info
11820 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
11821 &inbranch_clause_specified);
11822 if (clone_info == NULL)
11823 continue;
11825 int orig_simdlen = clone_info->simdlen;
11826 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
11827 /* The target can return 0 (no simd clones should be created),
11828 1 (just one ISA of simd clones should be created) or higher
11829 count of ISA variants. In that case, clone_info is initialized
11830 for the first ISA variant. */
11831 int count
11832 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
11833 base_type, 0);
11834 if (count == 0)
11835 continue;
11837 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
11838 also create one inbranch and one !inbranch clone of it. */
11839 for (int i = 0; i < count * 2; i++)
11841 struct cgraph_simd_clone *clone = clone_info;
11842 if (inbranch_clause_specified && (i & 1) != 0)
11843 continue;
11845 if (i != 0)
11847 clone = simd_clone_struct_alloc (clone_info->nargs
11848 + ((i & 1) != 0));
11849 simd_clone_struct_copy (clone, clone_info);
11850 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
11851 and simd_clone_adjust_argument_types did to the first
11852 clone's info. */
11853 clone->nargs -= clone_info->inbranch;
11854 clone->simdlen = orig_simdlen;
11855 /* And call the target hook again to get the right ISA. */
11856 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
11857 base_type,
11858 i / 2);
11859 if ((i & 1) != 0)
11860 clone->inbranch = 1;
11863 /* simd_clone_mangle might fail if such a clone has been created
11864 already. */
11865 tree id = simd_clone_mangle (node, clone);
11866 if (id == NULL_TREE)
11867 continue;
11869 /* Only when we are sure we want to create the clone actually
11870 clone the function (or definitions) or create another
11871 extern FUNCTION_DECL (for prototypes without definitions). */
11872 struct cgraph_node *n = simd_clone_create (node);
11873 if (n == NULL)
11874 continue;
11876 n->simdclone = clone;
11877 clone->origin = node;
11878 clone->next_clone = NULL;
11879 if (node->simd_clones == NULL)
11881 clone->prev_clone = n;
11882 node->simd_clones = n;
11884 else
11886 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
11887 clone->prev_clone->simdclone->next_clone = n;
11888 node->simd_clones->simdclone->prev_clone = n;
11890 change_decl_assembler_name (n->decl, id);
11891 /* And finally adjust the return type, parameters and for
11892 definitions also function body. */
11893 if (node->definition)
11894 simd_clone_adjust (n);
11895 else
11897 simd_clone_adjust_return_type (n);
11898 simd_clone_adjust_argument_types (n);
11902 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
11905 /* Entry point for IPA simd clone creation pass. */
11907 static unsigned int
11908 ipa_omp_simd_clone (void)
11910 struct cgraph_node *node;
11911 FOR_EACH_FUNCTION (node)
11912 expand_simd_clones (node);
11913 return 0;
11916 namespace {
11918 const pass_data pass_data_omp_simd_clone =
11920 SIMPLE_IPA_PASS, /* type */
11921 "simdclone", /* name */
11922 OPTGROUP_NONE, /* optinfo_flags */
11923 TV_NONE, /* tv_id */
11924 ( PROP_ssa | PROP_cfg ), /* properties_required */
11925 0, /* properties_provided */
11926 0, /* properties_destroyed */
11927 0, /* todo_flags_start */
11928 0, /* todo_flags_finish */
11931 class pass_omp_simd_clone : public simple_ipa_opt_pass
11933 public:
11934 pass_omp_simd_clone(gcc::context *ctxt)
11935 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
11938 /* opt_pass methods: */
11939 virtual bool gate (function *);
11940 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
11943 bool
11944 pass_omp_simd_clone::gate (function *)
11946 return ((flag_openmp || flag_openmp_simd
11947 || flag_cilkplus
11948 || (in_lto_p && !flag_wpa))
11949 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
11952 } // anon namespace
11954 simple_ipa_opt_pass *
11955 make_pass_omp_simd_clone (gcc::context *ctxt)
11957 return new pass_omp_simd_clone (ctxt);
11960 #include "gt-omp-low.h"