Compile gcc.target/i386/fuse-caller-save.c with -fomit-frame-pointer (PR target/61533)
[official-gcc.git] / gcc / omp-low.c
blob67254cc5bdf4c9cb9c18597118b0463b23951829
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 gcc_assert (!splay_tree_lookup (ctx->field_map,
1682 (splay_tree_key) decl));
1683 tree field
1684 = build_decl (OMP_CLAUSE_LOCATION (c),
1685 FIELD_DECL, NULL_TREE, ptr_type_node);
1686 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1687 insert_field_into_struct (ctx->record_type, field);
1688 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1689 (splay_tree_value) field);
1692 break;
1694 case OMP_CLAUSE_NOWAIT:
1695 case OMP_CLAUSE_ORDERED:
1696 case OMP_CLAUSE_COLLAPSE:
1697 case OMP_CLAUSE_UNTIED:
1698 case OMP_CLAUSE_MERGEABLE:
1699 case OMP_CLAUSE_PROC_BIND:
1700 case OMP_CLAUSE_SAFELEN:
1701 break;
1703 case OMP_CLAUSE_ALIGNED:
1704 decl = OMP_CLAUSE_DECL (c);
1705 if (is_global_var (decl)
1706 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1707 install_var_local (decl, ctx);
1708 break;
1710 default:
1711 gcc_unreachable ();
1715 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1717 switch (OMP_CLAUSE_CODE (c))
1719 case OMP_CLAUSE_LASTPRIVATE:
1720 /* Let the corresponding firstprivate clause create
1721 the variable. */
1722 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1723 scan_array_reductions = true;
1724 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1725 break;
1726 /* FALLTHRU */
1728 case OMP_CLAUSE_PRIVATE:
1729 case OMP_CLAUSE_FIRSTPRIVATE:
1730 case OMP_CLAUSE_REDUCTION:
1731 case OMP_CLAUSE_LINEAR:
1732 decl = OMP_CLAUSE_DECL (c);
1733 if (is_variable_sized (decl))
1734 install_var_local (decl, ctx);
1735 fixup_remapped_decl (decl, ctx,
1736 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1737 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1738 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1739 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1740 scan_array_reductions = true;
1741 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1742 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1743 scan_array_reductions = true;
1744 break;
1746 case OMP_CLAUSE_SHARED:
1747 /* Ignore shared directives in teams construct. */
1748 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1749 break;
1750 decl = OMP_CLAUSE_DECL (c);
1751 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1752 fixup_remapped_decl (decl, ctx, false);
1753 break;
1755 case OMP_CLAUSE_MAP:
1756 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1757 break;
1758 decl = OMP_CLAUSE_DECL (c);
1759 if (DECL_P (decl)
1760 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1761 && lookup_attribute ("omp declare target",
1762 DECL_ATTRIBUTES (decl)))
1763 break;
1764 if (DECL_P (decl))
1766 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1767 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1768 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1770 tree new_decl = lookup_decl (decl, ctx);
1771 TREE_TYPE (new_decl)
1772 = remap_type (TREE_TYPE (decl), &ctx->cb);
1774 else if (DECL_SIZE (decl)
1775 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1777 tree decl2 = DECL_VALUE_EXPR (decl);
1778 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1779 decl2 = TREE_OPERAND (decl2, 0);
1780 gcc_assert (DECL_P (decl2));
1781 fixup_remapped_decl (decl2, ctx, false);
1782 fixup_remapped_decl (decl, ctx, true);
1784 else
1785 fixup_remapped_decl (decl, ctx, false);
1787 break;
1789 case OMP_CLAUSE_COPYPRIVATE:
1790 case OMP_CLAUSE_COPYIN:
1791 case OMP_CLAUSE_DEFAULT:
1792 case OMP_CLAUSE_IF:
1793 case OMP_CLAUSE_NUM_THREADS:
1794 case OMP_CLAUSE_NUM_TEAMS:
1795 case OMP_CLAUSE_THREAD_LIMIT:
1796 case OMP_CLAUSE_DEVICE:
1797 case OMP_CLAUSE_SCHEDULE:
1798 case OMP_CLAUSE_DIST_SCHEDULE:
1799 case OMP_CLAUSE_NOWAIT:
1800 case OMP_CLAUSE_ORDERED:
1801 case OMP_CLAUSE_COLLAPSE:
1802 case OMP_CLAUSE_UNTIED:
1803 case OMP_CLAUSE_FINAL:
1804 case OMP_CLAUSE_MERGEABLE:
1805 case OMP_CLAUSE_PROC_BIND:
1806 case OMP_CLAUSE_SAFELEN:
1807 case OMP_CLAUSE_ALIGNED:
1808 case OMP_CLAUSE_DEPEND:
1809 case OMP_CLAUSE__LOOPTEMP_:
1810 case OMP_CLAUSE_TO:
1811 case OMP_CLAUSE_FROM:
1812 break;
1814 default:
1815 gcc_unreachable ();
1819 if (scan_array_reductions)
1820 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1821 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1822 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1824 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1825 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1827 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1828 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1829 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1830 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1831 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1832 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1835 /* Create a new name for omp child function. Returns an identifier. */
1837 static tree
1838 create_omp_child_function_name (bool task_copy)
1840 return (clone_function_name (current_function_decl,
1841 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1844 /* Build a decl for the omp child function. It'll not contain a body
1845 yet, just the bare decl. */
1847 static void
1848 create_omp_child_function (omp_context *ctx, bool task_copy)
1850 tree decl, type, name, t;
1852 name = create_omp_child_function_name (task_copy);
1853 if (task_copy)
1854 type = build_function_type_list (void_type_node, ptr_type_node,
1855 ptr_type_node, NULL_TREE);
1856 else
1857 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1859 decl = build_decl (gimple_location (ctx->stmt),
1860 FUNCTION_DECL, name, type);
1862 if (!task_copy)
1863 ctx->cb.dst_fn = decl;
1864 else
1865 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1867 TREE_STATIC (decl) = 1;
1868 TREE_USED (decl) = 1;
1869 DECL_ARTIFICIAL (decl) = 1;
1870 DECL_NAMELESS (decl) = 1;
1871 DECL_IGNORED_P (decl) = 0;
1872 TREE_PUBLIC (decl) = 0;
1873 DECL_UNINLINABLE (decl) = 1;
1874 DECL_EXTERNAL (decl) = 0;
1875 DECL_CONTEXT (decl) = NULL_TREE;
1876 DECL_INITIAL (decl) = make_node (BLOCK);
1877 bool target_p = false;
1878 if (lookup_attribute ("omp declare target",
1879 DECL_ATTRIBUTES (current_function_decl)))
1880 target_p = true;
1881 else
1883 omp_context *octx;
1884 for (octx = ctx; octx; octx = octx->outer)
1885 if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
1886 && gimple_omp_target_kind (octx->stmt)
1887 == GF_OMP_TARGET_KIND_REGION)
1889 target_p = true;
1890 break;
1893 if (target_p)
1894 DECL_ATTRIBUTES (decl)
1895 = tree_cons (get_identifier ("omp declare target"),
1896 NULL_TREE, DECL_ATTRIBUTES (decl));
1898 t = build_decl (DECL_SOURCE_LOCATION (decl),
1899 RESULT_DECL, NULL_TREE, void_type_node);
1900 DECL_ARTIFICIAL (t) = 1;
1901 DECL_IGNORED_P (t) = 1;
1902 DECL_CONTEXT (t) = decl;
1903 DECL_RESULT (decl) = t;
1905 t = build_decl (DECL_SOURCE_LOCATION (decl),
1906 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1907 DECL_ARTIFICIAL (t) = 1;
1908 DECL_NAMELESS (t) = 1;
1909 DECL_ARG_TYPE (t) = ptr_type_node;
1910 DECL_CONTEXT (t) = current_function_decl;
1911 TREE_USED (t) = 1;
1912 DECL_ARGUMENTS (decl) = t;
1913 if (!task_copy)
1914 ctx->receiver_decl = t;
1915 else
1917 t = build_decl (DECL_SOURCE_LOCATION (decl),
1918 PARM_DECL, get_identifier (".omp_data_o"),
1919 ptr_type_node);
1920 DECL_ARTIFICIAL (t) = 1;
1921 DECL_NAMELESS (t) = 1;
1922 DECL_ARG_TYPE (t) = ptr_type_node;
1923 DECL_CONTEXT (t) = current_function_decl;
1924 TREE_USED (t) = 1;
1925 TREE_ADDRESSABLE (t) = 1;
1926 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1927 DECL_ARGUMENTS (decl) = t;
1930 /* Allocate memory for the function structure. The call to
1931 allocate_struct_function clobbers CFUN, so we need to restore
1932 it afterward. */
1933 push_struct_function (decl);
1934 cfun->function_end_locus = gimple_location (ctx->stmt);
1935 pop_cfun ();
1938 /* Callback for walk_gimple_seq. Check if combined parallel
1939 contains gimple_omp_for_combined_into_p OMP_FOR. */
1941 static tree
1942 find_combined_for (gimple_stmt_iterator *gsi_p,
1943 bool *handled_ops_p,
1944 struct walk_stmt_info *wi)
1946 gimple stmt = gsi_stmt (*gsi_p);
1948 *handled_ops_p = true;
1949 switch (gimple_code (stmt))
1951 WALK_SUBSTMTS;
1953 case GIMPLE_OMP_FOR:
1954 if (gimple_omp_for_combined_into_p (stmt)
1955 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
1957 wi->info = stmt;
1958 return integer_zero_node;
1960 break;
1961 default:
1962 break;
1964 return NULL;
1967 /* Scan an OpenMP parallel directive. */
1969 static void
1970 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1972 omp_context *ctx;
1973 tree name;
1974 gimple stmt = gsi_stmt (*gsi);
1976 /* Ignore parallel directives with empty bodies, unless there
1977 are copyin clauses. */
1978 if (optimize > 0
1979 && empty_body_p (gimple_omp_body (stmt))
1980 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1981 OMP_CLAUSE_COPYIN) == NULL)
1983 gsi_replace (gsi, gimple_build_nop (), false);
1984 return;
1987 if (gimple_omp_parallel_combined_p (stmt))
1989 gimple for_stmt;
1990 struct walk_stmt_info wi;
1992 memset (&wi, 0, sizeof (wi));
1993 wi.val_only = true;
1994 walk_gimple_seq (gimple_omp_body (stmt),
1995 find_combined_for, NULL, &wi);
1996 for_stmt = (gimple) wi.info;
1997 if (for_stmt)
1999 struct omp_for_data fd;
2000 extract_omp_for_data (for_stmt, &fd, NULL);
2001 /* We need two temporaries with fd.loop.v type (istart/iend)
2002 and then (fd.collapse - 1) temporaries with the same
2003 type for count2 ... countN-1 vars if not constant. */
2004 size_t count = 2, i;
2005 tree type = fd.iter_type;
2006 if (fd.collapse > 1
2007 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2008 count += fd.collapse - 1;
2009 for (i = 0; i < count; i++)
2011 tree temp = create_tmp_var (type, NULL);
2012 tree c = build_omp_clause (UNKNOWN_LOCATION,
2013 OMP_CLAUSE__LOOPTEMP_);
2014 OMP_CLAUSE_DECL (c) = temp;
2015 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2016 gimple_omp_parallel_set_clauses (stmt, c);
2021 ctx = new_omp_context (stmt, outer_ctx);
2022 if (taskreg_nesting_level > 1)
2023 ctx->is_nested = true;
2024 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2025 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2026 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2027 name = create_tmp_var_name (".omp_data_s");
2028 name = build_decl (gimple_location (stmt),
2029 TYPE_DECL, name, ctx->record_type);
2030 DECL_ARTIFICIAL (name) = 1;
2031 DECL_NAMELESS (name) = 1;
2032 TYPE_NAME (ctx->record_type) = name;
2033 create_omp_child_function (ctx, false);
2034 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2036 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2037 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2039 if (TYPE_FIELDS (ctx->record_type) == NULL)
2040 ctx->record_type = ctx->receiver_decl = NULL;
2041 else
2043 layout_type (ctx->record_type);
2044 fixup_child_record_type (ctx);
2048 /* Scan an OpenMP task directive. */
2050 static void
2051 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2053 omp_context *ctx;
2054 tree name, t;
2055 gimple stmt = gsi_stmt (*gsi);
2056 location_t loc = gimple_location (stmt);
2058 /* Ignore task directives with empty bodies. */
2059 if (optimize > 0
2060 && empty_body_p (gimple_omp_body (stmt)))
2062 gsi_replace (gsi, gimple_build_nop (), false);
2063 return;
2066 ctx = new_omp_context (stmt, outer_ctx);
2067 if (taskreg_nesting_level > 1)
2068 ctx->is_nested = true;
2069 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2070 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2071 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2072 name = create_tmp_var_name (".omp_data_s");
2073 name = build_decl (gimple_location (stmt),
2074 TYPE_DECL, name, ctx->record_type);
2075 DECL_ARTIFICIAL (name) = 1;
2076 DECL_NAMELESS (name) = 1;
2077 TYPE_NAME (ctx->record_type) = name;
2078 create_omp_child_function (ctx, false);
2079 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2081 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2083 if (ctx->srecord_type)
2085 name = create_tmp_var_name (".omp_data_a");
2086 name = build_decl (gimple_location (stmt),
2087 TYPE_DECL, name, ctx->srecord_type);
2088 DECL_ARTIFICIAL (name) = 1;
2089 DECL_NAMELESS (name) = 1;
2090 TYPE_NAME (ctx->srecord_type) = name;
2091 create_omp_child_function (ctx, true);
2094 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2096 if (TYPE_FIELDS (ctx->record_type) == NULL)
2098 ctx->record_type = ctx->receiver_decl = NULL;
2099 t = build_int_cst (long_integer_type_node, 0);
2100 gimple_omp_task_set_arg_size (stmt, t);
2101 t = build_int_cst (long_integer_type_node, 1);
2102 gimple_omp_task_set_arg_align (stmt, t);
2104 else
2106 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2107 /* Move VLA fields to the end. */
2108 p = &TYPE_FIELDS (ctx->record_type);
2109 while (*p)
2110 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2111 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2113 *q = *p;
2114 *p = TREE_CHAIN (*p);
2115 TREE_CHAIN (*q) = NULL_TREE;
2116 q = &TREE_CHAIN (*q);
2118 else
2119 p = &DECL_CHAIN (*p);
2120 *p = vla_fields;
2121 layout_type (ctx->record_type);
2122 fixup_child_record_type (ctx);
2123 if (ctx->srecord_type)
2124 layout_type (ctx->srecord_type);
2125 t = fold_convert_loc (loc, long_integer_type_node,
2126 TYPE_SIZE_UNIT (ctx->record_type));
2127 gimple_omp_task_set_arg_size (stmt, t);
2128 t = build_int_cst (long_integer_type_node,
2129 TYPE_ALIGN_UNIT (ctx->record_type));
2130 gimple_omp_task_set_arg_align (stmt, t);
2135 /* Scan an OpenMP loop directive. */
2137 static void
2138 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2140 omp_context *ctx;
2141 size_t i;
2143 ctx = new_omp_context (stmt, outer_ctx);
2145 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2147 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2148 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2150 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2151 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2152 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2153 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2155 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2158 /* Scan an OpenMP sections directive. */
2160 static void
2161 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2163 omp_context *ctx;
2165 ctx = new_omp_context (stmt, outer_ctx);
2166 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2167 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2170 /* Scan an OpenMP single directive. */
2172 static void
2173 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2175 omp_context *ctx;
2176 tree name;
2178 ctx = new_omp_context (stmt, outer_ctx);
2179 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2180 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2181 name = create_tmp_var_name (".omp_copy_s");
2182 name = build_decl (gimple_location (stmt),
2183 TYPE_DECL, name, ctx->record_type);
2184 TYPE_NAME (ctx->record_type) = name;
2186 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2187 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2189 if (TYPE_FIELDS (ctx->record_type) == NULL)
2190 ctx->record_type = NULL;
2191 else
2192 layout_type (ctx->record_type);
2195 /* Scan an OpenMP target{, data, update} directive. */
2197 static void
2198 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2200 omp_context *ctx;
2201 tree name;
2202 int kind = gimple_omp_target_kind (stmt);
2204 ctx = new_omp_context (stmt, outer_ctx);
2205 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2206 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2207 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2208 name = create_tmp_var_name (".omp_data_t");
2209 name = build_decl (gimple_location (stmt),
2210 TYPE_DECL, name, ctx->record_type);
2211 DECL_ARTIFICIAL (name) = 1;
2212 DECL_NAMELESS (name) = 1;
2213 TYPE_NAME (ctx->record_type) = name;
2214 if (kind == GF_OMP_TARGET_KIND_REGION)
2216 create_omp_child_function (ctx, false);
2217 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2220 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2221 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2223 if (TYPE_FIELDS (ctx->record_type) == NULL)
2224 ctx->record_type = ctx->receiver_decl = NULL;
2225 else
2227 TYPE_FIELDS (ctx->record_type)
2228 = nreverse (TYPE_FIELDS (ctx->record_type));
2229 #ifdef ENABLE_CHECKING
2230 tree field;
2231 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2232 for (field = TYPE_FIELDS (ctx->record_type);
2233 field;
2234 field = DECL_CHAIN (field))
2235 gcc_assert (DECL_ALIGN (field) == align);
2236 #endif
2237 layout_type (ctx->record_type);
2238 if (kind == GF_OMP_TARGET_KIND_REGION)
2239 fixup_child_record_type (ctx);
2243 /* Scan an OpenMP teams directive. */
2245 static void
2246 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2248 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2249 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2250 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2253 /* Check OpenMP nesting restrictions. */
2254 static bool
2255 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2257 if (ctx != NULL)
2259 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2260 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2262 error_at (gimple_location (stmt),
2263 "OpenMP constructs may not be nested inside simd region");
2264 return false;
2266 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2268 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2269 || (gimple_omp_for_kind (stmt)
2270 != GF_OMP_FOR_KIND_DISTRIBUTE))
2271 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2273 error_at (gimple_location (stmt),
2274 "only distribute or parallel constructs are allowed to "
2275 "be closely nested inside teams construct");
2276 return false;
2280 switch (gimple_code (stmt))
2282 case GIMPLE_OMP_FOR:
2283 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2284 return true;
2285 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2287 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2289 error_at (gimple_location (stmt),
2290 "distribute construct must be closely nested inside "
2291 "teams construct");
2292 return false;
2294 return true;
2296 /* FALLTHRU */
2297 case GIMPLE_CALL:
2298 if (is_gimple_call (stmt)
2299 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2300 == BUILT_IN_GOMP_CANCEL
2301 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2302 == BUILT_IN_GOMP_CANCELLATION_POINT))
2304 const char *bad = NULL;
2305 const char *kind = NULL;
2306 if (ctx == NULL)
2308 error_at (gimple_location (stmt), "orphaned %qs construct",
2309 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2310 == BUILT_IN_GOMP_CANCEL
2311 ? "#pragma omp cancel"
2312 : "#pragma omp cancellation point");
2313 return false;
2315 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2316 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2317 : 0)
2319 case 1:
2320 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2321 bad = "#pragma omp parallel";
2322 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2323 == BUILT_IN_GOMP_CANCEL
2324 && !integer_zerop (gimple_call_arg (stmt, 1)))
2325 ctx->cancellable = true;
2326 kind = "parallel";
2327 break;
2328 case 2:
2329 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2330 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2331 bad = "#pragma omp for";
2332 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2333 == BUILT_IN_GOMP_CANCEL
2334 && !integer_zerop (gimple_call_arg (stmt, 1)))
2336 ctx->cancellable = true;
2337 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2338 OMP_CLAUSE_NOWAIT))
2339 warning_at (gimple_location (stmt), 0,
2340 "%<#pragma omp cancel for%> inside "
2341 "%<nowait%> for construct");
2342 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2343 OMP_CLAUSE_ORDERED))
2344 warning_at (gimple_location (stmt), 0,
2345 "%<#pragma omp cancel for%> inside "
2346 "%<ordered%> for construct");
2348 kind = "for";
2349 break;
2350 case 4:
2351 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2352 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2353 bad = "#pragma omp sections";
2354 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2355 == BUILT_IN_GOMP_CANCEL
2356 && !integer_zerop (gimple_call_arg (stmt, 1)))
2358 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2360 ctx->cancellable = true;
2361 if (find_omp_clause (gimple_omp_sections_clauses
2362 (ctx->stmt),
2363 OMP_CLAUSE_NOWAIT))
2364 warning_at (gimple_location (stmt), 0,
2365 "%<#pragma omp cancel sections%> inside "
2366 "%<nowait%> sections construct");
2368 else
2370 gcc_assert (ctx->outer
2371 && gimple_code (ctx->outer->stmt)
2372 == GIMPLE_OMP_SECTIONS);
2373 ctx->outer->cancellable = true;
2374 if (find_omp_clause (gimple_omp_sections_clauses
2375 (ctx->outer->stmt),
2376 OMP_CLAUSE_NOWAIT))
2377 warning_at (gimple_location (stmt), 0,
2378 "%<#pragma omp cancel sections%> inside "
2379 "%<nowait%> sections construct");
2382 kind = "sections";
2383 break;
2384 case 8:
2385 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2386 bad = "#pragma omp task";
2387 else
2388 ctx->cancellable = true;
2389 kind = "taskgroup";
2390 break;
2391 default:
2392 error_at (gimple_location (stmt), "invalid arguments");
2393 return false;
2395 if (bad)
2397 error_at (gimple_location (stmt),
2398 "%<%s %s%> construct not closely nested inside of %qs",
2399 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2400 == BUILT_IN_GOMP_CANCEL
2401 ? "#pragma omp cancel"
2402 : "#pragma omp cancellation point", kind, bad);
2403 return false;
2406 /* FALLTHRU */
2407 case GIMPLE_OMP_SECTIONS:
2408 case GIMPLE_OMP_SINGLE:
2409 for (; ctx != NULL; ctx = ctx->outer)
2410 switch (gimple_code (ctx->stmt))
2412 case GIMPLE_OMP_FOR:
2413 case GIMPLE_OMP_SECTIONS:
2414 case GIMPLE_OMP_SINGLE:
2415 case GIMPLE_OMP_ORDERED:
2416 case GIMPLE_OMP_MASTER:
2417 case GIMPLE_OMP_TASK:
2418 case GIMPLE_OMP_CRITICAL:
2419 if (is_gimple_call (stmt))
2421 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2422 != BUILT_IN_GOMP_BARRIER)
2423 return true;
2424 error_at (gimple_location (stmt),
2425 "barrier region may not be closely nested inside "
2426 "of work-sharing, critical, ordered, master or "
2427 "explicit task region");
2428 return false;
2430 error_at (gimple_location (stmt),
2431 "work-sharing region may not be closely nested inside "
2432 "of work-sharing, critical, ordered, master or explicit "
2433 "task region");
2434 return false;
2435 case GIMPLE_OMP_PARALLEL:
2436 return true;
2437 default:
2438 break;
2440 break;
2441 case GIMPLE_OMP_MASTER:
2442 for (; ctx != NULL; ctx = ctx->outer)
2443 switch (gimple_code (ctx->stmt))
2445 case GIMPLE_OMP_FOR:
2446 case GIMPLE_OMP_SECTIONS:
2447 case GIMPLE_OMP_SINGLE:
2448 case GIMPLE_OMP_TASK:
2449 error_at (gimple_location (stmt),
2450 "master region may not be closely nested inside "
2451 "of work-sharing or explicit task region");
2452 return false;
2453 case GIMPLE_OMP_PARALLEL:
2454 return true;
2455 default:
2456 break;
2458 break;
2459 case GIMPLE_OMP_ORDERED:
2460 for (; ctx != NULL; ctx = ctx->outer)
2461 switch (gimple_code (ctx->stmt))
2463 case GIMPLE_OMP_CRITICAL:
2464 case GIMPLE_OMP_TASK:
2465 error_at (gimple_location (stmt),
2466 "ordered region may not be closely nested inside "
2467 "of critical or explicit task region");
2468 return false;
2469 case GIMPLE_OMP_FOR:
2470 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2471 OMP_CLAUSE_ORDERED) == NULL)
2473 error_at (gimple_location (stmt),
2474 "ordered region must be closely nested inside "
2475 "a loop region with an ordered clause");
2476 return false;
2478 return true;
2479 case GIMPLE_OMP_PARALLEL:
2480 error_at (gimple_location (stmt),
2481 "ordered region must be closely nested inside "
2482 "a loop region with an ordered clause");
2483 return false;
2484 default:
2485 break;
2487 break;
2488 case GIMPLE_OMP_CRITICAL:
2489 for (; ctx != NULL; ctx = ctx->outer)
2490 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2491 && (gimple_omp_critical_name (stmt)
2492 == gimple_omp_critical_name (ctx->stmt)))
2494 error_at (gimple_location (stmt),
2495 "critical region may not be nested inside a critical "
2496 "region with the same name");
2497 return false;
2499 break;
2500 case GIMPLE_OMP_TEAMS:
2501 if (ctx == NULL
2502 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2503 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2505 error_at (gimple_location (stmt),
2506 "teams construct not closely nested inside of target "
2507 "region");
2508 return false;
2510 break;
2511 default:
2512 break;
2514 return true;
2518 /* Helper function scan_omp.
2520 Callback for walk_tree or operators in walk_gimple_stmt used to
2521 scan for OpenMP directives in TP. */
2523 static tree
2524 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2526 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2527 omp_context *ctx = (omp_context *) wi->info;
2528 tree t = *tp;
2530 switch (TREE_CODE (t))
2532 case VAR_DECL:
2533 case PARM_DECL:
2534 case LABEL_DECL:
2535 case RESULT_DECL:
2536 if (ctx)
2537 *tp = remap_decl (t, &ctx->cb);
2538 break;
2540 default:
2541 if (ctx && TYPE_P (t))
2542 *tp = remap_type (t, &ctx->cb);
2543 else if (!DECL_P (t))
2545 *walk_subtrees = 1;
2546 if (ctx)
2548 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2549 if (tem != TREE_TYPE (t))
2551 if (TREE_CODE (t) == INTEGER_CST)
2552 *tp = wide_int_to_tree (tem, t);
2553 else
2554 TREE_TYPE (t) = tem;
2558 break;
2561 return NULL_TREE;
2564 /* Return true if FNDECL is a setjmp or a longjmp. */
2566 static bool
2567 setjmp_or_longjmp_p (const_tree fndecl)
2569 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2570 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2571 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2572 return true;
2574 tree declname = DECL_NAME (fndecl);
2575 if (!declname)
2576 return false;
2577 const char *name = IDENTIFIER_POINTER (declname);
2578 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2582 /* Helper function for scan_omp.
2584 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2585 the current statement in GSI. */
2587 static tree
2588 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2589 struct walk_stmt_info *wi)
2591 gimple stmt = gsi_stmt (*gsi);
2592 omp_context *ctx = (omp_context *) wi->info;
2594 if (gimple_has_location (stmt))
2595 input_location = gimple_location (stmt);
2597 /* Check the OpenMP nesting restrictions. */
2598 bool remove = false;
2599 if (is_gimple_omp (stmt))
2600 remove = !check_omp_nesting_restrictions (stmt, ctx);
2601 else if (is_gimple_call (stmt))
2603 tree fndecl = gimple_call_fndecl (stmt);
2604 if (fndecl)
2606 if (setjmp_or_longjmp_p (fndecl)
2607 && ctx
2608 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2609 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2611 remove = true;
2612 error_at (gimple_location (stmt),
2613 "setjmp/longjmp inside simd construct");
2615 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2616 switch (DECL_FUNCTION_CODE (fndecl))
2618 case BUILT_IN_GOMP_BARRIER:
2619 case BUILT_IN_GOMP_CANCEL:
2620 case BUILT_IN_GOMP_CANCELLATION_POINT:
2621 case BUILT_IN_GOMP_TASKYIELD:
2622 case BUILT_IN_GOMP_TASKWAIT:
2623 case BUILT_IN_GOMP_TASKGROUP_START:
2624 case BUILT_IN_GOMP_TASKGROUP_END:
2625 remove = !check_omp_nesting_restrictions (stmt, ctx);
2626 break;
2627 default:
2628 break;
2632 if (remove)
2634 stmt = gimple_build_nop ();
2635 gsi_replace (gsi, stmt, false);
2638 *handled_ops_p = true;
2640 switch (gimple_code (stmt))
2642 case GIMPLE_OMP_PARALLEL:
2643 taskreg_nesting_level++;
2644 scan_omp_parallel (gsi, ctx);
2645 taskreg_nesting_level--;
2646 break;
2648 case GIMPLE_OMP_TASK:
2649 taskreg_nesting_level++;
2650 scan_omp_task (gsi, ctx);
2651 taskreg_nesting_level--;
2652 break;
2654 case GIMPLE_OMP_FOR:
2655 scan_omp_for (stmt, ctx);
2656 break;
2658 case GIMPLE_OMP_SECTIONS:
2659 scan_omp_sections (stmt, ctx);
2660 break;
2662 case GIMPLE_OMP_SINGLE:
2663 scan_omp_single (stmt, ctx);
2664 break;
2666 case GIMPLE_OMP_SECTION:
2667 case GIMPLE_OMP_MASTER:
2668 case GIMPLE_OMP_TASKGROUP:
2669 case GIMPLE_OMP_ORDERED:
2670 case GIMPLE_OMP_CRITICAL:
2671 ctx = new_omp_context (stmt, ctx);
2672 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2673 break;
2675 case GIMPLE_OMP_TARGET:
2676 scan_omp_target (stmt, ctx);
2677 break;
2679 case GIMPLE_OMP_TEAMS:
2680 scan_omp_teams (stmt, ctx);
2681 break;
2683 case GIMPLE_BIND:
2685 tree var;
2687 *handled_ops_p = false;
2688 if (ctx)
2689 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2690 insert_decl_map (&ctx->cb, var, var);
2692 break;
2693 default:
2694 *handled_ops_p = false;
2695 break;
2698 return NULL_TREE;
2702 /* Scan all the statements starting at the current statement. CTX
2703 contains context information about the OpenMP directives and
2704 clauses found during the scan. */
2706 static void
2707 scan_omp (gimple_seq *body_p, omp_context *ctx)
2709 location_t saved_location;
2710 struct walk_stmt_info wi;
2712 memset (&wi, 0, sizeof (wi));
2713 wi.info = ctx;
2714 wi.want_locations = true;
2716 saved_location = input_location;
2717 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2718 input_location = saved_location;
2721 /* Re-gimplification and code generation routines. */
2723 /* Build a call to GOMP_barrier. */
2725 static gimple
2726 build_omp_barrier (tree lhs)
2728 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2729 : BUILT_IN_GOMP_BARRIER);
2730 gimple g = gimple_build_call (fndecl, 0);
2731 if (lhs)
2732 gimple_call_set_lhs (g, lhs);
2733 return g;
2736 /* If a context was created for STMT when it was scanned, return it. */
2738 static omp_context *
2739 maybe_lookup_ctx (gimple stmt)
2741 splay_tree_node n;
2742 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2743 return n ? (omp_context *) n->value : NULL;
2747 /* Find the mapping for DECL in CTX or the immediately enclosing
2748 context that has a mapping for DECL.
2750 If CTX is a nested parallel directive, we may have to use the decl
2751 mappings created in CTX's parent context. Suppose that we have the
2752 following parallel nesting (variable UIDs showed for clarity):
2754 iD.1562 = 0;
2755 #omp parallel shared(iD.1562) -> outer parallel
2756 iD.1562 = iD.1562 + 1;
2758 #omp parallel shared (iD.1562) -> inner parallel
2759 iD.1562 = iD.1562 - 1;
2761 Each parallel structure will create a distinct .omp_data_s structure
2762 for copying iD.1562 in/out of the directive:
2764 outer parallel .omp_data_s.1.i -> iD.1562
2765 inner parallel .omp_data_s.2.i -> iD.1562
2767 A shared variable mapping will produce a copy-out operation before
2768 the parallel directive and a copy-in operation after it. So, in
2769 this case we would have:
2771 iD.1562 = 0;
2772 .omp_data_o.1.i = iD.1562;
2773 #omp parallel shared(iD.1562) -> outer parallel
2774 .omp_data_i.1 = &.omp_data_o.1
2775 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2777 .omp_data_o.2.i = iD.1562; -> **
2778 #omp parallel shared(iD.1562) -> inner parallel
2779 .omp_data_i.2 = &.omp_data_o.2
2780 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2783 ** This is a problem. The symbol iD.1562 cannot be referenced
2784 inside the body of the outer parallel region. But since we are
2785 emitting this copy operation while expanding the inner parallel
2786 directive, we need to access the CTX structure of the outer
2787 parallel directive to get the correct mapping:
2789 .omp_data_o.2.i = .omp_data_i.1->i
2791 Since there may be other workshare or parallel directives enclosing
2792 the parallel directive, it may be necessary to walk up the context
2793 parent chain. This is not a problem in general because nested
2794 parallelism happens only rarely. */
2796 static tree
2797 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2799 tree t;
2800 omp_context *up;
2802 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2803 t = maybe_lookup_decl (decl, up);
2805 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2807 return t ? t : decl;
2811 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2812 in outer contexts. */
2814 static tree
2815 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2817 tree t = NULL;
2818 omp_context *up;
2820 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2821 t = maybe_lookup_decl (decl, up);
2823 return t ? t : decl;
2827 /* Construct the initialization value for reduction CLAUSE. */
2829 tree
2830 omp_reduction_init (tree clause, tree type)
2832 location_t loc = OMP_CLAUSE_LOCATION (clause);
2833 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2835 case PLUS_EXPR:
2836 case MINUS_EXPR:
2837 case BIT_IOR_EXPR:
2838 case BIT_XOR_EXPR:
2839 case TRUTH_OR_EXPR:
2840 case TRUTH_ORIF_EXPR:
2841 case TRUTH_XOR_EXPR:
2842 case NE_EXPR:
2843 return build_zero_cst (type);
2845 case MULT_EXPR:
2846 case TRUTH_AND_EXPR:
2847 case TRUTH_ANDIF_EXPR:
2848 case EQ_EXPR:
2849 return fold_convert_loc (loc, type, integer_one_node);
2851 case BIT_AND_EXPR:
2852 return fold_convert_loc (loc, type, integer_minus_one_node);
2854 case MAX_EXPR:
2855 if (SCALAR_FLOAT_TYPE_P (type))
2857 REAL_VALUE_TYPE max, min;
2858 if (HONOR_INFINITIES (TYPE_MODE (type)))
2860 real_inf (&max);
2861 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2863 else
2864 real_maxval (&min, 1, TYPE_MODE (type));
2865 return build_real (type, min);
2867 else
2869 gcc_assert (INTEGRAL_TYPE_P (type));
2870 return TYPE_MIN_VALUE (type);
2873 case MIN_EXPR:
2874 if (SCALAR_FLOAT_TYPE_P (type))
2876 REAL_VALUE_TYPE max;
2877 if (HONOR_INFINITIES (TYPE_MODE (type)))
2878 real_inf (&max);
2879 else
2880 real_maxval (&max, 0, TYPE_MODE (type));
2881 return build_real (type, max);
2883 else
2885 gcc_assert (INTEGRAL_TYPE_P (type));
2886 return TYPE_MAX_VALUE (type);
2889 default:
2890 gcc_unreachable ();
2894 /* Return alignment to be assumed for var in CLAUSE, which should be
2895 OMP_CLAUSE_ALIGNED. */
2897 static tree
2898 omp_clause_aligned_alignment (tree clause)
2900 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
2901 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
2903 /* Otherwise return implementation defined alignment. */
2904 unsigned int al = 1;
2905 enum machine_mode mode, vmode;
2906 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2907 if (vs)
2908 vs = 1 << floor_log2 (vs);
2909 static enum mode_class classes[]
2910 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
2911 for (int i = 0; i < 4; i += 2)
2912 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
2913 mode != VOIDmode;
2914 mode = GET_MODE_WIDER_MODE (mode))
2916 vmode = targetm.vectorize.preferred_simd_mode (mode);
2917 if (GET_MODE_CLASS (vmode) != classes[i + 1])
2918 continue;
2919 while (vs
2920 && GET_MODE_SIZE (vmode) < vs
2921 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
2922 vmode = GET_MODE_2XWIDER_MODE (vmode);
2924 tree type = lang_hooks.types.type_for_mode (mode, 1);
2925 if (type == NULL_TREE || TYPE_MODE (type) != mode)
2926 continue;
2927 type = build_vector_type (type, GET_MODE_SIZE (vmode)
2928 / GET_MODE_SIZE (mode));
2929 if (TYPE_MODE (type) != vmode)
2930 continue;
2931 if (TYPE_ALIGN_UNIT (type) > al)
2932 al = TYPE_ALIGN_UNIT (type);
2934 return build_int_cst (integer_type_node, al);
2937 /* Return maximum possible vectorization factor for the target. */
2939 static int
2940 omp_max_vf (void)
2942 if (!optimize
2943 || optimize_debug
2944 || !flag_tree_loop_optimize
2945 || (!flag_tree_loop_vectorize
2946 && (global_options_set.x_flag_tree_loop_vectorize
2947 || global_options_set.x_flag_tree_vectorize)))
2948 return 1;
2950 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2951 if (vs)
2953 vs = 1 << floor_log2 (vs);
2954 return vs;
2956 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
2957 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
2958 return GET_MODE_NUNITS (vqimode);
2959 return 1;
2962 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2963 privatization. */
2965 static bool
2966 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
2967 tree &idx, tree &lane, tree &ivar, tree &lvar)
2969 if (max_vf == 0)
2971 max_vf = omp_max_vf ();
2972 if (max_vf > 1)
2974 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2975 OMP_CLAUSE_SAFELEN);
2976 if (c
2977 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
2978 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
2980 if (max_vf > 1)
2982 idx = create_tmp_var (unsigned_type_node, NULL);
2983 lane = create_tmp_var (unsigned_type_node, NULL);
2986 if (max_vf == 1)
2987 return false;
2989 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
2990 tree avar = create_tmp_var_raw (atype, NULL);
2991 if (TREE_ADDRESSABLE (new_var))
2992 TREE_ADDRESSABLE (avar) = 1;
2993 DECL_ATTRIBUTES (avar)
2994 = tree_cons (get_identifier ("omp simd array"), NULL,
2995 DECL_ATTRIBUTES (avar));
2996 gimple_add_tmp_var (avar);
2997 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
2998 NULL_TREE, NULL_TREE);
2999 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3000 NULL_TREE, NULL_TREE);
3001 if (DECL_P (new_var))
3003 SET_DECL_VALUE_EXPR (new_var, lvar);
3004 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3006 return true;
3009 /* Helper function of lower_rec_input_clauses. For a reference
3010 in simd reduction, add an underlying variable it will reference. */
3012 static void
3013 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3015 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3016 if (TREE_CONSTANT (z))
3018 const char *name = NULL;
3019 if (DECL_NAME (new_vard))
3020 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3022 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3023 gimple_add_tmp_var (z);
3024 TREE_ADDRESSABLE (z) = 1;
3025 z = build_fold_addr_expr_loc (loc, z);
3026 gimplify_assign (new_vard, z, ilist);
3030 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3031 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3032 private variables. Initialization statements go in ILIST, while calls
3033 to destructors go in DLIST. */
3035 static void
3036 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3037 omp_context *ctx, struct omp_for_data *fd)
3039 tree c, dtor, copyin_seq, x, ptr;
3040 bool copyin_by_ref = false;
3041 bool lastprivate_firstprivate = false;
3042 bool reduction_omp_orig_ref = false;
3043 int pass;
3044 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3045 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3046 int max_vf = 0;
3047 tree lane = NULL_TREE, idx = NULL_TREE;
3048 tree ivar = NULL_TREE, lvar = NULL_TREE;
3049 gimple_seq llist[2] = { NULL, NULL };
3051 copyin_seq = NULL;
3053 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3054 with data sharing clauses referencing variable sized vars. That
3055 is unnecessarily hard to support and very unlikely to result in
3056 vectorized code anyway. */
3057 if (is_simd)
3058 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3059 switch (OMP_CLAUSE_CODE (c))
3061 case OMP_CLAUSE_REDUCTION:
3062 case OMP_CLAUSE_PRIVATE:
3063 case OMP_CLAUSE_FIRSTPRIVATE:
3064 case OMP_CLAUSE_LASTPRIVATE:
3065 case OMP_CLAUSE_LINEAR:
3066 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3067 max_vf = 1;
3068 break;
3069 default:
3070 continue;
3073 /* Do all the fixed sized types in the first pass, and the variable sized
3074 types in the second pass. This makes sure that the scalar arguments to
3075 the variable sized types are processed before we use them in the
3076 variable sized operations. */
3077 for (pass = 0; pass < 2; ++pass)
3079 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3081 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3082 tree var, new_var;
3083 bool by_ref;
3084 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3086 switch (c_kind)
3088 case OMP_CLAUSE_PRIVATE:
3089 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3090 continue;
3091 break;
3092 case OMP_CLAUSE_SHARED:
3093 /* Ignore shared directives in teams construct. */
3094 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3095 continue;
3096 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3098 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3099 continue;
3101 case OMP_CLAUSE_FIRSTPRIVATE:
3102 case OMP_CLAUSE_COPYIN:
3103 case OMP_CLAUSE_LINEAR:
3104 break;
3105 case OMP_CLAUSE_REDUCTION:
3106 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3107 reduction_omp_orig_ref = true;
3108 break;
3109 case OMP_CLAUSE__LOOPTEMP_:
3110 /* Handle _looptemp_ clauses only on parallel. */
3111 if (fd)
3112 continue;
3113 break;
3114 case OMP_CLAUSE_LASTPRIVATE:
3115 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3117 lastprivate_firstprivate = true;
3118 if (pass != 0)
3119 continue;
3121 /* Even without corresponding firstprivate, if
3122 decl is Fortran allocatable, it needs outer var
3123 reference. */
3124 else if (pass == 0
3125 && lang_hooks.decls.omp_private_outer_ref
3126 (OMP_CLAUSE_DECL (c)))
3127 lastprivate_firstprivate = true;
3128 break;
3129 case OMP_CLAUSE_ALIGNED:
3130 if (pass == 0)
3131 continue;
3132 var = OMP_CLAUSE_DECL (c);
3133 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3134 && !is_global_var (var))
3136 new_var = maybe_lookup_decl (var, ctx);
3137 if (new_var == NULL_TREE)
3138 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3139 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3140 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3141 omp_clause_aligned_alignment (c));
3142 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3143 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3144 gimplify_and_add (x, ilist);
3146 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3147 && is_global_var (var))
3149 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3150 new_var = lookup_decl (var, ctx);
3151 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3152 t = build_fold_addr_expr_loc (clause_loc, t);
3153 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3154 t = build_call_expr_loc (clause_loc, t2, 2, t,
3155 omp_clause_aligned_alignment (c));
3156 t = fold_convert_loc (clause_loc, ptype, t);
3157 x = create_tmp_var (ptype, NULL);
3158 t = build2 (MODIFY_EXPR, ptype, x, t);
3159 gimplify_and_add (t, ilist);
3160 t = build_simple_mem_ref_loc (clause_loc, x);
3161 SET_DECL_VALUE_EXPR (new_var, t);
3162 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3164 continue;
3165 default:
3166 continue;
3169 new_var = var = OMP_CLAUSE_DECL (c);
3170 if (c_kind != OMP_CLAUSE_COPYIN)
3171 new_var = lookup_decl (var, ctx);
3173 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3175 if (pass != 0)
3176 continue;
3178 else if (is_variable_sized (var))
3180 /* For variable sized types, we need to allocate the
3181 actual storage here. Call alloca and store the
3182 result in the pointer decl that we created elsewhere. */
3183 if (pass == 0)
3184 continue;
3186 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3188 gimple stmt;
3189 tree tmp, atmp;
3191 ptr = DECL_VALUE_EXPR (new_var);
3192 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3193 ptr = TREE_OPERAND (ptr, 0);
3194 gcc_assert (DECL_P (ptr));
3195 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3197 /* void *tmp = __builtin_alloca */
3198 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3199 stmt = gimple_build_call (atmp, 1, x);
3200 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3201 gimple_add_tmp_var (tmp);
3202 gimple_call_set_lhs (stmt, tmp);
3204 gimple_seq_add_stmt (ilist, stmt);
3206 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3207 gimplify_assign (ptr, x, ilist);
3210 else if (is_reference (var))
3212 /* For references that are being privatized for Fortran,
3213 allocate new backing storage for the new pointer
3214 variable. This allows us to avoid changing all the
3215 code that expects a pointer to something that expects
3216 a direct variable. */
3217 if (pass == 0)
3218 continue;
3220 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3221 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3223 x = build_receiver_ref (var, false, ctx);
3224 x = build_fold_addr_expr_loc (clause_loc, x);
3226 else if (TREE_CONSTANT (x))
3228 /* For reduction in SIMD loop, defer adding the
3229 initialization of the reference, because if we decide
3230 to use SIMD array for it, the initilization could cause
3231 expansion ICE. */
3232 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3233 x = NULL_TREE;
3234 else
3236 const char *name = NULL;
3237 if (DECL_NAME (var))
3238 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3240 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3241 name);
3242 gimple_add_tmp_var (x);
3243 TREE_ADDRESSABLE (x) = 1;
3244 x = build_fold_addr_expr_loc (clause_loc, x);
3247 else
3249 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3250 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3253 if (x)
3255 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3256 gimplify_assign (new_var, x, ilist);
3259 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3261 else if (c_kind == OMP_CLAUSE_REDUCTION
3262 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3264 if (pass == 0)
3265 continue;
3267 else if (pass != 0)
3268 continue;
3270 switch (OMP_CLAUSE_CODE (c))
3272 case OMP_CLAUSE_SHARED:
3273 /* Ignore shared directives in teams construct. */
3274 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3275 continue;
3276 /* Shared global vars are just accessed directly. */
3277 if (is_global_var (new_var))
3278 break;
3279 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3280 needs to be delayed until after fixup_child_record_type so
3281 that we get the correct type during the dereference. */
3282 by_ref = use_pointer_for_field (var, ctx);
3283 x = build_receiver_ref (var, by_ref, ctx);
3284 SET_DECL_VALUE_EXPR (new_var, x);
3285 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3287 /* ??? If VAR is not passed by reference, and the variable
3288 hasn't been initialized yet, then we'll get a warning for
3289 the store into the omp_data_s structure. Ideally, we'd be
3290 able to notice this and not store anything at all, but
3291 we're generating code too early. Suppress the warning. */
3292 if (!by_ref)
3293 TREE_NO_WARNING (var) = 1;
3294 break;
3296 case OMP_CLAUSE_LASTPRIVATE:
3297 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3298 break;
3299 /* FALLTHRU */
3301 case OMP_CLAUSE_PRIVATE:
3302 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3303 x = build_outer_var_ref (var, ctx);
3304 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3306 if (is_task_ctx (ctx))
3307 x = build_receiver_ref (var, false, ctx);
3308 else
3309 x = build_outer_var_ref (var, ctx);
3311 else
3312 x = NULL;
3313 do_private:
3314 tree nx;
3315 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3316 if (is_simd)
3318 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3319 if ((TREE_ADDRESSABLE (new_var) || nx || y
3320 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3321 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3322 idx, lane, ivar, lvar))
3324 if (nx)
3325 x = lang_hooks.decls.omp_clause_default_ctor
3326 (c, unshare_expr (ivar), x);
3327 if (nx && x)
3328 gimplify_and_add (x, &llist[0]);
3329 if (y)
3331 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3332 if (y)
3334 gimple_seq tseq = NULL;
3336 dtor = y;
3337 gimplify_stmt (&dtor, &tseq);
3338 gimple_seq_add_seq (&llist[1], tseq);
3341 break;
3344 if (nx)
3345 gimplify_and_add (nx, ilist);
3346 /* FALLTHRU */
3348 do_dtor:
3349 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3350 if (x)
3352 gimple_seq tseq = NULL;
3354 dtor = x;
3355 gimplify_stmt (&dtor, &tseq);
3356 gimple_seq_add_seq (dlist, tseq);
3358 break;
3360 case OMP_CLAUSE_LINEAR:
3361 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3362 goto do_firstprivate;
3363 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3364 x = NULL;
3365 else
3366 x = build_outer_var_ref (var, ctx);
3367 goto do_private;
3369 case OMP_CLAUSE_FIRSTPRIVATE:
3370 if (is_task_ctx (ctx))
3372 if (is_reference (var) || is_variable_sized (var))
3373 goto do_dtor;
3374 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3375 ctx))
3376 || use_pointer_for_field (var, NULL))
3378 x = build_receiver_ref (var, false, ctx);
3379 SET_DECL_VALUE_EXPR (new_var, x);
3380 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3381 goto do_dtor;
3384 do_firstprivate:
3385 x = build_outer_var_ref (var, ctx);
3386 if (is_simd)
3388 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3389 && gimple_omp_for_combined_into_p (ctx->stmt))
3391 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3392 ? sizetype : TREE_TYPE (x);
3393 tree t = fold_convert (stept,
3394 OMP_CLAUSE_LINEAR_STEP (c));
3395 tree c = find_omp_clause (clauses,
3396 OMP_CLAUSE__LOOPTEMP_);
3397 gcc_assert (c);
3398 tree l = OMP_CLAUSE_DECL (c);
3399 if (fd->collapse == 1)
3401 tree n1 = fd->loop.n1;
3402 tree step = fd->loop.step;
3403 tree itype = TREE_TYPE (l);
3404 if (POINTER_TYPE_P (itype))
3405 itype = signed_type_for (itype);
3406 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3407 if (TYPE_UNSIGNED (itype)
3408 && fd->loop.cond_code == GT_EXPR)
3409 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3410 fold_build1 (NEGATE_EXPR,
3411 itype, l),
3412 fold_build1 (NEGATE_EXPR,
3413 itype, step));
3414 else
3415 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3417 t = fold_build2 (MULT_EXPR, stept,
3418 fold_convert (stept, l), t);
3419 if (POINTER_TYPE_P (TREE_TYPE (x)))
3420 x = fold_build2 (POINTER_PLUS_EXPR,
3421 TREE_TYPE (x), x, t);
3422 else
3423 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3426 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3427 || TREE_ADDRESSABLE (new_var))
3428 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3429 idx, lane, ivar, lvar))
3431 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3433 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3434 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3435 gimplify_and_add (x, ilist);
3436 gimple_stmt_iterator gsi
3437 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3438 gimple g
3439 = gimple_build_assign (unshare_expr (lvar), iv);
3440 gsi_insert_before_without_update (&gsi, g,
3441 GSI_SAME_STMT);
3442 tree stept = POINTER_TYPE_P (TREE_TYPE (iv))
3443 ? sizetype : TREE_TYPE (iv);
3444 tree t = fold_convert (stept,
3445 OMP_CLAUSE_LINEAR_STEP (c));
3446 enum tree_code code = PLUS_EXPR;
3447 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3448 code = POINTER_PLUS_EXPR;
3449 g = gimple_build_assign_with_ops (code, iv, iv, t);
3450 gsi_insert_before_without_update (&gsi, g,
3451 GSI_SAME_STMT);
3452 break;
3454 x = lang_hooks.decls.omp_clause_copy_ctor
3455 (c, unshare_expr (ivar), x);
3456 gimplify_and_add (x, &llist[0]);
3457 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3458 if (x)
3460 gimple_seq tseq = NULL;
3462 dtor = x;
3463 gimplify_stmt (&dtor, &tseq);
3464 gimple_seq_add_seq (&llist[1], tseq);
3466 break;
3469 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3470 gimplify_and_add (x, ilist);
3471 goto do_dtor;
3473 case OMP_CLAUSE__LOOPTEMP_:
3474 gcc_assert (is_parallel_ctx (ctx));
3475 x = build_outer_var_ref (var, ctx);
3476 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3477 gimplify_and_add (x, ilist);
3478 break;
3480 case OMP_CLAUSE_COPYIN:
3481 by_ref = use_pointer_for_field (var, NULL);
3482 x = build_receiver_ref (var, by_ref, ctx);
3483 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3484 append_to_statement_list (x, &copyin_seq);
3485 copyin_by_ref |= by_ref;
3486 break;
3488 case OMP_CLAUSE_REDUCTION:
3489 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3491 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3492 gimple tseq;
3493 x = build_outer_var_ref (var, ctx);
3495 if (is_reference (var)
3496 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3497 TREE_TYPE (x)))
3498 x = build_fold_addr_expr_loc (clause_loc, x);
3499 SET_DECL_VALUE_EXPR (placeholder, x);
3500 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3501 tree new_vard = new_var;
3502 if (is_reference (var))
3504 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3505 new_vard = TREE_OPERAND (new_var, 0);
3506 gcc_assert (DECL_P (new_vard));
3508 if (is_simd
3509 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3510 idx, lane, ivar, lvar))
3512 if (new_vard == new_var)
3514 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3515 SET_DECL_VALUE_EXPR (new_var, ivar);
3517 else
3519 SET_DECL_VALUE_EXPR (new_vard,
3520 build_fold_addr_expr (ivar));
3521 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3523 x = lang_hooks.decls.omp_clause_default_ctor
3524 (c, unshare_expr (ivar),
3525 build_outer_var_ref (var, ctx));
3526 if (x)
3527 gimplify_and_add (x, &llist[0]);
3528 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3530 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3531 lower_omp (&tseq, ctx);
3532 gimple_seq_add_seq (&llist[0], tseq);
3534 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3535 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3536 lower_omp (&tseq, ctx);
3537 gimple_seq_add_seq (&llist[1], tseq);
3538 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3539 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3540 if (new_vard == new_var)
3541 SET_DECL_VALUE_EXPR (new_var, lvar);
3542 else
3543 SET_DECL_VALUE_EXPR (new_vard,
3544 build_fold_addr_expr (lvar));
3545 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3546 if (x)
3548 tseq = NULL;
3549 dtor = x;
3550 gimplify_stmt (&dtor, &tseq);
3551 gimple_seq_add_seq (&llist[1], tseq);
3553 break;
3555 /* If this is a reference to constant size reduction var
3556 with placeholder, we haven't emitted the initializer
3557 for it because it is undesirable if SIMD arrays are used.
3558 But if they aren't used, we need to emit the deferred
3559 initialization now. */
3560 else if (is_reference (var) && is_simd)
3561 handle_simd_reference (clause_loc, new_vard, ilist);
3562 x = lang_hooks.decls.omp_clause_default_ctor
3563 (c, unshare_expr (new_var),
3564 build_outer_var_ref (var, ctx));
3565 if (x)
3566 gimplify_and_add (x, ilist);
3567 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3569 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3570 lower_omp (&tseq, ctx);
3571 gimple_seq_add_seq (ilist, tseq);
3573 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3574 if (is_simd)
3576 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3577 lower_omp (&tseq, ctx);
3578 gimple_seq_add_seq (dlist, tseq);
3579 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3581 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3582 goto do_dtor;
3584 else
3586 x = omp_reduction_init (c, TREE_TYPE (new_var));
3587 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3588 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3590 /* reduction(-:var) sums up the partial results, so it
3591 acts identically to reduction(+:var). */
3592 if (code == MINUS_EXPR)
3593 code = PLUS_EXPR;
3595 tree new_vard = new_var;
3596 if (is_simd && is_reference (var))
3598 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3599 new_vard = TREE_OPERAND (new_var, 0);
3600 gcc_assert (DECL_P (new_vard));
3602 if (is_simd
3603 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3604 idx, lane, ivar, lvar))
3606 tree ref = build_outer_var_ref (var, ctx);
3608 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3610 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3611 ref = build_outer_var_ref (var, ctx);
3612 gimplify_assign (ref, x, &llist[1]);
3614 if (new_vard != new_var)
3616 SET_DECL_VALUE_EXPR (new_vard,
3617 build_fold_addr_expr (lvar));
3618 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3621 else
3623 if (is_reference (var) && is_simd)
3624 handle_simd_reference (clause_loc, new_vard, ilist);
3625 gimplify_assign (new_var, x, ilist);
3626 if (is_simd)
3628 tree ref = build_outer_var_ref (var, ctx);
3630 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3631 ref = build_outer_var_ref (var, ctx);
3632 gimplify_assign (ref, x, dlist);
3636 break;
3638 default:
3639 gcc_unreachable ();
3644 if (lane)
3646 tree uid = create_tmp_var (ptr_type_node, "simduid");
3647 /* Don't want uninit warnings on simduid, it is always uninitialized,
3648 but we use it not for the value, but for the DECL_UID only. */
3649 TREE_NO_WARNING (uid) = 1;
3650 gimple g
3651 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3652 gimple_call_set_lhs (g, lane);
3653 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3654 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3655 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3656 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3657 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3658 gimple_omp_for_set_clauses (ctx->stmt, c);
3659 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3660 build_int_cst (unsigned_type_node, 0),
3661 NULL_TREE);
3662 gimple_seq_add_stmt (ilist, g);
3663 for (int i = 0; i < 2; i++)
3664 if (llist[i])
3666 tree vf = create_tmp_var (unsigned_type_node, NULL);
3667 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3668 gimple_call_set_lhs (g, vf);
3669 gimple_seq *seq = i == 0 ? ilist : dlist;
3670 gimple_seq_add_stmt (seq, g);
3671 tree t = build_int_cst (unsigned_type_node, 0);
3672 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3673 gimple_seq_add_stmt (seq, g);
3674 tree body = create_artificial_label (UNKNOWN_LOCATION);
3675 tree header = create_artificial_label (UNKNOWN_LOCATION);
3676 tree end = create_artificial_label (UNKNOWN_LOCATION);
3677 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3678 gimple_seq_add_stmt (seq, gimple_build_label (body));
3679 gimple_seq_add_seq (seq, llist[i]);
3680 t = build_int_cst (unsigned_type_node, 1);
3681 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3682 gimple_seq_add_stmt (seq, g);
3683 gimple_seq_add_stmt (seq, gimple_build_label (header));
3684 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3685 gimple_seq_add_stmt (seq, g);
3686 gimple_seq_add_stmt (seq, gimple_build_label (end));
3690 /* The copyin sequence is not to be executed by the main thread, since
3691 that would result in self-copies. Perhaps not visible to scalars,
3692 but it certainly is to C++ operator=. */
3693 if (copyin_seq)
3695 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3697 x = build2 (NE_EXPR, boolean_type_node, x,
3698 build_int_cst (TREE_TYPE (x), 0));
3699 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3700 gimplify_and_add (x, ilist);
3703 /* If any copyin variable is passed by reference, we must ensure the
3704 master thread doesn't modify it before it is copied over in all
3705 threads. Similarly for variables in both firstprivate and
3706 lastprivate clauses we need to ensure the lastprivate copying
3707 happens after firstprivate copying in all threads. And similarly
3708 for UDRs if initializer expression refers to omp_orig. */
3709 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3711 /* Don't add any barrier for #pragma omp simd or
3712 #pragma omp distribute. */
3713 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3714 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3715 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3718 /* If max_vf is non-zero, then we can use only a vectorization factor
3719 up to the max_vf we chose. So stick it into the safelen clause. */
3720 if (max_vf)
3722 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3723 OMP_CLAUSE_SAFELEN);
3724 if (c == NULL_TREE
3725 || compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3726 max_vf) == 1)
3728 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3729 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3730 max_vf);
3731 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3732 gimple_omp_for_set_clauses (ctx->stmt, c);
3738 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3739 both parallel and workshare constructs. PREDICATE may be NULL if it's
3740 always true. */
3742 static void
3743 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3744 omp_context *ctx)
3746 tree x, c, label = NULL, orig_clauses = clauses;
3747 bool par_clauses = false;
3748 tree simduid = NULL, lastlane = NULL;
3750 /* Early exit if there are no lastprivate or linear clauses. */
3751 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3752 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3753 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3754 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3755 break;
3756 if (clauses == NULL)
3758 /* If this was a workshare clause, see if it had been combined
3759 with its parallel. In that case, look for the clauses on the
3760 parallel statement itself. */
3761 if (is_parallel_ctx (ctx))
3762 return;
3764 ctx = ctx->outer;
3765 if (ctx == NULL || !is_parallel_ctx (ctx))
3766 return;
3768 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3769 OMP_CLAUSE_LASTPRIVATE);
3770 if (clauses == NULL)
3771 return;
3772 par_clauses = true;
3775 if (predicate)
3777 gimple stmt;
3778 tree label_true, arm1, arm2;
3780 label = create_artificial_label (UNKNOWN_LOCATION);
3781 label_true = create_artificial_label (UNKNOWN_LOCATION);
3782 arm1 = TREE_OPERAND (predicate, 0);
3783 arm2 = TREE_OPERAND (predicate, 1);
3784 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3785 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3786 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3787 label_true, label);
3788 gimple_seq_add_stmt (stmt_list, stmt);
3789 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3792 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3793 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3795 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3796 if (simduid)
3797 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3800 for (c = clauses; c ;)
3802 tree var, new_var;
3803 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3805 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3806 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3807 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3809 var = OMP_CLAUSE_DECL (c);
3810 new_var = lookup_decl (var, ctx);
3812 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3814 tree val = DECL_VALUE_EXPR (new_var);
3815 if (TREE_CODE (val) == ARRAY_REF
3816 && VAR_P (TREE_OPERAND (val, 0))
3817 && lookup_attribute ("omp simd array",
3818 DECL_ATTRIBUTES (TREE_OPERAND (val,
3819 0))))
3821 if (lastlane == NULL)
3823 lastlane = create_tmp_var (unsigned_type_node, NULL);
3824 gimple g
3825 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
3826 2, simduid,
3827 TREE_OPERAND (val, 1));
3828 gimple_call_set_lhs (g, lastlane);
3829 gimple_seq_add_stmt (stmt_list, g);
3831 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
3832 TREE_OPERAND (val, 0), lastlane,
3833 NULL_TREE, NULL_TREE);
3837 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3838 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
3840 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
3841 gimple_seq_add_seq (stmt_list,
3842 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3843 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
3845 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3846 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
3848 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
3849 gimple_seq_add_seq (stmt_list,
3850 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
3851 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
3854 x = build_outer_var_ref (var, ctx);
3855 if (is_reference (var))
3856 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3857 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
3858 gimplify_and_add (x, stmt_list);
3860 c = OMP_CLAUSE_CHAIN (c);
3861 if (c == NULL && !par_clauses)
3863 /* If this was a workshare clause, see if it had been combined
3864 with its parallel. In that case, continue looking for the
3865 clauses also on the parallel statement itself. */
3866 if (is_parallel_ctx (ctx))
3867 break;
3869 ctx = ctx->outer;
3870 if (ctx == NULL || !is_parallel_ctx (ctx))
3871 break;
3873 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3874 OMP_CLAUSE_LASTPRIVATE);
3875 par_clauses = true;
3879 if (label)
3880 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
3884 /* Generate code to implement the REDUCTION clauses. */
3886 static void
3887 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
3889 gimple_seq sub_seq = NULL;
3890 gimple stmt;
3891 tree x, c;
3892 int count = 0;
3894 /* SIMD reductions are handled in lower_rec_input_clauses. */
3895 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3896 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3897 return;
3899 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3900 update in that case, otherwise use a lock. */
3901 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
3902 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
3904 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3906 /* Never use OMP_ATOMIC for array reductions or UDRs. */
3907 count = -1;
3908 break;
3910 count++;
3913 if (count == 0)
3914 return;
3916 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3918 tree var, ref, new_var;
3919 enum tree_code code;
3920 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3922 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
3923 continue;
3925 var = OMP_CLAUSE_DECL (c);
3926 new_var = lookup_decl (var, ctx);
3927 if (is_reference (var))
3928 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3929 ref = build_outer_var_ref (var, ctx);
3930 code = OMP_CLAUSE_REDUCTION_CODE (c);
3932 /* reduction(-:var) sums up the partial results, so it acts
3933 identically to reduction(+:var). */
3934 if (code == MINUS_EXPR)
3935 code = PLUS_EXPR;
3937 if (count == 1)
3939 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
3941 addr = save_expr (addr);
3942 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
3943 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
3944 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
3945 gimplify_and_add (x, stmt_seqp);
3946 return;
3949 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3951 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3953 if (is_reference (var)
3954 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3955 TREE_TYPE (ref)))
3956 ref = build_fold_addr_expr_loc (clause_loc, ref);
3957 SET_DECL_VALUE_EXPR (placeholder, ref);
3958 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3959 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
3960 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
3961 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3962 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
3964 else
3966 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3967 ref = build_outer_var_ref (var, ctx);
3968 gimplify_assign (ref, x, &sub_seq);
3972 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
3974 gimple_seq_add_stmt (stmt_seqp, stmt);
3976 gimple_seq_add_seq (stmt_seqp, sub_seq);
3978 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
3980 gimple_seq_add_stmt (stmt_seqp, stmt);
3984 /* Generate code to implement the COPYPRIVATE clauses. */
3986 static void
3987 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
3988 omp_context *ctx)
3990 tree c;
3992 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3994 tree var, new_var, ref, x;
3995 bool by_ref;
3996 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3998 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
3999 continue;
4001 var = OMP_CLAUSE_DECL (c);
4002 by_ref = use_pointer_for_field (var, NULL);
4004 ref = build_sender_ref (var, ctx);
4005 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4006 if (by_ref)
4008 x = build_fold_addr_expr_loc (clause_loc, new_var);
4009 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4011 gimplify_assign (ref, x, slist);
4013 ref = build_receiver_ref (var, false, ctx);
4014 if (by_ref)
4016 ref = fold_convert_loc (clause_loc,
4017 build_pointer_type (TREE_TYPE (new_var)),
4018 ref);
4019 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4021 if (is_reference (var))
4023 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4024 ref = build_simple_mem_ref_loc (clause_loc, ref);
4025 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4027 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4028 gimplify_and_add (x, rlist);
4033 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4034 and REDUCTION from the sender (aka parent) side. */
4036 static void
4037 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4038 omp_context *ctx)
4040 tree c;
4042 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4044 tree val, ref, x, var;
4045 bool by_ref, do_in = false, do_out = false;
4046 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4048 switch (OMP_CLAUSE_CODE (c))
4050 case OMP_CLAUSE_PRIVATE:
4051 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4052 break;
4053 continue;
4054 case OMP_CLAUSE_FIRSTPRIVATE:
4055 case OMP_CLAUSE_COPYIN:
4056 case OMP_CLAUSE_LASTPRIVATE:
4057 case OMP_CLAUSE_REDUCTION:
4058 case OMP_CLAUSE__LOOPTEMP_:
4059 break;
4060 default:
4061 continue;
4064 val = OMP_CLAUSE_DECL (c);
4065 var = lookup_decl_in_outer_ctx (val, ctx);
4067 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4068 && is_global_var (var))
4069 continue;
4070 if (is_variable_sized (val))
4071 continue;
4072 by_ref = use_pointer_for_field (val, NULL);
4074 switch (OMP_CLAUSE_CODE (c))
4076 case OMP_CLAUSE_PRIVATE:
4077 case OMP_CLAUSE_FIRSTPRIVATE:
4078 case OMP_CLAUSE_COPYIN:
4079 case OMP_CLAUSE__LOOPTEMP_:
4080 do_in = true;
4081 break;
4083 case OMP_CLAUSE_LASTPRIVATE:
4084 if (by_ref || is_reference (val))
4086 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4087 continue;
4088 do_in = true;
4090 else
4092 do_out = true;
4093 if (lang_hooks.decls.omp_private_outer_ref (val))
4094 do_in = true;
4096 break;
4098 case OMP_CLAUSE_REDUCTION:
4099 do_in = true;
4100 do_out = !(by_ref || is_reference (val));
4101 break;
4103 default:
4104 gcc_unreachable ();
4107 if (do_in)
4109 ref = build_sender_ref (val, ctx);
4110 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4111 gimplify_assign (ref, x, ilist);
4112 if (is_task_ctx (ctx))
4113 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4116 if (do_out)
4118 ref = build_sender_ref (val, ctx);
4119 gimplify_assign (var, ref, olist);
4124 /* Generate code to implement SHARED from the sender (aka parent)
4125 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4126 list things that got automatically shared. */
4128 static void
4129 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4131 tree var, ovar, nvar, f, x, record_type;
4133 if (ctx->record_type == NULL)
4134 return;
4136 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4137 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4139 ovar = DECL_ABSTRACT_ORIGIN (f);
4140 nvar = maybe_lookup_decl (ovar, ctx);
4141 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4142 continue;
4144 /* If CTX is a nested parallel directive. Find the immediately
4145 enclosing parallel or workshare construct that contains a
4146 mapping for OVAR. */
4147 var = lookup_decl_in_outer_ctx (ovar, ctx);
4149 if (use_pointer_for_field (ovar, ctx))
4151 x = build_sender_ref (ovar, ctx);
4152 var = build_fold_addr_expr (var);
4153 gimplify_assign (x, var, ilist);
4155 else
4157 x = build_sender_ref (ovar, ctx);
4158 gimplify_assign (x, var, ilist);
4160 if (!TREE_READONLY (var)
4161 /* We don't need to receive a new reference to a result
4162 or parm decl. In fact we may not store to it as we will
4163 invalidate any pending RSO and generate wrong gimple
4164 during inlining. */
4165 && !((TREE_CODE (var) == RESULT_DECL
4166 || TREE_CODE (var) == PARM_DECL)
4167 && DECL_BY_REFERENCE (var)))
4169 x = build_sender_ref (ovar, ctx);
4170 gimplify_assign (var, x, olist);
4177 /* A convenience function to build an empty GIMPLE_COND with just the
4178 condition. */
4180 static gimple
4181 gimple_build_cond_empty (tree cond)
4183 enum tree_code pred_code;
4184 tree lhs, rhs;
4186 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4187 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4191 /* Build the function calls to GOMP_parallel_start etc to actually
4192 generate the parallel operation. REGION is the parallel region
4193 being expanded. BB is the block where to insert the code. WS_ARGS
4194 will be set if this is a call to a combined parallel+workshare
4195 construct, it contains the list of additional arguments needed by
4196 the workshare construct. */
4198 static void
4199 expand_parallel_call (struct omp_region *region, basic_block bb,
4200 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4202 tree t, t1, t2, val, cond, c, clauses, flags;
4203 gimple_stmt_iterator gsi;
4204 gimple stmt;
4205 enum built_in_function start_ix;
4206 int start_ix2;
4207 location_t clause_loc;
4208 vec<tree, va_gc> *args;
4210 clauses = gimple_omp_parallel_clauses (entry_stmt);
4212 /* Determine what flavor of GOMP_parallel we will be
4213 emitting. */
4214 start_ix = BUILT_IN_GOMP_PARALLEL;
4215 if (is_combined_parallel (region))
4217 switch (region->inner->type)
4219 case GIMPLE_OMP_FOR:
4220 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4221 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4222 + (region->inner->sched_kind
4223 == OMP_CLAUSE_SCHEDULE_RUNTIME
4224 ? 3 : region->inner->sched_kind));
4225 start_ix = (enum built_in_function)start_ix2;
4226 break;
4227 case GIMPLE_OMP_SECTIONS:
4228 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4229 break;
4230 default:
4231 gcc_unreachable ();
4235 /* By default, the value of NUM_THREADS is zero (selected at run time)
4236 and there is no conditional. */
4237 cond = NULL_TREE;
4238 val = build_int_cst (unsigned_type_node, 0);
4239 flags = build_int_cst (unsigned_type_node, 0);
4241 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4242 if (c)
4243 cond = OMP_CLAUSE_IF_EXPR (c);
4245 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4246 if (c)
4248 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4249 clause_loc = OMP_CLAUSE_LOCATION (c);
4251 else
4252 clause_loc = gimple_location (entry_stmt);
4254 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4255 if (c)
4256 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4258 /* Ensure 'val' is of the correct type. */
4259 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4261 /* If we found the clause 'if (cond)', build either
4262 (cond != 0) or (cond ? val : 1u). */
4263 if (cond)
4265 cond = gimple_boolify (cond);
4267 if (integer_zerop (val))
4268 val = fold_build2_loc (clause_loc,
4269 EQ_EXPR, unsigned_type_node, cond,
4270 build_int_cst (TREE_TYPE (cond), 0));
4271 else
4273 basic_block cond_bb, then_bb, else_bb;
4274 edge e, e_then, e_else;
4275 tree tmp_then, tmp_else, tmp_join, tmp_var;
4277 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4278 if (gimple_in_ssa_p (cfun))
4280 tmp_then = make_ssa_name (tmp_var, NULL);
4281 tmp_else = make_ssa_name (tmp_var, NULL);
4282 tmp_join = make_ssa_name (tmp_var, NULL);
4284 else
4286 tmp_then = tmp_var;
4287 tmp_else = tmp_var;
4288 tmp_join = tmp_var;
4291 e = split_block (bb, NULL);
4292 cond_bb = e->src;
4293 bb = e->dest;
4294 remove_edge (e);
4296 then_bb = create_empty_bb (cond_bb);
4297 else_bb = create_empty_bb (then_bb);
4298 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4299 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4301 stmt = gimple_build_cond_empty (cond);
4302 gsi = gsi_start_bb (cond_bb);
4303 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4305 gsi = gsi_start_bb (then_bb);
4306 stmt = gimple_build_assign (tmp_then, val);
4307 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4309 gsi = gsi_start_bb (else_bb);
4310 stmt = gimple_build_assign
4311 (tmp_else, build_int_cst (unsigned_type_node, 1));
4312 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4314 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4315 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4316 add_bb_to_loop (then_bb, cond_bb->loop_father);
4317 add_bb_to_loop (else_bb, cond_bb->loop_father);
4318 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4319 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4321 if (gimple_in_ssa_p (cfun))
4323 gimple phi = create_phi_node (tmp_join, bb);
4324 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4325 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4328 val = tmp_join;
4331 gsi = gsi_start_bb (bb);
4332 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4333 false, GSI_CONTINUE_LINKING);
4336 gsi = gsi_last_bb (bb);
4337 t = gimple_omp_parallel_data_arg (entry_stmt);
4338 if (t == NULL)
4339 t1 = null_pointer_node;
4340 else
4341 t1 = build_fold_addr_expr (t);
4342 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4344 vec_alloc (args, 4 + vec_safe_length (ws_args));
4345 args->quick_push (t2);
4346 args->quick_push (t1);
4347 args->quick_push (val);
4348 if (ws_args)
4349 args->splice (*ws_args);
4350 args->quick_push (flags);
4352 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4353 builtin_decl_explicit (start_ix), args);
4355 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4356 false, GSI_CONTINUE_LINKING);
4360 /* Build the function call to GOMP_task to actually
4361 generate the task operation. BB is the block where to insert the code. */
4363 static void
4364 expand_task_call (basic_block bb, gimple entry_stmt)
4366 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4367 gimple_stmt_iterator gsi;
4368 location_t loc = gimple_location (entry_stmt);
4370 clauses = gimple_omp_task_clauses (entry_stmt);
4372 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4373 if (c)
4374 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4375 else
4376 cond = boolean_true_node;
4378 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4379 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4380 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4381 flags = build_int_cst (unsigned_type_node,
4382 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4384 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4385 if (c)
4387 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4388 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4389 build_int_cst (unsigned_type_node, 2),
4390 build_int_cst (unsigned_type_node, 0));
4391 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4393 if (depend)
4394 depend = OMP_CLAUSE_DECL (depend);
4395 else
4396 depend = build_int_cst (ptr_type_node, 0);
4398 gsi = gsi_last_bb (bb);
4399 t = gimple_omp_task_data_arg (entry_stmt);
4400 if (t == NULL)
4401 t2 = null_pointer_node;
4402 else
4403 t2 = build_fold_addr_expr_loc (loc, t);
4404 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4405 t = gimple_omp_task_copy_fn (entry_stmt);
4406 if (t == NULL)
4407 t3 = null_pointer_node;
4408 else
4409 t3 = build_fold_addr_expr_loc (loc, t);
4411 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4412 8, t1, t2, t3,
4413 gimple_omp_task_arg_size (entry_stmt),
4414 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4415 depend);
4417 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4418 false, GSI_CONTINUE_LINKING);
4422 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4423 catch handler and return it. This prevents programs from violating the
4424 structured block semantics with throws. */
4426 static gimple_seq
4427 maybe_catch_exception (gimple_seq body)
4429 gimple g;
4430 tree decl;
4432 if (!flag_exceptions)
4433 return body;
4435 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4436 decl = lang_hooks.eh_protect_cleanup_actions ();
4437 else
4438 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4440 g = gimple_build_eh_must_not_throw (decl);
4441 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4442 GIMPLE_TRY_CATCH);
4444 return gimple_seq_alloc_with_stmt (g);
4447 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4449 static tree
4450 vec2chain (vec<tree, va_gc> *v)
4452 tree chain = NULL_TREE, t;
4453 unsigned ix;
4455 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4457 DECL_CHAIN (t) = chain;
4458 chain = t;
4461 return chain;
4465 /* Remove barriers in REGION->EXIT's block. Note that this is only
4466 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4467 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4468 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4469 removed. */
4471 static void
4472 remove_exit_barrier (struct omp_region *region)
4474 gimple_stmt_iterator gsi;
4475 basic_block exit_bb;
4476 edge_iterator ei;
4477 edge e;
4478 gimple stmt;
4479 int any_addressable_vars = -1;
4481 exit_bb = region->exit;
4483 /* If the parallel region doesn't return, we don't have REGION->EXIT
4484 block at all. */
4485 if (! exit_bb)
4486 return;
4488 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4489 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4490 statements that can appear in between are extremely limited -- no
4491 memory operations at all. Here, we allow nothing at all, so the
4492 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4493 gsi = gsi_last_bb (exit_bb);
4494 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4495 gsi_prev (&gsi);
4496 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4497 return;
4499 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4501 gsi = gsi_last_bb (e->src);
4502 if (gsi_end_p (gsi))
4503 continue;
4504 stmt = gsi_stmt (gsi);
4505 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4506 && !gimple_omp_return_nowait_p (stmt))
4508 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4509 in many cases. If there could be tasks queued, the barrier
4510 might be needed to let the tasks run before some local
4511 variable of the parallel that the task uses as shared
4512 runs out of scope. The task can be spawned either
4513 from within current function (this would be easy to check)
4514 or from some function it calls and gets passed an address
4515 of such a variable. */
4516 if (any_addressable_vars < 0)
4518 gimple parallel_stmt = last_stmt (region->entry);
4519 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4520 tree local_decls, block, decl;
4521 unsigned ix;
4523 any_addressable_vars = 0;
4524 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4525 if (TREE_ADDRESSABLE (decl))
4527 any_addressable_vars = 1;
4528 break;
4530 for (block = gimple_block (stmt);
4531 !any_addressable_vars
4532 && block
4533 && TREE_CODE (block) == BLOCK;
4534 block = BLOCK_SUPERCONTEXT (block))
4536 for (local_decls = BLOCK_VARS (block);
4537 local_decls;
4538 local_decls = DECL_CHAIN (local_decls))
4539 if (TREE_ADDRESSABLE (local_decls))
4541 any_addressable_vars = 1;
4542 break;
4544 if (block == gimple_block (parallel_stmt))
4545 break;
4548 if (!any_addressable_vars)
4549 gimple_omp_return_set_nowait (stmt);
4554 static void
4555 remove_exit_barriers (struct omp_region *region)
4557 if (region->type == GIMPLE_OMP_PARALLEL)
4558 remove_exit_barrier (region);
4560 if (region->inner)
4562 region = region->inner;
4563 remove_exit_barriers (region);
4564 while (region->next)
4566 region = region->next;
4567 remove_exit_barriers (region);
4572 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4573 calls. These can't be declared as const functions, but
4574 within one parallel body they are constant, so they can be
4575 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4576 which are declared const. Similarly for task body, except
4577 that in untied task omp_get_thread_num () can change at any task
4578 scheduling point. */
4580 static void
4581 optimize_omp_library_calls (gimple entry_stmt)
4583 basic_block bb;
4584 gimple_stmt_iterator gsi;
4585 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4586 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4587 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4588 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4589 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4590 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4591 OMP_CLAUSE_UNTIED) != NULL);
4593 FOR_EACH_BB_FN (bb, cfun)
4594 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4596 gimple call = gsi_stmt (gsi);
4597 tree decl;
4599 if (is_gimple_call (call)
4600 && (decl = gimple_call_fndecl (call))
4601 && DECL_EXTERNAL (decl)
4602 && TREE_PUBLIC (decl)
4603 && DECL_INITIAL (decl) == NULL)
4605 tree built_in;
4607 if (DECL_NAME (decl) == thr_num_id)
4609 /* In #pragma omp task untied omp_get_thread_num () can change
4610 during the execution of the task region. */
4611 if (untied_task)
4612 continue;
4613 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4615 else if (DECL_NAME (decl) == num_thr_id)
4616 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4617 else
4618 continue;
4620 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4621 || gimple_call_num_args (call) != 0)
4622 continue;
4624 if (flag_exceptions && !TREE_NOTHROW (decl))
4625 continue;
4627 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4628 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4629 TREE_TYPE (TREE_TYPE (built_in))))
4630 continue;
4632 gimple_call_set_fndecl (call, built_in);
4637 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4638 regimplified. */
4640 static tree
4641 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4643 tree t = *tp;
4645 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4646 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4647 return t;
4649 if (TREE_CODE (t) == ADDR_EXPR)
4650 recompute_tree_invariant_for_addr_expr (t);
4652 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4653 return NULL_TREE;
4656 /* Prepend TO = FROM assignment before *GSI_P. */
4658 static void
4659 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4661 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4662 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4663 true, GSI_SAME_STMT);
4664 gimple stmt = gimple_build_assign (to, from);
4665 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4666 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4667 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4669 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4670 gimple_regimplify_operands (stmt, &gsi);
4674 /* Expand the OpenMP parallel or task directive starting at REGION. */
4676 static void
4677 expand_omp_taskreg (struct omp_region *region)
4679 basic_block entry_bb, exit_bb, new_bb;
4680 struct function *child_cfun;
4681 tree child_fn, block, t;
4682 gimple_stmt_iterator gsi;
4683 gimple entry_stmt, stmt;
4684 edge e;
4685 vec<tree, va_gc> *ws_args;
4687 entry_stmt = last_stmt (region->entry);
4688 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4689 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4691 entry_bb = region->entry;
4692 exit_bb = region->exit;
4694 if (is_combined_parallel (region))
4695 ws_args = region->ws_args;
4696 else
4697 ws_args = NULL;
4699 if (child_cfun->cfg)
4701 /* Due to inlining, it may happen that we have already outlined
4702 the region, in which case all we need to do is make the
4703 sub-graph unreachable and emit the parallel call. */
4704 edge entry_succ_e, exit_succ_e;
4706 entry_succ_e = single_succ_edge (entry_bb);
4708 gsi = gsi_last_bb (entry_bb);
4709 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4710 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4711 gsi_remove (&gsi, true);
4713 new_bb = entry_bb;
4714 if (exit_bb)
4716 exit_succ_e = single_succ_edge (exit_bb);
4717 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4719 remove_edge_and_dominated_blocks (entry_succ_e);
4721 else
4723 unsigned srcidx, dstidx, num;
4725 /* If the parallel region needs data sent from the parent
4726 function, then the very first statement (except possible
4727 tree profile counter updates) of the parallel body
4728 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4729 &.OMP_DATA_O is passed as an argument to the child function,
4730 we need to replace it with the argument as seen by the child
4731 function.
4733 In most cases, this will end up being the identity assignment
4734 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4735 a function call that has been inlined, the original PARM_DECL
4736 .OMP_DATA_I may have been converted into a different local
4737 variable. In which case, we need to keep the assignment. */
4738 if (gimple_omp_taskreg_data_arg (entry_stmt))
4740 basic_block entry_succ_bb = single_succ (entry_bb);
4741 tree arg, narg;
4742 gimple parcopy_stmt = NULL;
4744 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4746 gimple stmt;
4748 gcc_assert (!gsi_end_p (gsi));
4749 stmt = gsi_stmt (gsi);
4750 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4751 continue;
4753 if (gimple_num_ops (stmt) == 2)
4755 tree arg = gimple_assign_rhs1 (stmt);
4757 /* We're ignore the subcode because we're
4758 effectively doing a STRIP_NOPS. */
4760 if (TREE_CODE (arg) == ADDR_EXPR
4761 && TREE_OPERAND (arg, 0)
4762 == gimple_omp_taskreg_data_arg (entry_stmt))
4764 parcopy_stmt = stmt;
4765 break;
4770 gcc_assert (parcopy_stmt != NULL);
4771 arg = DECL_ARGUMENTS (child_fn);
4773 if (!gimple_in_ssa_p (cfun))
4775 if (gimple_assign_lhs (parcopy_stmt) == arg)
4776 gsi_remove (&gsi, true);
4777 else
4779 /* ?? Is setting the subcode really necessary ?? */
4780 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
4781 gimple_assign_set_rhs1 (parcopy_stmt, arg);
4784 else
4786 /* If we are in ssa form, we must load the value from the default
4787 definition of the argument. That should not be defined now,
4788 since the argument is not used uninitialized. */
4789 gcc_assert (ssa_default_def (cfun, arg) == NULL);
4790 narg = make_ssa_name (arg, gimple_build_nop ());
4791 set_ssa_default_def (cfun, arg, narg);
4792 /* ?? Is setting the subcode really necessary ?? */
4793 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
4794 gimple_assign_set_rhs1 (parcopy_stmt, narg);
4795 update_stmt (parcopy_stmt);
4799 /* Declare local variables needed in CHILD_CFUN. */
4800 block = DECL_INITIAL (child_fn);
4801 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4802 /* The gimplifier could record temporaries in parallel/task block
4803 rather than in containing function's local_decls chain,
4804 which would mean cgraph missed finalizing them. Do it now. */
4805 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4806 if (TREE_CODE (t) == VAR_DECL
4807 && TREE_STATIC (t)
4808 && !DECL_EXTERNAL (t))
4809 varpool_finalize_decl (t);
4810 DECL_SAVED_TREE (child_fn) = NULL;
4811 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4812 gimple_set_body (child_fn, NULL);
4813 TREE_USED (block) = 1;
4815 /* Reset DECL_CONTEXT on function arguments. */
4816 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
4817 DECL_CONTEXT (t) = child_fn;
4819 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
4820 so that it can be moved to the child function. */
4821 gsi = gsi_last_bb (entry_bb);
4822 stmt = gsi_stmt (gsi);
4823 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
4824 || gimple_code (stmt) == GIMPLE_OMP_TASK));
4825 gsi_remove (&gsi, true);
4826 e = split_block (entry_bb, stmt);
4827 entry_bb = e->dest;
4828 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4830 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4831 if (exit_bb)
4833 gsi = gsi_last_bb (exit_bb);
4834 gcc_assert (!gsi_end_p (gsi)
4835 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4836 stmt = gimple_build_return (NULL);
4837 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4838 gsi_remove (&gsi, true);
4841 /* Move the parallel region into CHILD_CFUN. */
4843 if (gimple_in_ssa_p (cfun))
4845 init_tree_ssa (child_cfun);
4846 init_ssa_operands (child_cfun);
4847 child_cfun->gimple_df->in_ssa_p = true;
4848 block = NULL_TREE;
4850 else
4851 block = gimple_block (entry_stmt);
4853 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
4854 if (exit_bb)
4855 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
4856 /* When the OMP expansion process cannot guarantee an up-to-date
4857 loop tree arrange for the child function to fixup loops. */
4858 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
4859 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
4861 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
4862 num = vec_safe_length (child_cfun->local_decls);
4863 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
4865 t = (*child_cfun->local_decls)[srcidx];
4866 if (DECL_CONTEXT (t) == cfun->decl)
4867 continue;
4868 if (srcidx != dstidx)
4869 (*child_cfun->local_decls)[dstidx] = t;
4870 dstidx++;
4872 if (dstidx != num)
4873 vec_safe_truncate (child_cfun->local_decls, dstidx);
4875 /* Inform the callgraph about the new function. */
4876 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
4877 cgraph_add_new_function (child_fn, true);
4879 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4880 fixed in a following pass. */
4881 push_cfun (child_cfun);
4882 if (optimize)
4883 optimize_omp_library_calls (entry_stmt);
4884 rebuild_cgraph_edges ();
4886 /* Some EH regions might become dead, see PR34608. If
4887 pass_cleanup_cfg isn't the first pass to happen with the
4888 new child, these dead EH edges might cause problems.
4889 Clean them up now. */
4890 if (flag_exceptions)
4892 basic_block bb;
4893 bool changed = false;
4895 FOR_EACH_BB_FN (bb, cfun)
4896 changed |= gimple_purge_dead_eh_edges (bb);
4897 if (changed)
4898 cleanup_tree_cfg ();
4900 if (gimple_in_ssa_p (cfun))
4901 update_ssa (TODO_update_ssa);
4902 pop_cfun ();
4905 /* Emit a library call to launch the children threads. */
4906 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
4907 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
4908 else
4909 expand_task_call (new_bb, entry_stmt);
4910 if (gimple_in_ssa_p (cfun))
4911 update_ssa (TODO_update_ssa_only_virtuals);
4915 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4916 of the combined collapse > 1 loop constructs, generate code like:
4917 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4918 if (cond3 is <)
4919 adj = STEP3 - 1;
4920 else
4921 adj = STEP3 + 1;
4922 count3 = (adj + N32 - N31) / STEP3;
4923 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4924 if (cond2 is <)
4925 adj = STEP2 - 1;
4926 else
4927 adj = STEP2 + 1;
4928 count2 = (adj + N22 - N21) / STEP2;
4929 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4930 if (cond1 is <)
4931 adj = STEP1 - 1;
4932 else
4933 adj = STEP1 + 1;
4934 count1 = (adj + N12 - N11) / STEP1;
4935 count = count1 * count2 * count3;
4936 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4937 count = 0;
4938 and set ZERO_ITER_BB to that bb. If this isn't the outermost
4939 of the combined loop constructs, just initialize COUNTS array
4940 from the _looptemp_ clauses. */
4942 /* NOTE: It *could* be better to moosh all of the BBs together,
4943 creating one larger BB with all the computation and the unexpected
4944 jump at the end. I.e.
4946 bool zero3, zero2, zero1, zero;
4948 zero3 = N32 c3 N31;
4949 count3 = (N32 - N31) /[cl] STEP3;
4950 zero2 = N22 c2 N21;
4951 count2 = (N22 - N21) /[cl] STEP2;
4952 zero1 = N12 c1 N11;
4953 count1 = (N12 - N11) /[cl] STEP1;
4954 zero = zero3 || zero2 || zero1;
4955 count = count1 * count2 * count3;
4956 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4958 After all, we expect the zero=false, and thus we expect to have to
4959 evaluate all of the comparison expressions, so short-circuiting
4960 oughtn't be a win. Since the condition isn't protecting a
4961 denominator, we're not concerned about divide-by-zero, so we can
4962 fully evaluate count even if a numerator turned out to be wrong.
4964 It seems like putting this all together would create much better
4965 scheduling opportunities, and less pressure on the chip's branch
4966 predictor. */
4968 static void
4969 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4970 basic_block &entry_bb, tree *counts,
4971 basic_block &zero_iter_bb, int &first_zero_iter,
4972 basic_block &l2_dom_bb)
4974 tree t, type = TREE_TYPE (fd->loop.v);
4975 gimple stmt;
4976 edge e, ne;
4977 int i;
4979 /* Collapsed loops need work for expansion into SSA form. */
4980 gcc_assert (!gimple_in_ssa_p (cfun));
4982 if (gimple_omp_for_combined_into_p (fd->for_stmt)
4983 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
4985 /* First two _looptemp_ clauses are for istart/iend, counts[0]
4986 isn't supposed to be handled, as the inner loop doesn't
4987 use it. */
4988 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
4989 OMP_CLAUSE__LOOPTEMP_);
4990 gcc_assert (innerc);
4991 for (i = 0; i < fd->collapse; i++)
4993 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
4994 OMP_CLAUSE__LOOPTEMP_);
4995 gcc_assert (innerc);
4996 if (i)
4997 counts[i] = OMP_CLAUSE_DECL (innerc);
4998 else
4999 counts[0] = NULL_TREE;
5001 return;
5004 for (i = 0; i < fd->collapse; i++)
5006 tree itype = TREE_TYPE (fd->loops[i].v);
5008 if (SSA_VAR_P (fd->loop.n2)
5009 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5010 fold_convert (itype, fd->loops[i].n1),
5011 fold_convert (itype, fd->loops[i].n2)))
5012 == NULL_TREE || !integer_onep (t)))
5014 tree n1, n2;
5015 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5016 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5017 true, GSI_SAME_STMT);
5018 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5019 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5020 true, GSI_SAME_STMT);
5021 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5022 NULL_TREE, NULL_TREE);
5023 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5024 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5025 expand_omp_regimplify_p, NULL, NULL)
5026 || walk_tree (gimple_cond_rhs_ptr (stmt),
5027 expand_omp_regimplify_p, NULL, NULL))
5029 *gsi = gsi_for_stmt (stmt);
5030 gimple_regimplify_operands (stmt, gsi);
5032 e = split_block (entry_bb, stmt);
5033 if (zero_iter_bb == NULL)
5035 first_zero_iter = i;
5036 zero_iter_bb = create_empty_bb (entry_bb);
5037 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5038 *gsi = gsi_after_labels (zero_iter_bb);
5039 stmt = gimple_build_assign (fd->loop.n2,
5040 build_zero_cst (type));
5041 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5042 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5043 entry_bb);
5045 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5046 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5047 e->flags = EDGE_TRUE_VALUE;
5048 e->probability = REG_BR_PROB_BASE - ne->probability;
5049 if (l2_dom_bb == NULL)
5050 l2_dom_bb = entry_bb;
5051 entry_bb = e->dest;
5052 *gsi = gsi_last_bb (entry_bb);
5055 if (POINTER_TYPE_P (itype))
5056 itype = signed_type_for (itype);
5057 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5058 ? -1 : 1));
5059 t = fold_build2 (PLUS_EXPR, itype,
5060 fold_convert (itype, fd->loops[i].step), t);
5061 t = fold_build2 (PLUS_EXPR, itype, t,
5062 fold_convert (itype, fd->loops[i].n2));
5063 t = fold_build2 (MINUS_EXPR, itype, t,
5064 fold_convert (itype, fd->loops[i].n1));
5065 /* ?? We could probably use CEIL_DIV_EXPR instead of
5066 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5067 generate the same code in the end because generically we
5068 don't know that the values involved must be negative for
5069 GT?? */
5070 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5071 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5072 fold_build1 (NEGATE_EXPR, itype, t),
5073 fold_build1 (NEGATE_EXPR, itype,
5074 fold_convert (itype,
5075 fd->loops[i].step)));
5076 else
5077 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5078 fold_convert (itype, fd->loops[i].step));
5079 t = fold_convert (type, t);
5080 if (TREE_CODE (t) == INTEGER_CST)
5081 counts[i] = t;
5082 else
5084 counts[i] = create_tmp_reg (type, ".count");
5085 expand_omp_build_assign (gsi, counts[i], t);
5087 if (SSA_VAR_P (fd->loop.n2))
5089 if (i == 0)
5090 t = counts[0];
5091 else
5092 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5093 expand_omp_build_assign (gsi, fd->loop.n2, t);
5099 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5100 T = V;
5101 V3 = N31 + (T % count3) * STEP3;
5102 T = T / count3;
5103 V2 = N21 + (T % count2) * STEP2;
5104 T = T / count2;
5105 V1 = N11 + T * STEP1;
5106 if this loop doesn't have an inner loop construct combined with it.
5107 If it does have an inner loop construct combined with it and the
5108 iteration count isn't known constant, store values from counts array
5109 into its _looptemp_ temporaries instead. */
5111 static void
5112 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5113 tree *counts, gimple inner_stmt, tree startvar)
5115 int i;
5116 if (gimple_omp_for_combined_p (fd->for_stmt))
5118 /* If fd->loop.n2 is constant, then no propagation of the counts
5119 is needed, they are constant. */
5120 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5121 return;
5123 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5124 ? gimple_omp_parallel_clauses (inner_stmt)
5125 : gimple_omp_for_clauses (inner_stmt);
5126 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5127 isn't supposed to be handled, as the inner loop doesn't
5128 use it. */
5129 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5130 gcc_assert (innerc);
5131 for (i = 0; i < fd->collapse; i++)
5133 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5134 OMP_CLAUSE__LOOPTEMP_);
5135 gcc_assert (innerc);
5136 if (i)
5138 tree tem = OMP_CLAUSE_DECL (innerc);
5139 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5140 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5141 false, GSI_CONTINUE_LINKING);
5142 gimple stmt = gimple_build_assign (tem, t);
5143 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5146 return;
5149 tree type = TREE_TYPE (fd->loop.v);
5150 tree tem = create_tmp_reg (type, ".tem");
5151 gimple stmt = gimple_build_assign (tem, startvar);
5152 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5154 for (i = fd->collapse - 1; i >= 0; i--)
5156 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5157 itype = vtype;
5158 if (POINTER_TYPE_P (vtype))
5159 itype = signed_type_for (vtype);
5160 if (i != 0)
5161 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5162 else
5163 t = tem;
5164 t = fold_convert (itype, t);
5165 t = fold_build2 (MULT_EXPR, itype, t,
5166 fold_convert (itype, fd->loops[i].step));
5167 if (POINTER_TYPE_P (vtype))
5168 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5169 else
5170 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5171 t = force_gimple_operand_gsi (gsi, t,
5172 DECL_P (fd->loops[i].v)
5173 && TREE_ADDRESSABLE (fd->loops[i].v),
5174 NULL_TREE, false,
5175 GSI_CONTINUE_LINKING);
5176 stmt = gimple_build_assign (fd->loops[i].v, t);
5177 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5178 if (i != 0)
5180 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5181 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5182 false, GSI_CONTINUE_LINKING);
5183 stmt = gimple_build_assign (tem, t);
5184 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5190 /* Helper function for expand_omp_for_*. Generate code like:
5191 L10:
5192 V3 += STEP3;
5193 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5194 L11:
5195 V3 = N31;
5196 V2 += STEP2;
5197 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5198 L12:
5199 V2 = N21;
5200 V1 += STEP1;
5201 goto BODY_BB; */
5203 static basic_block
5204 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5205 basic_block body_bb)
5207 basic_block last_bb, bb, collapse_bb = NULL;
5208 int i;
5209 gimple_stmt_iterator gsi;
5210 edge e;
5211 tree t;
5212 gimple stmt;
5214 last_bb = cont_bb;
5215 for (i = fd->collapse - 1; i >= 0; i--)
5217 tree vtype = TREE_TYPE (fd->loops[i].v);
5219 bb = create_empty_bb (last_bb);
5220 add_bb_to_loop (bb, last_bb->loop_father);
5221 gsi = gsi_start_bb (bb);
5223 if (i < fd->collapse - 1)
5225 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5226 e->probability = REG_BR_PROB_BASE / 8;
5228 t = fd->loops[i + 1].n1;
5229 t = force_gimple_operand_gsi (&gsi, t,
5230 DECL_P (fd->loops[i + 1].v)
5231 && TREE_ADDRESSABLE (fd->loops[i
5232 + 1].v),
5233 NULL_TREE, false,
5234 GSI_CONTINUE_LINKING);
5235 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5236 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5238 else
5239 collapse_bb = bb;
5241 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5243 if (POINTER_TYPE_P (vtype))
5244 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5245 else
5246 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5247 t = force_gimple_operand_gsi (&gsi, t,
5248 DECL_P (fd->loops[i].v)
5249 && TREE_ADDRESSABLE (fd->loops[i].v),
5250 NULL_TREE, false, GSI_CONTINUE_LINKING);
5251 stmt = gimple_build_assign (fd->loops[i].v, t);
5252 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5254 if (i > 0)
5256 t = fd->loops[i].n2;
5257 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5258 false, GSI_CONTINUE_LINKING);
5259 tree v = fd->loops[i].v;
5260 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5261 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5262 false, GSI_CONTINUE_LINKING);
5263 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5264 stmt = gimple_build_cond_empty (t);
5265 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5266 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5267 e->probability = REG_BR_PROB_BASE * 7 / 8;
5269 else
5270 make_edge (bb, body_bb, EDGE_FALLTHRU);
5271 last_bb = bb;
5274 return collapse_bb;
5278 /* A subroutine of expand_omp_for. Generate code for a parallel
5279 loop with any schedule. Given parameters:
5281 for (V = N1; V cond N2; V += STEP) BODY;
5283 where COND is "<" or ">", we generate pseudocode
5285 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5286 if (more) goto L0; else goto L3;
5288 V = istart0;
5289 iend = iend0;
5291 BODY;
5292 V += STEP;
5293 if (V cond iend) goto L1; else goto L2;
5295 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5298 If this is a combined omp parallel loop, instead of the call to
5299 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5300 If this is gimple_omp_for_combined_p loop, then instead of assigning
5301 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5302 inner GIMPLE_OMP_FOR and V += STEP; and
5303 if (V cond iend) goto L1; else goto L2; are removed.
5305 For collapsed loops, given parameters:
5306 collapse(3)
5307 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5308 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5309 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5310 BODY;
5312 we generate pseudocode
5314 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5315 if (cond3 is <)
5316 adj = STEP3 - 1;
5317 else
5318 adj = STEP3 + 1;
5319 count3 = (adj + N32 - N31) / STEP3;
5320 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5321 if (cond2 is <)
5322 adj = STEP2 - 1;
5323 else
5324 adj = STEP2 + 1;
5325 count2 = (adj + N22 - N21) / STEP2;
5326 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5327 if (cond1 is <)
5328 adj = STEP1 - 1;
5329 else
5330 adj = STEP1 + 1;
5331 count1 = (adj + N12 - N11) / STEP1;
5332 count = count1 * count2 * count3;
5333 goto Z1;
5335 count = 0;
5337 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5338 if (more) goto L0; else goto L3;
5340 V = istart0;
5341 T = V;
5342 V3 = N31 + (T % count3) * STEP3;
5343 T = T / count3;
5344 V2 = N21 + (T % count2) * STEP2;
5345 T = T / count2;
5346 V1 = N11 + T * STEP1;
5347 iend = iend0;
5349 BODY;
5350 V += 1;
5351 if (V < iend) goto L10; else goto L2;
5352 L10:
5353 V3 += STEP3;
5354 if (V3 cond3 N32) goto L1; else goto L11;
5355 L11:
5356 V3 = N31;
5357 V2 += STEP2;
5358 if (V2 cond2 N22) goto L1; else goto L12;
5359 L12:
5360 V2 = N21;
5361 V1 += STEP1;
5362 goto L1;
5364 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5369 static void
5370 expand_omp_for_generic (struct omp_region *region,
5371 struct omp_for_data *fd,
5372 enum built_in_function start_fn,
5373 enum built_in_function next_fn,
5374 gimple inner_stmt)
5376 tree type, istart0, iend0, iend;
5377 tree t, vmain, vback, bias = NULL_TREE;
5378 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5379 basic_block l2_bb = NULL, l3_bb = NULL;
5380 gimple_stmt_iterator gsi;
5381 gimple stmt;
5382 bool in_combined_parallel = is_combined_parallel (region);
5383 bool broken_loop = region->cont == NULL;
5384 edge e, ne;
5385 tree *counts = NULL;
5386 int i;
5388 gcc_assert (!broken_loop || !in_combined_parallel);
5389 gcc_assert (fd->iter_type == long_integer_type_node
5390 || !in_combined_parallel);
5392 type = TREE_TYPE (fd->loop.v);
5393 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5394 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5395 TREE_ADDRESSABLE (istart0) = 1;
5396 TREE_ADDRESSABLE (iend0) = 1;
5398 /* See if we need to bias by LLONG_MIN. */
5399 if (fd->iter_type == long_long_unsigned_type_node
5400 && TREE_CODE (type) == INTEGER_TYPE
5401 && !TYPE_UNSIGNED (type))
5403 tree n1, n2;
5405 if (fd->loop.cond_code == LT_EXPR)
5407 n1 = fd->loop.n1;
5408 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5410 else
5412 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5413 n2 = fd->loop.n1;
5415 if (TREE_CODE (n1) != INTEGER_CST
5416 || TREE_CODE (n2) != INTEGER_CST
5417 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5418 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5421 entry_bb = region->entry;
5422 cont_bb = region->cont;
5423 collapse_bb = NULL;
5424 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5425 gcc_assert (broken_loop
5426 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5427 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5428 l1_bb = single_succ (l0_bb);
5429 if (!broken_loop)
5431 l2_bb = create_empty_bb (cont_bb);
5432 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5433 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5435 else
5436 l2_bb = NULL;
5437 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5438 exit_bb = region->exit;
5440 gsi = gsi_last_bb (entry_bb);
5442 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5443 if (fd->collapse > 1)
5445 int first_zero_iter = -1;
5446 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5448 counts = XALLOCAVEC (tree, fd->collapse);
5449 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5450 zero_iter_bb, first_zero_iter,
5451 l2_dom_bb);
5453 if (zero_iter_bb)
5455 /* Some counts[i] vars might be uninitialized if
5456 some loop has zero iterations. But the body shouldn't
5457 be executed in that case, so just avoid uninit warnings. */
5458 for (i = first_zero_iter; i < fd->collapse; i++)
5459 if (SSA_VAR_P (counts[i]))
5460 TREE_NO_WARNING (counts[i]) = 1;
5461 gsi_prev (&gsi);
5462 e = split_block (entry_bb, gsi_stmt (gsi));
5463 entry_bb = e->dest;
5464 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5465 gsi = gsi_last_bb (entry_bb);
5466 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5467 get_immediate_dominator (CDI_DOMINATORS,
5468 zero_iter_bb));
5471 if (in_combined_parallel)
5473 /* In a combined parallel loop, emit a call to
5474 GOMP_loop_foo_next. */
5475 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5476 build_fold_addr_expr (istart0),
5477 build_fold_addr_expr (iend0));
5479 else
5481 tree t0, t1, t2, t3, t4;
5482 /* If this is not a combined parallel loop, emit a call to
5483 GOMP_loop_foo_start in ENTRY_BB. */
5484 t4 = build_fold_addr_expr (iend0);
5485 t3 = build_fold_addr_expr (istart0);
5486 t2 = fold_convert (fd->iter_type, fd->loop.step);
5487 t1 = fd->loop.n2;
5488 t0 = fd->loop.n1;
5489 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5491 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5492 OMP_CLAUSE__LOOPTEMP_);
5493 gcc_assert (innerc);
5494 t0 = OMP_CLAUSE_DECL (innerc);
5495 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5496 OMP_CLAUSE__LOOPTEMP_);
5497 gcc_assert (innerc);
5498 t1 = OMP_CLAUSE_DECL (innerc);
5500 if (POINTER_TYPE_P (TREE_TYPE (t0))
5501 && TYPE_PRECISION (TREE_TYPE (t0))
5502 != TYPE_PRECISION (fd->iter_type))
5504 /* Avoid casting pointers to integer of a different size. */
5505 tree itype = signed_type_for (type);
5506 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5507 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5509 else
5511 t1 = fold_convert (fd->iter_type, t1);
5512 t0 = fold_convert (fd->iter_type, t0);
5514 if (bias)
5516 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5517 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5519 if (fd->iter_type == long_integer_type_node)
5521 if (fd->chunk_size)
5523 t = fold_convert (fd->iter_type, fd->chunk_size);
5524 t = build_call_expr (builtin_decl_explicit (start_fn),
5525 6, t0, t1, t2, t, t3, t4);
5527 else
5528 t = build_call_expr (builtin_decl_explicit (start_fn),
5529 5, t0, t1, t2, t3, t4);
5531 else
5533 tree t5;
5534 tree c_bool_type;
5535 tree bfn_decl;
5537 /* The GOMP_loop_ull_*start functions have additional boolean
5538 argument, true for < loops and false for > loops.
5539 In Fortran, the C bool type can be different from
5540 boolean_type_node. */
5541 bfn_decl = builtin_decl_explicit (start_fn);
5542 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5543 t5 = build_int_cst (c_bool_type,
5544 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5545 if (fd->chunk_size)
5547 tree bfn_decl = builtin_decl_explicit (start_fn);
5548 t = fold_convert (fd->iter_type, fd->chunk_size);
5549 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5551 else
5552 t = build_call_expr (builtin_decl_explicit (start_fn),
5553 6, t5, t0, t1, t2, t3, t4);
5556 if (TREE_TYPE (t) != boolean_type_node)
5557 t = fold_build2 (NE_EXPR, boolean_type_node,
5558 t, build_int_cst (TREE_TYPE (t), 0));
5559 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5560 true, GSI_SAME_STMT);
5561 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5563 /* Remove the GIMPLE_OMP_FOR statement. */
5564 gsi_remove (&gsi, true);
5566 /* Iteration setup for sequential loop goes in L0_BB. */
5567 tree startvar = fd->loop.v;
5568 tree endvar = NULL_TREE;
5570 if (gimple_omp_for_combined_p (fd->for_stmt))
5572 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5573 && gimple_omp_for_kind (inner_stmt)
5574 == GF_OMP_FOR_KIND_SIMD);
5575 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5576 OMP_CLAUSE__LOOPTEMP_);
5577 gcc_assert (innerc);
5578 startvar = OMP_CLAUSE_DECL (innerc);
5579 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5580 OMP_CLAUSE__LOOPTEMP_);
5581 gcc_assert (innerc);
5582 endvar = OMP_CLAUSE_DECL (innerc);
5585 gsi = gsi_start_bb (l0_bb);
5586 t = istart0;
5587 if (bias)
5588 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5589 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5590 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5591 t = fold_convert (TREE_TYPE (startvar), t);
5592 t = force_gimple_operand_gsi (&gsi, t,
5593 DECL_P (startvar)
5594 && TREE_ADDRESSABLE (startvar),
5595 NULL_TREE, false, GSI_CONTINUE_LINKING);
5596 stmt = gimple_build_assign (startvar, t);
5597 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5599 t = iend0;
5600 if (bias)
5601 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5602 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5603 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5604 t = fold_convert (TREE_TYPE (startvar), t);
5605 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5606 false, GSI_CONTINUE_LINKING);
5607 if (endvar)
5609 stmt = gimple_build_assign (endvar, iend);
5610 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5611 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
5612 stmt = gimple_build_assign (fd->loop.v, iend);
5613 else
5614 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend,
5615 NULL_TREE);
5616 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5618 if (fd->collapse > 1)
5619 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5621 if (!broken_loop)
5623 /* Code to control the increment and predicate for the sequential
5624 loop goes in the CONT_BB. */
5625 gsi = gsi_last_bb (cont_bb);
5626 stmt = gsi_stmt (gsi);
5627 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5628 vmain = gimple_omp_continue_control_use (stmt);
5629 vback = gimple_omp_continue_control_def (stmt);
5631 if (!gimple_omp_for_combined_p (fd->for_stmt))
5633 if (POINTER_TYPE_P (type))
5634 t = fold_build_pointer_plus (vmain, fd->loop.step);
5635 else
5636 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5637 t = force_gimple_operand_gsi (&gsi, t,
5638 DECL_P (vback)
5639 && TREE_ADDRESSABLE (vback),
5640 NULL_TREE, true, GSI_SAME_STMT);
5641 stmt = gimple_build_assign (vback, t);
5642 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5644 t = build2 (fd->loop.cond_code, boolean_type_node,
5645 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5646 iend);
5647 stmt = gimple_build_cond_empty (t);
5648 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5651 /* Remove GIMPLE_OMP_CONTINUE. */
5652 gsi_remove (&gsi, true);
5654 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5655 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5657 /* Emit code to get the next parallel iteration in L2_BB. */
5658 gsi = gsi_start_bb (l2_bb);
5660 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5661 build_fold_addr_expr (istart0),
5662 build_fold_addr_expr (iend0));
5663 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5664 false, GSI_CONTINUE_LINKING);
5665 if (TREE_TYPE (t) != boolean_type_node)
5666 t = fold_build2 (NE_EXPR, boolean_type_node,
5667 t, build_int_cst (TREE_TYPE (t), 0));
5668 stmt = gimple_build_cond_empty (t);
5669 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5672 /* Add the loop cleanup function. */
5673 gsi = gsi_last_bb (exit_bb);
5674 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5675 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5676 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5677 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5678 else
5679 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5680 stmt = gimple_build_call (t, 0);
5681 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5682 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5683 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5684 gsi_remove (&gsi, true);
5686 /* Connect the new blocks. */
5687 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5688 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5690 if (!broken_loop)
5692 gimple_seq phis;
5694 e = find_edge (cont_bb, l3_bb);
5695 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5697 phis = phi_nodes (l3_bb);
5698 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5700 gimple phi = gsi_stmt (gsi);
5701 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5702 PHI_ARG_DEF_FROM_EDGE (phi, e));
5704 remove_edge (e);
5706 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5707 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5708 e = find_edge (cont_bb, l1_bb);
5709 if (gimple_omp_for_combined_p (fd->for_stmt))
5711 remove_edge (e);
5712 e = NULL;
5714 else if (fd->collapse > 1)
5716 remove_edge (e);
5717 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5719 else
5720 e->flags = EDGE_TRUE_VALUE;
5721 if (e)
5723 e->probability = REG_BR_PROB_BASE * 7 / 8;
5724 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5726 else
5728 e = find_edge (cont_bb, l2_bb);
5729 e->flags = EDGE_FALLTHRU;
5731 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5733 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5734 recompute_dominator (CDI_DOMINATORS, l2_bb));
5735 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5736 recompute_dominator (CDI_DOMINATORS, l3_bb));
5737 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5738 recompute_dominator (CDI_DOMINATORS, l0_bb));
5739 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5740 recompute_dominator (CDI_DOMINATORS, l1_bb));
5742 struct loop *outer_loop = alloc_loop ();
5743 outer_loop->header = l0_bb;
5744 outer_loop->latch = l2_bb;
5745 add_loop (outer_loop, l0_bb->loop_father);
5747 if (!gimple_omp_for_combined_p (fd->for_stmt))
5749 struct loop *loop = alloc_loop ();
5750 loop->header = l1_bb;
5751 /* The loop may have multiple latches. */
5752 add_loop (loop, outer_loop);
5758 /* A subroutine of expand_omp_for. Generate code for a parallel
5759 loop with static schedule and no specified chunk size. Given
5760 parameters:
5762 for (V = N1; V cond N2; V += STEP) BODY;
5764 where COND is "<" or ">", we generate pseudocode
5766 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5767 if (cond is <)
5768 adj = STEP - 1;
5769 else
5770 adj = STEP + 1;
5771 if ((__typeof (V)) -1 > 0 && cond is >)
5772 n = -(adj + N2 - N1) / -STEP;
5773 else
5774 n = (adj + N2 - N1) / STEP;
5775 q = n / nthreads;
5776 tt = n % nthreads;
5777 if (threadid < tt) goto L3; else goto L4;
5779 tt = 0;
5780 q = q + 1;
5782 s0 = q * threadid + tt;
5783 e0 = s0 + q;
5784 V = s0 * STEP + N1;
5785 if (s0 >= e0) goto L2; else goto L0;
5787 e = e0 * STEP + N1;
5789 BODY;
5790 V += STEP;
5791 if (V cond e) goto L1;
5795 static void
5796 expand_omp_for_static_nochunk (struct omp_region *region,
5797 struct omp_for_data *fd,
5798 gimple inner_stmt)
5800 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
5801 tree type, itype, vmain, vback;
5802 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
5803 basic_block body_bb, cont_bb, collapse_bb = NULL;
5804 basic_block fin_bb;
5805 gimple_stmt_iterator gsi;
5806 gimple stmt;
5807 edge ep;
5808 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
5809 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
5810 bool broken_loop = region->cont == NULL;
5811 tree *counts = NULL;
5812 tree n1, n2, step;
5814 itype = type = TREE_TYPE (fd->loop.v);
5815 if (POINTER_TYPE_P (type))
5816 itype = signed_type_for (type);
5818 entry_bb = region->entry;
5819 cont_bb = region->cont;
5820 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5821 fin_bb = BRANCH_EDGE (entry_bb)->dest;
5822 gcc_assert (broken_loop
5823 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
5824 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5825 body_bb = single_succ (seq_start_bb);
5826 if (!broken_loop)
5828 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
5829 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5831 exit_bb = region->exit;
5833 /* Iteration space partitioning goes in ENTRY_BB. */
5834 gsi = gsi_last_bb (entry_bb);
5835 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5837 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
5839 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
5840 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
5843 if (fd->collapse > 1)
5845 int first_zero_iter = -1;
5846 basic_block l2_dom_bb = NULL;
5848 counts = XALLOCAVEC (tree, fd->collapse);
5849 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5850 fin_bb, first_zero_iter,
5851 l2_dom_bb);
5852 t = NULL_TREE;
5854 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
5855 t = integer_one_node;
5856 else
5857 t = fold_binary (fd->loop.cond_code, boolean_type_node,
5858 fold_convert (type, fd->loop.n1),
5859 fold_convert (type, fd->loop.n2));
5860 if (fd->collapse == 1
5861 && TYPE_UNSIGNED (type)
5862 && (t == NULL_TREE || !integer_onep (t)))
5864 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5865 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5866 true, GSI_SAME_STMT);
5867 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5868 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5869 true, GSI_SAME_STMT);
5870 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
5871 NULL_TREE, NULL_TREE);
5872 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5873 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5874 expand_omp_regimplify_p, NULL, NULL)
5875 || walk_tree (gimple_cond_rhs_ptr (stmt),
5876 expand_omp_regimplify_p, NULL, NULL))
5878 gsi = gsi_for_stmt (stmt);
5879 gimple_regimplify_operands (stmt, &gsi);
5881 ep = split_block (entry_bb, stmt);
5882 ep->flags = EDGE_TRUE_VALUE;
5883 entry_bb = ep->dest;
5884 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
5885 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
5886 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
5887 if (gimple_in_ssa_p (cfun))
5889 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
5890 for (gsi = gsi_start_phis (fin_bb);
5891 !gsi_end_p (gsi); gsi_next (&gsi))
5893 gimple phi = gsi_stmt (gsi);
5894 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
5895 ep, UNKNOWN_LOCATION);
5898 gsi = gsi_last_bb (entry_bb);
5901 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
5902 t = fold_convert (itype, t);
5903 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5904 true, GSI_SAME_STMT);
5906 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
5907 t = fold_convert (itype, t);
5908 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5909 true, GSI_SAME_STMT);
5911 n1 = fd->loop.n1;
5912 n2 = fd->loop.n2;
5913 step = fd->loop.step;
5914 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5916 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5917 OMP_CLAUSE__LOOPTEMP_);
5918 gcc_assert (innerc);
5919 n1 = OMP_CLAUSE_DECL (innerc);
5920 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5921 OMP_CLAUSE__LOOPTEMP_);
5922 gcc_assert (innerc);
5923 n2 = OMP_CLAUSE_DECL (innerc);
5925 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
5926 true, NULL_TREE, true, GSI_SAME_STMT);
5927 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
5928 true, NULL_TREE, true, GSI_SAME_STMT);
5929 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
5930 true, NULL_TREE, true, GSI_SAME_STMT);
5932 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
5933 t = fold_build2 (PLUS_EXPR, itype, step, t);
5934 t = fold_build2 (PLUS_EXPR, itype, t, n2);
5935 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
5936 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
5937 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5938 fold_build1 (NEGATE_EXPR, itype, t),
5939 fold_build1 (NEGATE_EXPR, itype, step));
5940 else
5941 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
5942 t = fold_convert (itype, t);
5943 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5945 q = create_tmp_reg (itype, "q");
5946 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
5947 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5948 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
5950 tt = create_tmp_reg (itype, "tt");
5951 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
5952 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5953 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
5955 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
5956 stmt = gimple_build_cond_empty (t);
5957 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5959 second_bb = split_block (entry_bb, stmt)->dest;
5960 gsi = gsi_last_bb (second_bb);
5961 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5963 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
5964 GSI_SAME_STMT);
5965 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
5966 build_int_cst (itype, 1));
5967 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5969 third_bb = split_block (second_bb, stmt)->dest;
5970 gsi = gsi_last_bb (third_bb);
5971 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5973 t = build2 (MULT_EXPR, itype, q, threadid);
5974 t = build2 (PLUS_EXPR, itype, t, tt);
5975 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5977 t = fold_build2 (PLUS_EXPR, itype, s0, q);
5978 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5980 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
5981 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5983 /* Remove the GIMPLE_OMP_FOR statement. */
5984 gsi_remove (&gsi, true);
5986 /* Setup code for sequential iteration goes in SEQ_START_BB. */
5987 gsi = gsi_start_bb (seq_start_bb);
5989 tree startvar = fd->loop.v;
5990 tree endvar = NULL_TREE;
5992 if (gimple_omp_for_combined_p (fd->for_stmt))
5994 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5995 ? gimple_omp_parallel_clauses (inner_stmt)
5996 : gimple_omp_for_clauses (inner_stmt);
5997 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5998 gcc_assert (innerc);
5999 startvar = OMP_CLAUSE_DECL (innerc);
6000 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6001 OMP_CLAUSE__LOOPTEMP_);
6002 gcc_assert (innerc);
6003 endvar = OMP_CLAUSE_DECL (innerc);
6005 t = fold_convert (itype, s0);
6006 t = fold_build2 (MULT_EXPR, itype, t, step);
6007 if (POINTER_TYPE_P (type))
6008 t = fold_build_pointer_plus (n1, t);
6009 else
6010 t = fold_build2 (PLUS_EXPR, type, t, n1);
6011 t = fold_convert (TREE_TYPE (startvar), t);
6012 t = force_gimple_operand_gsi (&gsi, t,
6013 DECL_P (startvar)
6014 && TREE_ADDRESSABLE (startvar),
6015 NULL_TREE, false, GSI_CONTINUE_LINKING);
6016 stmt = gimple_build_assign (startvar, t);
6017 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6019 t = fold_convert (itype, e0);
6020 t = fold_build2 (MULT_EXPR, itype, t, step);
6021 if (POINTER_TYPE_P (type))
6022 t = fold_build_pointer_plus (n1, t);
6023 else
6024 t = fold_build2 (PLUS_EXPR, type, t, n1);
6025 t = fold_convert (TREE_TYPE (startvar), t);
6026 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6027 false, GSI_CONTINUE_LINKING);
6028 if (endvar)
6030 stmt = gimple_build_assign (endvar, e);
6031 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6032 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6033 stmt = gimple_build_assign (fd->loop.v, e);
6034 else
6035 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6036 NULL_TREE);
6037 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6039 if (fd->collapse > 1)
6040 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6042 if (!broken_loop)
6044 /* The code controlling the sequential loop replaces the
6045 GIMPLE_OMP_CONTINUE. */
6046 gsi = gsi_last_bb (cont_bb);
6047 stmt = gsi_stmt (gsi);
6048 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6049 vmain = gimple_omp_continue_control_use (stmt);
6050 vback = gimple_omp_continue_control_def (stmt);
6052 if (!gimple_omp_for_combined_p (fd->for_stmt))
6054 if (POINTER_TYPE_P (type))
6055 t = fold_build_pointer_plus (vmain, step);
6056 else
6057 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6058 t = force_gimple_operand_gsi (&gsi, t,
6059 DECL_P (vback)
6060 && TREE_ADDRESSABLE (vback),
6061 NULL_TREE, true, GSI_SAME_STMT);
6062 stmt = gimple_build_assign (vback, t);
6063 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6065 t = build2 (fd->loop.cond_code, boolean_type_node,
6066 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6067 ? t : vback, e);
6068 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6071 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6072 gsi_remove (&gsi, true);
6074 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6075 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6078 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6079 gsi = gsi_last_bb (exit_bb);
6080 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6082 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6083 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6085 gsi_remove (&gsi, true);
6087 /* Connect all the blocks. */
6088 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6089 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6090 ep = find_edge (entry_bb, second_bb);
6091 ep->flags = EDGE_TRUE_VALUE;
6092 ep->probability = REG_BR_PROB_BASE / 4;
6093 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6094 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6096 if (!broken_loop)
6098 ep = find_edge (cont_bb, body_bb);
6099 if (gimple_omp_for_combined_p (fd->for_stmt))
6101 remove_edge (ep);
6102 ep = NULL;
6104 else if (fd->collapse > 1)
6106 remove_edge (ep);
6107 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6109 else
6110 ep->flags = EDGE_TRUE_VALUE;
6111 find_edge (cont_bb, fin_bb)->flags
6112 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6115 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6116 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6117 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6119 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6120 recompute_dominator (CDI_DOMINATORS, body_bb));
6121 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6122 recompute_dominator (CDI_DOMINATORS, fin_bb));
6124 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6126 struct loop *loop = alloc_loop ();
6127 loop->header = body_bb;
6128 if (collapse_bb == NULL)
6129 loop->latch = cont_bb;
6130 add_loop (loop, body_bb->loop_father);
6135 /* A subroutine of expand_omp_for. Generate code for a parallel
6136 loop with static schedule and a specified chunk size. Given
6137 parameters:
6139 for (V = N1; V cond N2; V += STEP) BODY;
6141 where COND is "<" or ">", we generate pseudocode
6143 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6144 if (cond is <)
6145 adj = STEP - 1;
6146 else
6147 adj = STEP + 1;
6148 if ((__typeof (V)) -1 > 0 && cond is >)
6149 n = -(adj + N2 - N1) / -STEP;
6150 else
6151 n = (adj + N2 - N1) / STEP;
6152 trip = 0;
6153 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6154 here so that V is defined
6155 if the loop is not entered
6157 s0 = (trip * nthreads + threadid) * CHUNK;
6158 e0 = min(s0 + CHUNK, n);
6159 if (s0 < n) goto L1; else goto L4;
6161 V = s0 * STEP + N1;
6162 e = e0 * STEP + N1;
6164 BODY;
6165 V += STEP;
6166 if (V cond e) goto L2; else goto L3;
6168 trip += 1;
6169 goto L0;
6173 static void
6174 expand_omp_for_static_chunk (struct omp_region *region,
6175 struct omp_for_data *fd, gimple inner_stmt)
6177 tree n, s0, e0, e, t;
6178 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6179 tree type, itype, vmain, vback, vextra;
6180 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6181 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6182 gimple_stmt_iterator gsi;
6183 gimple stmt;
6184 edge se;
6185 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6186 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6187 bool broken_loop = region->cont == NULL;
6188 tree *counts = NULL;
6189 tree n1, n2, step;
6191 itype = type = TREE_TYPE (fd->loop.v);
6192 if (POINTER_TYPE_P (type))
6193 itype = signed_type_for (type);
6195 entry_bb = region->entry;
6196 se = split_block (entry_bb, last_stmt (entry_bb));
6197 entry_bb = se->src;
6198 iter_part_bb = se->dest;
6199 cont_bb = region->cont;
6200 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6201 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6202 gcc_assert (broken_loop
6203 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6204 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6205 body_bb = single_succ (seq_start_bb);
6206 if (!broken_loop)
6208 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6209 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6210 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6212 exit_bb = region->exit;
6214 /* Trip and adjustment setup goes in ENTRY_BB. */
6215 gsi = gsi_last_bb (entry_bb);
6216 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6218 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6220 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6221 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6224 if (fd->collapse > 1)
6226 int first_zero_iter = -1;
6227 basic_block l2_dom_bb = NULL;
6229 counts = XALLOCAVEC (tree, fd->collapse);
6230 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6231 fin_bb, first_zero_iter,
6232 l2_dom_bb);
6233 t = NULL_TREE;
6235 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6236 t = integer_one_node;
6237 else
6238 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6239 fold_convert (type, fd->loop.n1),
6240 fold_convert (type, fd->loop.n2));
6241 if (fd->collapse == 1
6242 && TYPE_UNSIGNED (type)
6243 && (t == NULL_TREE || !integer_onep (t)))
6245 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6246 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6247 true, GSI_SAME_STMT);
6248 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6249 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6250 true, GSI_SAME_STMT);
6251 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6252 NULL_TREE, NULL_TREE);
6253 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6254 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6255 expand_omp_regimplify_p, NULL, NULL)
6256 || walk_tree (gimple_cond_rhs_ptr (stmt),
6257 expand_omp_regimplify_p, NULL, NULL))
6259 gsi = gsi_for_stmt (stmt);
6260 gimple_regimplify_operands (stmt, &gsi);
6262 se = split_block (entry_bb, stmt);
6263 se->flags = EDGE_TRUE_VALUE;
6264 entry_bb = se->dest;
6265 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6266 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6267 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6268 if (gimple_in_ssa_p (cfun))
6270 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6271 for (gsi = gsi_start_phis (fin_bb);
6272 !gsi_end_p (gsi); gsi_next (&gsi))
6274 gimple phi = gsi_stmt (gsi);
6275 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6276 se, UNKNOWN_LOCATION);
6279 gsi = gsi_last_bb (entry_bb);
6282 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6283 t = fold_convert (itype, t);
6284 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6285 true, GSI_SAME_STMT);
6287 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6288 t = fold_convert (itype, t);
6289 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6290 true, GSI_SAME_STMT);
6292 n1 = fd->loop.n1;
6293 n2 = fd->loop.n2;
6294 step = fd->loop.step;
6295 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6297 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6298 OMP_CLAUSE__LOOPTEMP_);
6299 gcc_assert (innerc);
6300 n1 = OMP_CLAUSE_DECL (innerc);
6301 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6302 OMP_CLAUSE__LOOPTEMP_);
6303 gcc_assert (innerc);
6304 n2 = OMP_CLAUSE_DECL (innerc);
6306 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6307 true, NULL_TREE, true, GSI_SAME_STMT);
6308 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6309 true, NULL_TREE, true, GSI_SAME_STMT);
6310 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6311 true, NULL_TREE, true, GSI_SAME_STMT);
6312 fd->chunk_size
6313 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
6314 true, NULL_TREE, true, GSI_SAME_STMT);
6316 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6317 t = fold_build2 (PLUS_EXPR, itype, step, t);
6318 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6319 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6320 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6321 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6322 fold_build1 (NEGATE_EXPR, itype, t),
6323 fold_build1 (NEGATE_EXPR, itype, step));
6324 else
6325 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6326 t = fold_convert (itype, t);
6327 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6328 true, GSI_SAME_STMT);
6330 trip_var = create_tmp_reg (itype, ".trip");
6331 if (gimple_in_ssa_p (cfun))
6333 trip_init = make_ssa_name (trip_var, NULL);
6334 trip_main = make_ssa_name (trip_var, NULL);
6335 trip_back = make_ssa_name (trip_var, NULL);
6337 else
6339 trip_init = trip_var;
6340 trip_main = trip_var;
6341 trip_back = trip_var;
6344 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6345 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6347 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6348 t = fold_build2 (MULT_EXPR, itype, t, step);
6349 if (POINTER_TYPE_P (type))
6350 t = fold_build_pointer_plus (n1, t);
6351 else
6352 t = fold_build2 (PLUS_EXPR, type, t, n1);
6353 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6354 true, GSI_SAME_STMT);
6356 /* Remove the GIMPLE_OMP_FOR. */
6357 gsi_remove (&gsi, true);
6359 /* Iteration space partitioning goes in ITER_PART_BB. */
6360 gsi = gsi_last_bb (iter_part_bb);
6362 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6363 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6364 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6365 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6366 false, GSI_CONTINUE_LINKING);
6368 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6369 t = fold_build2 (MIN_EXPR, itype, t, n);
6370 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6371 false, GSI_CONTINUE_LINKING);
6373 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6374 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6376 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6377 gsi = gsi_start_bb (seq_start_bb);
6379 tree startvar = fd->loop.v;
6380 tree endvar = NULL_TREE;
6382 if (gimple_omp_for_combined_p (fd->for_stmt))
6384 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6385 ? gimple_omp_parallel_clauses (inner_stmt)
6386 : gimple_omp_for_clauses (inner_stmt);
6387 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6388 gcc_assert (innerc);
6389 startvar = OMP_CLAUSE_DECL (innerc);
6390 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6391 OMP_CLAUSE__LOOPTEMP_);
6392 gcc_assert (innerc);
6393 endvar = OMP_CLAUSE_DECL (innerc);
6396 t = fold_convert (itype, s0);
6397 t = fold_build2 (MULT_EXPR, itype, t, step);
6398 if (POINTER_TYPE_P (type))
6399 t = fold_build_pointer_plus (n1, t);
6400 else
6401 t = fold_build2 (PLUS_EXPR, type, t, n1);
6402 t = fold_convert (TREE_TYPE (startvar), t);
6403 t = force_gimple_operand_gsi (&gsi, t,
6404 DECL_P (startvar)
6405 && TREE_ADDRESSABLE (startvar),
6406 NULL_TREE, false, GSI_CONTINUE_LINKING);
6407 stmt = gimple_build_assign (startvar, t);
6408 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6410 t = fold_convert (itype, e0);
6411 t = fold_build2 (MULT_EXPR, itype, t, step);
6412 if (POINTER_TYPE_P (type))
6413 t = fold_build_pointer_plus (n1, t);
6414 else
6415 t = fold_build2 (PLUS_EXPR, type, t, n1);
6416 t = fold_convert (TREE_TYPE (startvar), t);
6417 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6418 false, GSI_CONTINUE_LINKING);
6419 if (endvar)
6421 stmt = gimple_build_assign (endvar, e);
6422 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6423 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6424 stmt = gimple_build_assign (fd->loop.v, e);
6425 else
6426 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6427 NULL_TREE);
6428 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6430 if (fd->collapse > 1)
6431 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6433 if (!broken_loop)
6435 /* The code controlling the sequential loop goes in CONT_BB,
6436 replacing the GIMPLE_OMP_CONTINUE. */
6437 gsi = gsi_last_bb (cont_bb);
6438 stmt = gsi_stmt (gsi);
6439 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6440 vmain = gimple_omp_continue_control_use (stmt);
6441 vback = gimple_omp_continue_control_def (stmt);
6443 if (!gimple_omp_for_combined_p (fd->for_stmt))
6445 if (POINTER_TYPE_P (type))
6446 t = fold_build_pointer_plus (vmain, step);
6447 else
6448 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6449 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
6450 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6451 true, GSI_SAME_STMT);
6452 stmt = gimple_build_assign (vback, t);
6453 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6455 t = build2 (fd->loop.cond_code, boolean_type_node,
6456 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6457 ? t : vback, e);
6458 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6461 /* Remove GIMPLE_OMP_CONTINUE. */
6462 gsi_remove (&gsi, true);
6464 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6465 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6467 /* Trip update code goes into TRIP_UPDATE_BB. */
6468 gsi = gsi_start_bb (trip_update_bb);
6470 t = build_int_cst (itype, 1);
6471 t = build2 (PLUS_EXPR, itype, trip_main, t);
6472 stmt = gimple_build_assign (trip_back, t);
6473 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6476 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6477 gsi = gsi_last_bb (exit_bb);
6478 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6480 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6481 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6483 gsi_remove (&gsi, true);
6485 /* Connect the new blocks. */
6486 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6487 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6489 if (!broken_loop)
6491 se = find_edge (cont_bb, body_bb);
6492 if (gimple_omp_for_combined_p (fd->for_stmt))
6494 remove_edge (se);
6495 se = NULL;
6497 else if (fd->collapse > 1)
6499 remove_edge (se);
6500 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6502 else
6503 se->flags = EDGE_TRUE_VALUE;
6504 find_edge (cont_bb, trip_update_bb)->flags
6505 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6507 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6510 if (gimple_in_ssa_p (cfun))
6512 gimple_stmt_iterator psi;
6513 gimple phi;
6514 edge re, ene;
6515 edge_var_map_vector *head;
6516 edge_var_map *vm;
6517 size_t i;
6519 gcc_assert (fd->collapse == 1 && !broken_loop);
6521 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6522 remove arguments of the phi nodes in fin_bb. We need to create
6523 appropriate phi nodes in iter_part_bb instead. */
6524 se = single_pred_edge (fin_bb);
6525 re = single_succ_edge (trip_update_bb);
6526 head = redirect_edge_var_map_vector (re);
6527 ene = single_succ_edge (entry_bb);
6529 psi = gsi_start_phis (fin_bb);
6530 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6531 gsi_next (&psi), ++i)
6533 gimple nphi;
6534 source_location locus;
6536 phi = gsi_stmt (psi);
6537 t = gimple_phi_result (phi);
6538 gcc_assert (t == redirect_edge_var_map_result (vm));
6539 nphi = create_phi_node (t, iter_part_bb);
6541 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6542 locus = gimple_phi_arg_location_from_edge (phi, se);
6544 /* A special case -- fd->loop.v is not yet computed in
6545 iter_part_bb, we need to use vextra instead. */
6546 if (t == fd->loop.v)
6547 t = vextra;
6548 add_phi_arg (nphi, t, ene, locus);
6549 locus = redirect_edge_var_map_location (vm);
6550 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6552 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6553 redirect_edge_var_map_clear (re);
6554 while (1)
6556 psi = gsi_start_phis (fin_bb);
6557 if (gsi_end_p (psi))
6558 break;
6559 remove_phi_node (&psi, false);
6562 /* Make phi node for trip. */
6563 phi = create_phi_node (trip_main, iter_part_bb);
6564 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6565 UNKNOWN_LOCATION);
6566 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6567 UNKNOWN_LOCATION);
6570 if (!broken_loop)
6571 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6572 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6573 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6574 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6575 recompute_dominator (CDI_DOMINATORS, fin_bb));
6576 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6577 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6578 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6579 recompute_dominator (CDI_DOMINATORS, body_bb));
6581 if (!broken_loop)
6583 struct loop *trip_loop = alloc_loop ();
6584 trip_loop->header = iter_part_bb;
6585 trip_loop->latch = trip_update_bb;
6586 add_loop (trip_loop, iter_part_bb->loop_father);
6588 if (!gimple_omp_for_combined_p (fd->for_stmt))
6590 struct loop *loop = alloc_loop ();
6591 loop->header = body_bb;
6592 if (collapse_bb == NULL)
6593 loop->latch = cont_bb;
6594 add_loop (loop, trip_loop);
6600 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6601 loop. Given parameters:
6603 for (V = N1; V cond N2; V += STEP) BODY;
6605 where COND is "<" or ">", we generate pseudocode
6607 V = N1;
6608 goto L1;
6610 BODY;
6611 V += STEP;
6613 if (V cond N2) goto L0; else goto L2;
6616 For collapsed loops, given parameters:
6617 collapse(3)
6618 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6619 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6620 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6621 BODY;
6623 we generate pseudocode
6625 if (cond3 is <)
6626 adj = STEP3 - 1;
6627 else
6628 adj = STEP3 + 1;
6629 count3 = (adj + N32 - N31) / STEP3;
6630 if (cond2 is <)
6631 adj = STEP2 - 1;
6632 else
6633 adj = STEP2 + 1;
6634 count2 = (adj + N22 - N21) / STEP2;
6635 if (cond1 is <)
6636 adj = STEP1 - 1;
6637 else
6638 adj = STEP1 + 1;
6639 count1 = (adj + N12 - N11) / STEP1;
6640 count = count1 * count2 * count3;
6641 V = 0;
6642 V1 = N11;
6643 V2 = N21;
6644 V3 = N31;
6645 goto L1;
6647 BODY;
6648 V += 1;
6649 V3 += STEP3;
6650 V2 += (V3 cond3 N32) ? 0 : STEP2;
6651 V3 = (V3 cond3 N32) ? V3 : N31;
6652 V1 += (V2 cond2 N22) ? 0 : STEP1;
6653 V2 = (V2 cond2 N22) ? V2 : N21;
6655 if (V < count) goto L0; else goto L2;
6660 static void
6661 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
6663 tree type, t;
6664 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
6665 gimple_stmt_iterator gsi;
6666 gimple stmt;
6667 bool broken_loop = region->cont == NULL;
6668 edge e, ne;
6669 tree *counts = NULL;
6670 int i;
6671 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6672 OMP_CLAUSE_SAFELEN);
6673 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6674 OMP_CLAUSE__SIMDUID_);
6675 tree n1, n2;
6677 type = TREE_TYPE (fd->loop.v);
6678 entry_bb = region->entry;
6679 cont_bb = region->cont;
6680 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6681 gcc_assert (broken_loop
6682 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6683 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6684 if (!broken_loop)
6686 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6687 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6688 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6689 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6691 else
6693 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6694 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6695 l2_bb = single_succ (l1_bb);
6697 exit_bb = region->exit;
6698 l2_dom_bb = NULL;
6700 gsi = gsi_last_bb (entry_bb);
6702 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6703 /* Not needed in SSA form right now. */
6704 gcc_assert (!gimple_in_ssa_p (cfun));
6705 if (fd->collapse > 1)
6707 int first_zero_iter = -1;
6708 basic_block zero_iter_bb = l2_bb;
6710 counts = XALLOCAVEC (tree, fd->collapse);
6711 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6712 zero_iter_bb, first_zero_iter,
6713 l2_dom_bb);
6715 if (l2_dom_bb == NULL)
6716 l2_dom_bb = l1_bb;
6718 n1 = fd->loop.n1;
6719 n2 = fd->loop.n2;
6720 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6722 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6723 OMP_CLAUSE__LOOPTEMP_);
6724 gcc_assert (innerc);
6725 n1 = OMP_CLAUSE_DECL (innerc);
6726 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6727 OMP_CLAUSE__LOOPTEMP_);
6728 gcc_assert (innerc);
6729 n2 = OMP_CLAUSE_DECL (innerc);
6730 expand_omp_build_assign (&gsi, fd->loop.v,
6731 fold_convert (type, n1));
6732 if (fd->collapse > 1)
6734 gsi_prev (&gsi);
6735 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
6736 gsi_next (&gsi);
6739 else
6741 expand_omp_build_assign (&gsi, fd->loop.v,
6742 fold_convert (type, fd->loop.n1));
6743 if (fd->collapse > 1)
6744 for (i = 0; i < fd->collapse; i++)
6746 tree itype = TREE_TYPE (fd->loops[i].v);
6747 if (POINTER_TYPE_P (itype))
6748 itype = signed_type_for (itype);
6749 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
6750 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6754 /* Remove the GIMPLE_OMP_FOR statement. */
6755 gsi_remove (&gsi, true);
6757 if (!broken_loop)
6759 /* Code to control the increment goes in the CONT_BB. */
6760 gsi = gsi_last_bb (cont_bb);
6761 stmt = gsi_stmt (gsi);
6762 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6764 if (POINTER_TYPE_P (type))
6765 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
6766 else
6767 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
6768 expand_omp_build_assign (&gsi, fd->loop.v, t);
6770 if (fd->collapse > 1)
6772 i = fd->collapse - 1;
6773 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
6775 t = fold_convert (sizetype, fd->loops[i].step);
6776 t = fold_build_pointer_plus (fd->loops[i].v, t);
6778 else
6780 t = fold_convert (TREE_TYPE (fd->loops[i].v),
6781 fd->loops[i].step);
6782 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
6783 fd->loops[i].v, t);
6785 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6787 for (i = fd->collapse - 1; i > 0; i--)
6789 tree itype = TREE_TYPE (fd->loops[i].v);
6790 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
6791 if (POINTER_TYPE_P (itype2))
6792 itype2 = signed_type_for (itype2);
6793 t = build3 (COND_EXPR, itype2,
6794 build2 (fd->loops[i].cond_code, boolean_type_node,
6795 fd->loops[i].v,
6796 fold_convert (itype, fd->loops[i].n2)),
6797 build_int_cst (itype2, 0),
6798 fold_convert (itype2, fd->loops[i - 1].step));
6799 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
6800 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
6801 else
6802 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
6803 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
6805 t = build3 (COND_EXPR, itype,
6806 build2 (fd->loops[i].cond_code, boolean_type_node,
6807 fd->loops[i].v,
6808 fold_convert (itype, fd->loops[i].n2)),
6809 fd->loops[i].v,
6810 fold_convert (itype, fd->loops[i].n1));
6811 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6815 /* Remove GIMPLE_OMP_CONTINUE. */
6816 gsi_remove (&gsi, true);
6819 /* Emit the condition in L1_BB. */
6820 gsi = gsi_start_bb (l1_bb);
6822 t = fold_convert (type, n2);
6823 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6824 false, GSI_CONTINUE_LINKING);
6825 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
6826 stmt = gimple_build_cond_empty (t);
6827 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6828 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
6829 NULL, NULL)
6830 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
6831 NULL, NULL))
6833 gsi = gsi_for_stmt (stmt);
6834 gimple_regimplify_operands (stmt, &gsi);
6837 /* Remove GIMPLE_OMP_RETURN. */
6838 gsi = gsi_last_bb (exit_bb);
6839 gsi_remove (&gsi, true);
6841 /* Connect the new blocks. */
6842 remove_edge (FALLTHRU_EDGE (entry_bb));
6844 if (!broken_loop)
6846 remove_edge (BRANCH_EDGE (entry_bb));
6847 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6849 e = BRANCH_EDGE (l1_bb);
6850 ne = FALLTHRU_EDGE (l1_bb);
6851 e->flags = EDGE_TRUE_VALUE;
6853 else
6855 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6857 ne = single_succ_edge (l1_bb);
6858 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6861 ne->flags = EDGE_FALSE_VALUE;
6862 e->probability = REG_BR_PROB_BASE * 7 / 8;
6863 ne->probability = REG_BR_PROB_BASE / 8;
6865 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6866 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6867 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6869 if (!broken_loop)
6871 struct loop *loop = alloc_loop ();
6872 loop->header = l1_bb;
6873 loop->latch = cont_bb;
6874 add_loop (loop, l1_bb->loop_father);
6875 if (safelen == NULL_TREE)
6876 loop->safelen = INT_MAX;
6877 else
6879 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
6880 if (!tree_fits_uhwi_p (safelen)
6881 || tree_to_uhwi (safelen) > INT_MAX)
6882 loop->safelen = INT_MAX;
6883 else
6884 loop->safelen = tree_to_uhwi (safelen);
6885 if (loop->safelen == 1)
6886 loop->safelen = 0;
6888 if (simduid)
6890 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
6891 cfun->has_simduid_loops = true;
6893 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
6894 the loop. */
6895 if ((flag_tree_loop_vectorize
6896 || (!global_options_set.x_flag_tree_loop_vectorize
6897 && !global_options_set.x_flag_tree_vectorize))
6898 && flag_tree_loop_optimize
6899 && loop->safelen > 1)
6901 loop->force_vectorize = true;
6902 cfun->has_force_vectorize_loops = true;
6908 /* Expand the OpenMP loop defined by REGION. */
6910 static void
6911 expand_omp_for (struct omp_region *region, gimple inner_stmt)
6913 struct omp_for_data fd;
6914 struct omp_for_data_loop *loops;
6916 loops
6917 = (struct omp_for_data_loop *)
6918 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
6919 * sizeof (struct omp_for_data_loop));
6920 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
6921 region->sched_kind = fd.sched_kind;
6923 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
6924 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6925 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6926 if (region->cont)
6928 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
6929 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6930 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6932 else
6933 /* If there isn't a continue then this is a degerate case where
6934 the introduction of abnormal edges during lowering will prevent
6935 original loops from being detected. Fix that up. */
6936 loops_state_set (LOOPS_NEED_FIXUP);
6938 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
6939 expand_omp_simd (region, &fd);
6940 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
6941 && !fd.have_ordered)
6943 if (fd.chunk_size == NULL)
6944 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
6945 else
6946 expand_omp_for_static_chunk (region, &fd, inner_stmt);
6948 else
6950 int fn_index, start_ix, next_ix;
6952 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
6953 == GF_OMP_FOR_KIND_FOR);
6954 if (fd.chunk_size == NULL
6955 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
6956 fd.chunk_size = integer_zero_node;
6957 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6958 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
6959 ? 3 : fd.sched_kind;
6960 fn_index += fd.have_ordered * 4;
6961 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
6962 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
6963 if (fd.iter_type == long_long_unsigned_type_node)
6965 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
6966 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
6967 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
6968 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
6970 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
6971 (enum built_in_function) next_ix, inner_stmt);
6974 if (gimple_in_ssa_p (cfun))
6975 update_ssa (TODO_update_ssa_only_virtuals);
6979 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
6981 v = GOMP_sections_start (n);
6983 switch (v)
6985 case 0:
6986 goto L2;
6987 case 1:
6988 section 1;
6989 goto L1;
6990 case 2:
6992 case n:
6994 default:
6995 abort ();
6998 v = GOMP_sections_next ();
6999 goto L0;
7001 reduction;
7003 If this is a combined parallel sections, replace the call to
7004 GOMP_sections_start with call to GOMP_sections_next. */
7006 static void
7007 expand_omp_sections (struct omp_region *region)
7009 tree t, u, vin = NULL, vmain, vnext, l2;
7010 unsigned len;
7011 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7012 gimple_stmt_iterator si, switch_si;
7013 gimple sections_stmt, stmt, cont;
7014 edge_iterator ei;
7015 edge e;
7016 struct omp_region *inner;
7017 unsigned i, casei;
7018 bool exit_reachable = region->cont != NULL;
7020 gcc_assert (region->exit != NULL);
7021 entry_bb = region->entry;
7022 l0_bb = single_succ (entry_bb);
7023 l1_bb = region->cont;
7024 l2_bb = region->exit;
7025 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7026 l2 = gimple_block_label (l2_bb);
7027 else
7029 /* This can happen if there are reductions. */
7030 len = EDGE_COUNT (l0_bb->succs);
7031 gcc_assert (len > 0);
7032 e = EDGE_SUCC (l0_bb, len - 1);
7033 si = gsi_last_bb (e->dest);
7034 l2 = NULL_TREE;
7035 if (gsi_end_p (si)
7036 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7037 l2 = gimple_block_label (e->dest);
7038 else
7039 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7041 si = gsi_last_bb (e->dest);
7042 if (gsi_end_p (si)
7043 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7045 l2 = gimple_block_label (e->dest);
7046 break;
7050 if (exit_reachable)
7051 default_bb = create_empty_bb (l1_bb->prev_bb);
7052 else
7053 default_bb = create_empty_bb (l0_bb);
7055 /* We will build a switch() with enough cases for all the
7056 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7057 and a default case to abort if something goes wrong. */
7058 len = EDGE_COUNT (l0_bb->succs);
7060 /* Use vec::quick_push on label_vec throughout, since we know the size
7061 in advance. */
7062 auto_vec<tree> label_vec (len);
7064 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7065 GIMPLE_OMP_SECTIONS statement. */
7066 si = gsi_last_bb (entry_bb);
7067 sections_stmt = gsi_stmt (si);
7068 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7069 vin = gimple_omp_sections_control (sections_stmt);
7070 if (!is_combined_parallel (region))
7072 /* If we are not inside a combined parallel+sections region,
7073 call GOMP_sections_start. */
7074 t = build_int_cst (unsigned_type_node, len - 1);
7075 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7076 stmt = gimple_build_call (u, 1, t);
7078 else
7080 /* Otherwise, call GOMP_sections_next. */
7081 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7082 stmt = gimple_build_call (u, 0);
7084 gimple_call_set_lhs (stmt, vin);
7085 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7086 gsi_remove (&si, true);
7088 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7089 L0_BB. */
7090 switch_si = gsi_last_bb (l0_bb);
7091 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7092 if (exit_reachable)
7094 cont = last_stmt (l1_bb);
7095 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7096 vmain = gimple_omp_continue_control_use (cont);
7097 vnext = gimple_omp_continue_control_def (cont);
7099 else
7101 vmain = vin;
7102 vnext = NULL_TREE;
7105 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7106 label_vec.quick_push (t);
7107 i = 1;
7109 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7110 for (inner = region->inner, casei = 1;
7111 inner;
7112 inner = inner->next, i++, casei++)
7114 basic_block s_entry_bb, s_exit_bb;
7116 /* Skip optional reduction region. */
7117 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7119 --i;
7120 --casei;
7121 continue;
7124 s_entry_bb = inner->entry;
7125 s_exit_bb = inner->exit;
7127 t = gimple_block_label (s_entry_bb);
7128 u = build_int_cst (unsigned_type_node, casei);
7129 u = build_case_label (u, NULL, t);
7130 label_vec.quick_push (u);
7132 si = gsi_last_bb (s_entry_bb);
7133 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7134 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7135 gsi_remove (&si, true);
7136 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7138 if (s_exit_bb == NULL)
7139 continue;
7141 si = gsi_last_bb (s_exit_bb);
7142 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7143 gsi_remove (&si, true);
7145 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7148 /* Error handling code goes in DEFAULT_BB. */
7149 t = gimple_block_label (default_bb);
7150 u = build_case_label (NULL, NULL, t);
7151 make_edge (l0_bb, default_bb, 0);
7152 add_bb_to_loop (default_bb, current_loops->tree_root);
7154 stmt = gimple_build_switch (vmain, u, label_vec);
7155 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7156 gsi_remove (&switch_si, true);
7158 si = gsi_start_bb (default_bb);
7159 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7160 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7162 if (exit_reachable)
7164 tree bfn_decl;
7166 /* Code to get the next section goes in L1_BB. */
7167 si = gsi_last_bb (l1_bb);
7168 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7170 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7171 stmt = gimple_build_call (bfn_decl, 0);
7172 gimple_call_set_lhs (stmt, vnext);
7173 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7174 gsi_remove (&si, true);
7176 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7179 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7180 si = gsi_last_bb (l2_bb);
7181 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7182 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7183 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7184 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7185 else
7186 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7187 stmt = gimple_build_call (t, 0);
7188 if (gimple_omp_return_lhs (gsi_stmt (si)))
7189 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7190 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7191 gsi_remove (&si, true);
7193 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7197 /* Expand code for an OpenMP single directive. We've already expanded
7198 much of the code, here we simply place the GOMP_barrier call. */
7200 static void
7201 expand_omp_single (struct omp_region *region)
7203 basic_block entry_bb, exit_bb;
7204 gimple_stmt_iterator si;
7206 entry_bb = region->entry;
7207 exit_bb = region->exit;
7209 si = gsi_last_bb (entry_bb);
7210 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7211 gsi_remove (&si, true);
7212 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7214 si = gsi_last_bb (exit_bb);
7215 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7217 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7218 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7220 gsi_remove (&si, true);
7221 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7225 /* Generic expansion for OpenMP synchronization directives: master,
7226 ordered and critical. All we need to do here is remove the entry
7227 and exit markers for REGION. */
7229 static void
7230 expand_omp_synch (struct omp_region *region)
7232 basic_block entry_bb, exit_bb;
7233 gimple_stmt_iterator si;
7235 entry_bb = region->entry;
7236 exit_bb = region->exit;
7238 si = gsi_last_bb (entry_bb);
7239 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7240 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7241 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7242 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7243 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7244 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7245 gsi_remove (&si, true);
7246 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7248 if (exit_bb)
7250 si = gsi_last_bb (exit_bb);
7251 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7252 gsi_remove (&si, true);
7253 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7257 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7258 operation as a normal volatile load. */
7260 static bool
7261 expand_omp_atomic_load (basic_block load_bb, tree addr,
7262 tree loaded_val, int index)
7264 enum built_in_function tmpbase;
7265 gimple_stmt_iterator gsi;
7266 basic_block store_bb;
7267 location_t loc;
7268 gimple stmt;
7269 tree decl, call, type, itype;
7271 gsi = gsi_last_bb (load_bb);
7272 stmt = gsi_stmt (gsi);
7273 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7274 loc = gimple_location (stmt);
7276 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7277 is smaller than word size, then expand_atomic_load assumes that the load
7278 is atomic. We could avoid the builtin entirely in this case. */
7280 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7281 decl = builtin_decl_explicit (tmpbase);
7282 if (decl == NULL_TREE)
7283 return false;
7285 type = TREE_TYPE (loaded_val);
7286 itype = TREE_TYPE (TREE_TYPE (decl));
7288 call = build_call_expr_loc (loc, decl, 2, addr,
7289 build_int_cst (NULL,
7290 gimple_omp_atomic_seq_cst_p (stmt)
7291 ? MEMMODEL_SEQ_CST
7292 : MEMMODEL_RELAXED));
7293 if (!useless_type_conversion_p (type, itype))
7294 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7295 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7297 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7298 gsi_remove (&gsi, true);
7300 store_bb = single_succ (load_bb);
7301 gsi = gsi_last_bb (store_bb);
7302 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7303 gsi_remove (&gsi, true);
7305 if (gimple_in_ssa_p (cfun))
7306 update_ssa (TODO_update_ssa_no_phi);
7308 return true;
7311 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7312 operation as a normal volatile store. */
7314 static bool
7315 expand_omp_atomic_store (basic_block load_bb, tree addr,
7316 tree loaded_val, tree stored_val, int index)
7318 enum built_in_function tmpbase;
7319 gimple_stmt_iterator gsi;
7320 basic_block store_bb = single_succ (load_bb);
7321 location_t loc;
7322 gimple stmt;
7323 tree decl, call, type, itype;
7324 enum machine_mode imode;
7325 bool exchange;
7327 gsi = gsi_last_bb (load_bb);
7328 stmt = gsi_stmt (gsi);
7329 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7331 /* If the load value is needed, then this isn't a store but an exchange. */
7332 exchange = gimple_omp_atomic_need_value_p (stmt);
7334 gsi = gsi_last_bb (store_bb);
7335 stmt = gsi_stmt (gsi);
7336 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7337 loc = gimple_location (stmt);
7339 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7340 is smaller than word size, then expand_atomic_store assumes that the store
7341 is atomic. We could avoid the builtin entirely in this case. */
7343 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7344 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7345 decl = builtin_decl_explicit (tmpbase);
7346 if (decl == NULL_TREE)
7347 return false;
7349 type = TREE_TYPE (stored_val);
7351 /* Dig out the type of the function's second argument. */
7352 itype = TREE_TYPE (decl);
7353 itype = TYPE_ARG_TYPES (itype);
7354 itype = TREE_CHAIN (itype);
7355 itype = TREE_VALUE (itype);
7356 imode = TYPE_MODE (itype);
7358 if (exchange && !can_atomic_exchange_p (imode, true))
7359 return false;
7361 if (!useless_type_conversion_p (itype, type))
7362 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7363 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7364 build_int_cst (NULL,
7365 gimple_omp_atomic_seq_cst_p (stmt)
7366 ? MEMMODEL_SEQ_CST
7367 : MEMMODEL_RELAXED));
7368 if (exchange)
7370 if (!useless_type_conversion_p (type, itype))
7371 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7372 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7375 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7376 gsi_remove (&gsi, true);
7378 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7379 gsi = gsi_last_bb (load_bb);
7380 gsi_remove (&gsi, true);
7382 if (gimple_in_ssa_p (cfun))
7383 update_ssa (TODO_update_ssa_no_phi);
7385 return true;
7388 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7389 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7390 size of the data type, and thus usable to find the index of the builtin
7391 decl. Returns false if the expression is not of the proper form. */
7393 static bool
7394 expand_omp_atomic_fetch_op (basic_block load_bb,
7395 tree addr, tree loaded_val,
7396 tree stored_val, int index)
7398 enum built_in_function oldbase, newbase, tmpbase;
7399 tree decl, itype, call;
7400 tree lhs, rhs;
7401 basic_block store_bb = single_succ (load_bb);
7402 gimple_stmt_iterator gsi;
7403 gimple stmt;
7404 location_t loc;
7405 enum tree_code code;
7406 bool need_old, need_new;
7407 enum machine_mode imode;
7408 bool seq_cst;
7410 /* We expect to find the following sequences:
7412 load_bb:
7413 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7415 store_bb:
7416 val = tmp OP something; (or: something OP tmp)
7417 GIMPLE_OMP_STORE (val)
7419 ???FIXME: Allow a more flexible sequence.
7420 Perhaps use data flow to pick the statements.
7424 gsi = gsi_after_labels (store_bb);
7425 stmt = gsi_stmt (gsi);
7426 loc = gimple_location (stmt);
7427 if (!is_gimple_assign (stmt))
7428 return false;
7429 gsi_next (&gsi);
7430 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7431 return false;
7432 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7433 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7434 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7435 gcc_checking_assert (!need_old || !need_new);
7437 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7438 return false;
7440 /* Check for one of the supported fetch-op operations. */
7441 code = gimple_assign_rhs_code (stmt);
7442 switch (code)
7444 case PLUS_EXPR:
7445 case POINTER_PLUS_EXPR:
7446 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7447 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7448 break;
7449 case MINUS_EXPR:
7450 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7451 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7452 break;
7453 case BIT_AND_EXPR:
7454 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7455 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7456 break;
7457 case BIT_IOR_EXPR:
7458 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7459 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7460 break;
7461 case BIT_XOR_EXPR:
7462 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7463 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7464 break;
7465 default:
7466 return false;
7469 /* Make sure the expression is of the proper form. */
7470 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7471 rhs = gimple_assign_rhs2 (stmt);
7472 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7473 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7474 rhs = gimple_assign_rhs1 (stmt);
7475 else
7476 return false;
7478 tmpbase = ((enum built_in_function)
7479 ((need_new ? newbase : oldbase) + index + 1));
7480 decl = builtin_decl_explicit (tmpbase);
7481 if (decl == NULL_TREE)
7482 return false;
7483 itype = TREE_TYPE (TREE_TYPE (decl));
7484 imode = TYPE_MODE (itype);
7486 /* We could test all of the various optabs involved, but the fact of the
7487 matter is that (with the exception of i486 vs i586 and xadd) all targets
7488 that support any atomic operaton optab also implements compare-and-swap.
7489 Let optabs.c take care of expanding any compare-and-swap loop. */
7490 if (!can_compare_and_swap_p (imode, true))
7491 return false;
7493 gsi = gsi_last_bb (load_bb);
7494 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7496 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7497 It only requires that the operation happen atomically. Thus we can
7498 use the RELAXED memory model. */
7499 call = build_call_expr_loc (loc, decl, 3, addr,
7500 fold_convert_loc (loc, itype, rhs),
7501 build_int_cst (NULL,
7502 seq_cst ? MEMMODEL_SEQ_CST
7503 : MEMMODEL_RELAXED));
7505 if (need_old || need_new)
7507 lhs = need_old ? loaded_val : stored_val;
7508 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7509 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7511 else
7512 call = fold_convert_loc (loc, void_type_node, call);
7513 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7514 gsi_remove (&gsi, true);
7516 gsi = gsi_last_bb (store_bb);
7517 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7518 gsi_remove (&gsi, true);
7519 gsi = gsi_last_bb (store_bb);
7520 gsi_remove (&gsi, true);
7522 if (gimple_in_ssa_p (cfun))
7523 update_ssa (TODO_update_ssa_no_phi);
7525 return true;
7528 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7530 oldval = *addr;
7531 repeat:
7532 newval = rhs; // with oldval replacing *addr in rhs
7533 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7534 if (oldval != newval)
7535 goto repeat;
7537 INDEX is log2 of the size of the data type, and thus usable to find the
7538 index of the builtin decl. */
7540 static bool
7541 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7542 tree addr, tree loaded_val, tree stored_val,
7543 int index)
7545 tree loadedi, storedi, initial, new_storedi, old_vali;
7546 tree type, itype, cmpxchg, iaddr;
7547 gimple_stmt_iterator si;
7548 basic_block loop_header = single_succ (load_bb);
7549 gimple phi, stmt;
7550 edge e;
7551 enum built_in_function fncode;
7553 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7554 order to use the RELAXED memory model effectively. */
7555 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7556 + index + 1);
7557 cmpxchg = builtin_decl_explicit (fncode);
7558 if (cmpxchg == NULL_TREE)
7559 return false;
7560 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7561 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7563 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7564 return false;
7566 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7567 si = gsi_last_bb (load_bb);
7568 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7570 /* For floating-point values, we'll need to view-convert them to integers
7571 so that we can perform the atomic compare and swap. Simplify the
7572 following code by always setting up the "i"ntegral variables. */
7573 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7575 tree iaddr_val;
7577 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7578 true), NULL);
7579 iaddr_val
7580 = force_gimple_operand_gsi (&si,
7581 fold_convert (TREE_TYPE (iaddr), addr),
7582 false, NULL_TREE, true, GSI_SAME_STMT);
7583 stmt = gimple_build_assign (iaddr, iaddr_val);
7584 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7585 loadedi = create_tmp_var (itype, NULL);
7586 if (gimple_in_ssa_p (cfun))
7587 loadedi = make_ssa_name (loadedi, NULL);
7589 else
7591 iaddr = addr;
7592 loadedi = loaded_val;
7595 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7596 tree loaddecl = builtin_decl_explicit (fncode);
7597 if (loaddecl)
7598 initial
7599 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
7600 build_call_expr (loaddecl, 2, iaddr,
7601 build_int_cst (NULL_TREE,
7602 MEMMODEL_RELAXED)));
7603 else
7604 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
7605 build_int_cst (TREE_TYPE (iaddr), 0));
7607 initial
7608 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
7609 GSI_SAME_STMT);
7611 /* Move the value to the LOADEDI temporary. */
7612 if (gimple_in_ssa_p (cfun))
7614 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
7615 phi = create_phi_node (loadedi, loop_header);
7616 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
7617 initial);
7619 else
7620 gsi_insert_before (&si,
7621 gimple_build_assign (loadedi, initial),
7622 GSI_SAME_STMT);
7623 if (loadedi != loaded_val)
7625 gimple_stmt_iterator gsi2;
7626 tree x;
7628 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
7629 gsi2 = gsi_start_bb (loop_header);
7630 if (gimple_in_ssa_p (cfun))
7632 gimple stmt;
7633 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7634 true, GSI_SAME_STMT);
7635 stmt = gimple_build_assign (loaded_val, x);
7636 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
7638 else
7640 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
7641 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7642 true, GSI_SAME_STMT);
7645 gsi_remove (&si, true);
7647 si = gsi_last_bb (store_bb);
7648 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7650 if (iaddr == addr)
7651 storedi = stored_val;
7652 else
7653 storedi =
7654 force_gimple_operand_gsi (&si,
7655 build1 (VIEW_CONVERT_EXPR, itype,
7656 stored_val), true, NULL_TREE, true,
7657 GSI_SAME_STMT);
7659 /* Build the compare&swap statement. */
7660 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
7661 new_storedi = force_gimple_operand_gsi (&si,
7662 fold_convert (TREE_TYPE (loadedi),
7663 new_storedi),
7664 true, NULL_TREE,
7665 true, GSI_SAME_STMT);
7667 if (gimple_in_ssa_p (cfun))
7668 old_vali = loadedi;
7669 else
7671 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
7672 stmt = gimple_build_assign (old_vali, loadedi);
7673 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7675 stmt = gimple_build_assign (loadedi, new_storedi);
7676 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7679 /* Note that we always perform the comparison as an integer, even for
7680 floating point. This allows the atomic operation to properly
7681 succeed even with NaNs and -0.0. */
7682 stmt = gimple_build_cond_empty
7683 (build2 (NE_EXPR, boolean_type_node,
7684 new_storedi, old_vali));
7685 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7687 /* Update cfg. */
7688 e = single_succ_edge (store_bb);
7689 e->flags &= ~EDGE_FALLTHRU;
7690 e->flags |= EDGE_FALSE_VALUE;
7692 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
7694 /* Copy the new value to loadedi (we already did that before the condition
7695 if we are not in SSA). */
7696 if (gimple_in_ssa_p (cfun))
7698 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
7699 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
7702 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
7703 gsi_remove (&si, true);
7705 struct loop *loop = alloc_loop ();
7706 loop->header = loop_header;
7707 loop->latch = store_bb;
7708 add_loop (loop, loop_header->loop_father);
7710 if (gimple_in_ssa_p (cfun))
7711 update_ssa (TODO_update_ssa_no_phi);
7713 return true;
7716 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7718 GOMP_atomic_start ();
7719 *addr = rhs;
7720 GOMP_atomic_end ();
7722 The result is not globally atomic, but works so long as all parallel
7723 references are within #pragma omp atomic directives. According to
7724 responses received from omp@openmp.org, appears to be within spec.
7725 Which makes sense, since that's how several other compilers handle
7726 this situation as well.
7727 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
7728 expanding. STORED_VAL is the operand of the matching
7729 GIMPLE_OMP_ATOMIC_STORE.
7731 We replace
7732 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
7733 loaded_val = *addr;
7735 and replace
7736 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
7737 *addr = stored_val;
7740 static bool
7741 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
7742 tree addr, tree loaded_val, tree stored_val)
7744 gimple_stmt_iterator si;
7745 gimple stmt;
7746 tree t;
7748 si = gsi_last_bb (load_bb);
7749 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7751 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
7752 t = build_call_expr (t, 0);
7753 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7755 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
7756 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7757 gsi_remove (&si, true);
7759 si = gsi_last_bb (store_bb);
7760 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7762 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
7763 stored_val);
7764 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7766 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
7767 t = build_call_expr (t, 0);
7768 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7769 gsi_remove (&si, true);
7771 if (gimple_in_ssa_p (cfun))
7772 update_ssa (TODO_update_ssa_no_phi);
7773 return true;
7776 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
7777 using expand_omp_atomic_fetch_op. If it failed, we try to
7778 call expand_omp_atomic_pipeline, and if it fails too, the
7779 ultimate fallback is wrapping the operation in a mutex
7780 (expand_omp_atomic_mutex). REGION is the atomic region built
7781 by build_omp_regions_1(). */
7783 static void
7784 expand_omp_atomic (struct omp_region *region)
7786 basic_block load_bb = region->entry, store_bb = region->exit;
7787 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
7788 tree loaded_val = gimple_omp_atomic_load_lhs (load);
7789 tree addr = gimple_omp_atomic_load_rhs (load);
7790 tree stored_val = gimple_omp_atomic_store_val (store);
7791 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7792 HOST_WIDE_INT index;
7794 /* Make sure the type is one of the supported sizes. */
7795 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
7796 index = exact_log2 (index);
7797 if (index >= 0 && index <= 4)
7799 unsigned int align = TYPE_ALIGN_UNIT (type);
7801 /* __sync builtins require strict data alignment. */
7802 if (exact_log2 (align) >= index)
7804 /* Atomic load. */
7805 if (loaded_val == stored_val
7806 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7807 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7808 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7809 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
7810 return;
7812 /* Atomic store. */
7813 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7814 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7815 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7816 && store_bb == single_succ (load_bb)
7817 && first_stmt (store_bb) == store
7818 && expand_omp_atomic_store (load_bb, addr, loaded_val,
7819 stored_val, index))
7820 return;
7822 /* When possible, use specialized atomic update functions. */
7823 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
7824 && store_bb == single_succ (load_bb)
7825 && expand_omp_atomic_fetch_op (load_bb, addr,
7826 loaded_val, stored_val, index))
7827 return;
7829 /* If we don't have specialized __sync builtins, try and implement
7830 as a compare and swap loop. */
7831 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
7832 loaded_val, stored_val, index))
7833 return;
7837 /* The ultimate fallback is wrapping the operation in a mutex. */
7838 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
7842 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
7844 static void
7845 expand_omp_target (struct omp_region *region)
7847 basic_block entry_bb, exit_bb, new_bb;
7848 struct function *child_cfun = NULL;
7849 tree child_fn = NULL_TREE, block, t;
7850 gimple_stmt_iterator gsi;
7851 gimple entry_stmt, stmt;
7852 edge e;
7854 entry_stmt = last_stmt (region->entry);
7855 new_bb = region->entry;
7856 int kind = gimple_omp_target_kind (entry_stmt);
7857 if (kind == GF_OMP_TARGET_KIND_REGION)
7859 child_fn = gimple_omp_target_child_fn (entry_stmt);
7860 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7863 entry_bb = region->entry;
7864 exit_bb = region->exit;
7866 if (kind == GF_OMP_TARGET_KIND_REGION)
7868 unsigned srcidx, dstidx, num;
7870 /* If the target region needs data sent from the parent
7871 function, then the very first statement (except possible
7872 tree profile counter updates) of the parallel body
7873 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7874 &.OMP_DATA_O is passed as an argument to the child function,
7875 we need to replace it with the argument as seen by the child
7876 function.
7878 In most cases, this will end up being the identity assignment
7879 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7880 a function call that has been inlined, the original PARM_DECL
7881 .OMP_DATA_I may have been converted into a different local
7882 variable. In which case, we need to keep the assignment. */
7883 if (gimple_omp_target_data_arg (entry_stmt))
7885 basic_block entry_succ_bb = single_succ (entry_bb);
7886 gimple_stmt_iterator gsi;
7887 tree arg;
7888 gimple tgtcopy_stmt = NULL;
7889 tree sender
7890 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
7892 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7894 gcc_assert (!gsi_end_p (gsi));
7895 stmt = gsi_stmt (gsi);
7896 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7897 continue;
7899 if (gimple_num_ops (stmt) == 2)
7901 tree arg = gimple_assign_rhs1 (stmt);
7903 /* We're ignoring the subcode because we're
7904 effectively doing a STRIP_NOPS. */
7906 if (TREE_CODE (arg) == ADDR_EXPR
7907 && TREE_OPERAND (arg, 0) == sender)
7909 tgtcopy_stmt = stmt;
7910 break;
7915 gcc_assert (tgtcopy_stmt != NULL);
7916 arg = DECL_ARGUMENTS (child_fn);
7918 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
7919 gsi_remove (&gsi, true);
7922 /* Declare local variables needed in CHILD_CFUN. */
7923 block = DECL_INITIAL (child_fn);
7924 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7925 /* The gimplifier could record temporaries in target block
7926 rather than in containing function's local_decls chain,
7927 which would mean cgraph missed finalizing them. Do it now. */
7928 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7929 if (TREE_CODE (t) == VAR_DECL
7930 && TREE_STATIC (t)
7931 && !DECL_EXTERNAL (t))
7932 varpool_finalize_decl (t);
7933 DECL_SAVED_TREE (child_fn) = NULL;
7934 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7935 gimple_set_body (child_fn, NULL);
7936 TREE_USED (block) = 1;
7938 /* Reset DECL_CONTEXT on function arguments. */
7939 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7940 DECL_CONTEXT (t) = child_fn;
7942 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
7943 so that it can be moved to the child function. */
7944 gsi = gsi_last_bb (entry_bb);
7945 stmt = gsi_stmt (gsi);
7946 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
7947 && gimple_omp_target_kind (stmt)
7948 == GF_OMP_TARGET_KIND_REGION);
7949 gsi_remove (&gsi, true);
7950 e = split_block (entry_bb, stmt);
7951 entry_bb = e->dest;
7952 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7954 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
7955 if (exit_bb)
7957 gsi = gsi_last_bb (exit_bb);
7958 gcc_assert (!gsi_end_p (gsi)
7959 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7960 stmt = gimple_build_return (NULL);
7961 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7962 gsi_remove (&gsi, true);
7965 /* Move the target region into CHILD_CFUN. */
7967 block = gimple_block (entry_stmt);
7969 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7970 if (exit_bb)
7971 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7972 /* When the OMP expansion process cannot guarantee an up-to-date
7973 loop tree arrange for the child function to fixup loops. */
7974 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7975 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7977 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7978 num = vec_safe_length (child_cfun->local_decls);
7979 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7981 t = (*child_cfun->local_decls)[srcidx];
7982 if (DECL_CONTEXT (t) == cfun->decl)
7983 continue;
7984 if (srcidx != dstidx)
7985 (*child_cfun->local_decls)[dstidx] = t;
7986 dstidx++;
7988 if (dstidx != num)
7989 vec_safe_truncate (child_cfun->local_decls, dstidx);
7991 /* Inform the callgraph about the new function. */
7992 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
7993 cgraph_add_new_function (child_fn, true);
7995 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7996 fixed in a following pass. */
7997 push_cfun (child_cfun);
7998 rebuild_cgraph_edges ();
8000 /* Some EH regions might become dead, see PR34608. If
8001 pass_cleanup_cfg isn't the first pass to happen with the
8002 new child, these dead EH edges might cause problems.
8003 Clean them up now. */
8004 if (flag_exceptions)
8006 basic_block bb;
8007 bool changed = false;
8009 FOR_EACH_BB_FN (bb, cfun)
8010 changed |= gimple_purge_dead_eh_edges (bb);
8011 if (changed)
8012 cleanup_tree_cfg ();
8014 pop_cfun ();
8017 /* Emit a library call to launch the target region, or do data
8018 transfers. */
8019 tree t1, t2, t3, t4, device, cond, c, clauses;
8020 enum built_in_function start_ix;
8021 location_t clause_loc;
8023 clauses = gimple_omp_target_clauses (entry_stmt);
8025 if (kind == GF_OMP_TARGET_KIND_REGION)
8026 start_ix = BUILT_IN_GOMP_TARGET;
8027 else if (kind == GF_OMP_TARGET_KIND_DATA)
8028 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8029 else
8030 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8032 /* By default, the value of DEVICE is -1 (let runtime library choose)
8033 and there is no conditional. */
8034 cond = NULL_TREE;
8035 device = build_int_cst (integer_type_node, -1);
8037 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8038 if (c)
8039 cond = OMP_CLAUSE_IF_EXPR (c);
8041 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8042 if (c)
8044 device = OMP_CLAUSE_DEVICE_ID (c);
8045 clause_loc = OMP_CLAUSE_LOCATION (c);
8047 else
8048 clause_loc = gimple_location (entry_stmt);
8050 /* Ensure 'device' is of the correct type. */
8051 device = fold_convert_loc (clause_loc, integer_type_node, device);
8053 /* If we found the clause 'if (cond)', build
8054 (cond ? device : -2). */
8055 if (cond)
8057 cond = gimple_boolify (cond);
8059 basic_block cond_bb, then_bb, else_bb;
8060 edge e;
8061 tree tmp_var;
8063 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8064 if (kind != GF_OMP_TARGET_KIND_REGION)
8066 gsi = gsi_last_bb (new_bb);
8067 gsi_prev (&gsi);
8068 e = split_block (new_bb, gsi_stmt (gsi));
8070 else
8071 e = split_block (new_bb, NULL);
8072 cond_bb = e->src;
8073 new_bb = e->dest;
8074 remove_edge (e);
8076 then_bb = create_empty_bb (cond_bb);
8077 else_bb = create_empty_bb (then_bb);
8078 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8079 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8081 stmt = gimple_build_cond_empty (cond);
8082 gsi = gsi_last_bb (cond_bb);
8083 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8085 gsi = gsi_start_bb (then_bb);
8086 stmt = gimple_build_assign (tmp_var, device);
8087 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8089 gsi = gsi_start_bb (else_bb);
8090 stmt = gimple_build_assign (tmp_var,
8091 build_int_cst (integer_type_node, -2));
8092 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8094 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8095 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8096 add_bb_to_loop (then_bb, cond_bb->loop_father);
8097 add_bb_to_loop (else_bb, cond_bb->loop_father);
8098 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8099 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8101 device = tmp_var;
8104 gsi = gsi_last_bb (new_bb);
8105 t = gimple_omp_target_data_arg (entry_stmt);
8106 if (t == NULL)
8108 t1 = size_zero_node;
8109 t2 = build_zero_cst (ptr_type_node);
8110 t3 = t2;
8111 t4 = t2;
8113 else
8115 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8116 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8117 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8118 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8119 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8122 gimple g;
8123 /* FIXME: This will be address of
8124 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8125 symbol, as soon as the linker plugin is able to create it for us. */
8126 tree openmp_target = build_zero_cst (ptr_type_node);
8127 if (kind == GF_OMP_TARGET_KIND_REGION)
8129 tree fnaddr = build_fold_addr_expr (child_fn);
8130 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8131 device, fnaddr, openmp_target, t1, t2, t3, t4);
8133 else
8134 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8135 device, openmp_target, t1, t2, t3, t4);
8136 gimple_set_location (g, gimple_location (entry_stmt));
8137 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8138 if (kind != GF_OMP_TARGET_KIND_REGION)
8140 g = gsi_stmt (gsi);
8141 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8142 gsi_remove (&gsi, true);
8144 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8146 gsi = gsi_last_bb (region->exit);
8147 g = gsi_stmt (gsi);
8148 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8149 gsi_remove (&gsi, true);
8154 /* Expand the parallel region tree rooted at REGION. Expansion
8155 proceeds in depth-first order. Innermost regions are expanded
8156 first. This way, parallel regions that require a new function to
8157 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8158 internal dependencies in their body. */
8160 static void
8161 expand_omp (struct omp_region *region)
8163 while (region)
8165 location_t saved_location;
8166 gimple inner_stmt = NULL;
8168 /* First, determine whether this is a combined parallel+workshare
8169 region. */
8170 if (region->type == GIMPLE_OMP_PARALLEL)
8171 determine_parallel_type (region);
8173 if (region->type == GIMPLE_OMP_FOR
8174 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8175 inner_stmt = last_stmt (region->inner->entry);
8177 if (region->inner)
8178 expand_omp (region->inner);
8180 saved_location = input_location;
8181 if (gimple_has_location (last_stmt (region->entry)))
8182 input_location = gimple_location (last_stmt (region->entry));
8184 switch (region->type)
8186 case GIMPLE_OMP_PARALLEL:
8187 case GIMPLE_OMP_TASK:
8188 expand_omp_taskreg (region);
8189 break;
8191 case GIMPLE_OMP_FOR:
8192 expand_omp_for (region, inner_stmt);
8193 break;
8195 case GIMPLE_OMP_SECTIONS:
8196 expand_omp_sections (region);
8197 break;
8199 case GIMPLE_OMP_SECTION:
8200 /* Individual omp sections are handled together with their
8201 parent GIMPLE_OMP_SECTIONS region. */
8202 break;
8204 case GIMPLE_OMP_SINGLE:
8205 expand_omp_single (region);
8206 break;
8208 case GIMPLE_OMP_MASTER:
8209 case GIMPLE_OMP_TASKGROUP:
8210 case GIMPLE_OMP_ORDERED:
8211 case GIMPLE_OMP_CRITICAL:
8212 case GIMPLE_OMP_TEAMS:
8213 expand_omp_synch (region);
8214 break;
8216 case GIMPLE_OMP_ATOMIC_LOAD:
8217 expand_omp_atomic (region);
8218 break;
8220 case GIMPLE_OMP_TARGET:
8221 expand_omp_target (region);
8222 break;
8224 default:
8225 gcc_unreachable ();
8228 input_location = saved_location;
8229 region = region->next;
8234 /* Helper for build_omp_regions. Scan the dominator tree starting at
8235 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8236 true, the function ends once a single tree is built (otherwise, whole
8237 forest of OMP constructs may be built). */
8239 static void
8240 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8241 bool single_tree)
8243 gimple_stmt_iterator gsi;
8244 gimple stmt;
8245 basic_block son;
8247 gsi = gsi_last_bb (bb);
8248 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8250 struct omp_region *region;
8251 enum gimple_code code;
8253 stmt = gsi_stmt (gsi);
8254 code = gimple_code (stmt);
8255 if (code == GIMPLE_OMP_RETURN)
8257 /* STMT is the return point out of region PARENT. Mark it
8258 as the exit point and make PARENT the immediately
8259 enclosing region. */
8260 gcc_assert (parent);
8261 region = parent;
8262 region->exit = bb;
8263 parent = parent->outer;
8265 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8267 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8268 GIMPLE_OMP_RETURN, but matches with
8269 GIMPLE_OMP_ATOMIC_LOAD. */
8270 gcc_assert (parent);
8271 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8272 region = parent;
8273 region->exit = bb;
8274 parent = parent->outer;
8277 else if (code == GIMPLE_OMP_CONTINUE)
8279 gcc_assert (parent);
8280 parent->cont = bb;
8282 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8284 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8285 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8288 else if (code == GIMPLE_OMP_TARGET
8289 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8290 new_omp_region (bb, code, parent);
8291 else
8293 /* Otherwise, this directive becomes the parent for a new
8294 region. */
8295 region = new_omp_region (bb, code, parent);
8296 parent = region;
8300 if (single_tree && !parent)
8301 return;
8303 for (son = first_dom_son (CDI_DOMINATORS, bb);
8304 son;
8305 son = next_dom_son (CDI_DOMINATORS, son))
8306 build_omp_regions_1 (son, parent, single_tree);
8309 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8310 root_omp_region. */
8312 static void
8313 build_omp_regions_root (basic_block root)
8315 gcc_assert (root_omp_region == NULL);
8316 build_omp_regions_1 (root, NULL, true);
8317 gcc_assert (root_omp_region != NULL);
8320 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8322 void
8323 omp_expand_local (basic_block head)
8325 build_omp_regions_root (head);
8326 if (dump_file && (dump_flags & TDF_DETAILS))
8328 fprintf (dump_file, "\nOMP region tree\n\n");
8329 dump_omp_region (dump_file, root_omp_region, 0);
8330 fprintf (dump_file, "\n");
8333 remove_exit_barriers (root_omp_region);
8334 expand_omp (root_omp_region);
8336 free_omp_regions ();
8339 /* Scan the CFG and build a tree of OMP regions. Return the root of
8340 the OMP region tree. */
8342 static void
8343 build_omp_regions (void)
8345 gcc_assert (root_omp_region == NULL);
8346 calculate_dominance_info (CDI_DOMINATORS);
8347 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8350 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8352 static unsigned int
8353 execute_expand_omp (void)
8355 build_omp_regions ();
8357 if (!root_omp_region)
8358 return 0;
8360 if (dump_file)
8362 fprintf (dump_file, "\nOMP region tree\n\n");
8363 dump_omp_region (dump_file, root_omp_region, 0);
8364 fprintf (dump_file, "\n");
8367 remove_exit_barriers (root_omp_region);
8369 expand_omp (root_omp_region);
8371 cleanup_tree_cfg ();
8373 free_omp_regions ();
8375 return 0;
8378 /* OMP expansion -- the default pass, run before creation of SSA form. */
8380 namespace {
8382 const pass_data pass_data_expand_omp =
8384 GIMPLE_PASS, /* type */
8385 "ompexp", /* name */
8386 OPTGROUP_NONE, /* optinfo_flags */
8387 true, /* has_execute */
8388 TV_NONE, /* tv_id */
8389 PROP_gimple_any, /* properties_required */
8390 0, /* properties_provided */
8391 0, /* properties_destroyed */
8392 0, /* todo_flags_start */
8393 0, /* todo_flags_finish */
8396 class pass_expand_omp : public gimple_opt_pass
8398 public:
8399 pass_expand_omp (gcc::context *ctxt)
8400 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8403 /* opt_pass methods: */
8404 virtual bool gate (function *)
8406 return ((flag_openmp != 0 || flag_openmp_simd != 0
8407 || flag_cilkplus != 0) && !seen_error ());
8410 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8412 }; // class pass_expand_omp
8414 } // anon namespace
8416 gimple_opt_pass *
8417 make_pass_expand_omp (gcc::context *ctxt)
8419 return new pass_expand_omp (ctxt);
8422 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8424 /* If ctx is a worksharing context inside of a cancellable parallel
8425 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8426 and conditional branch to parallel's cancel_label to handle
8427 cancellation in the implicit barrier. */
8429 static void
8430 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8432 gimple omp_return = gimple_seq_last_stmt (*body);
8433 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8434 if (gimple_omp_return_nowait_p (omp_return))
8435 return;
8436 if (ctx->outer
8437 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8438 && ctx->outer->cancellable)
8440 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8441 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8442 tree lhs = create_tmp_var (c_bool_type, NULL);
8443 gimple_omp_return_set_lhs (omp_return, lhs);
8444 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8445 gimple g = gimple_build_cond (NE_EXPR, lhs,
8446 fold_convert (c_bool_type,
8447 boolean_false_node),
8448 ctx->outer->cancel_label, fallthru_label);
8449 gimple_seq_add_stmt (body, g);
8450 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8454 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8455 CTX is the enclosing OMP context for the current statement. */
8457 static void
8458 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8460 tree block, control;
8461 gimple_stmt_iterator tgsi;
8462 gimple stmt, new_stmt, bind, t;
8463 gimple_seq ilist, dlist, olist, new_body;
8465 stmt = gsi_stmt (*gsi_p);
8467 push_gimplify_context ();
8469 dlist = NULL;
8470 ilist = NULL;
8471 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8472 &ilist, &dlist, ctx, NULL);
8474 new_body = gimple_omp_body (stmt);
8475 gimple_omp_set_body (stmt, NULL);
8476 tgsi = gsi_start (new_body);
8477 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8479 omp_context *sctx;
8480 gimple sec_start;
8482 sec_start = gsi_stmt (tgsi);
8483 sctx = maybe_lookup_ctx (sec_start);
8484 gcc_assert (sctx);
8486 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8487 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8488 GSI_CONTINUE_LINKING);
8489 gimple_omp_set_body (sec_start, NULL);
8491 if (gsi_one_before_end_p (tgsi))
8493 gimple_seq l = NULL;
8494 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8495 &l, ctx);
8496 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8497 gimple_omp_section_set_last (sec_start);
8500 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8501 GSI_CONTINUE_LINKING);
8504 block = make_node (BLOCK);
8505 bind = gimple_build_bind (NULL, new_body, block);
8507 olist = NULL;
8508 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8510 block = make_node (BLOCK);
8511 new_stmt = gimple_build_bind (NULL, NULL, block);
8512 gsi_replace (gsi_p, new_stmt, true);
8514 pop_gimplify_context (new_stmt);
8515 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8516 BLOCK_VARS (block) = gimple_bind_vars (bind);
8517 if (BLOCK_VARS (block))
8518 TREE_USED (block) = 1;
8520 new_body = NULL;
8521 gimple_seq_add_seq (&new_body, ilist);
8522 gimple_seq_add_stmt (&new_body, stmt);
8523 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8524 gimple_seq_add_stmt (&new_body, bind);
8526 control = create_tmp_var (unsigned_type_node, ".section");
8527 t = gimple_build_omp_continue (control, control);
8528 gimple_omp_sections_set_control (stmt, control);
8529 gimple_seq_add_stmt (&new_body, t);
8531 gimple_seq_add_seq (&new_body, olist);
8532 if (ctx->cancellable)
8533 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8534 gimple_seq_add_seq (&new_body, dlist);
8536 new_body = maybe_catch_exception (new_body);
8538 t = gimple_build_omp_return
8539 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8540 OMP_CLAUSE_NOWAIT));
8541 gimple_seq_add_stmt (&new_body, t);
8542 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8544 gimple_bind_set_body (new_stmt, new_body);
8548 /* A subroutine of lower_omp_single. Expand the simple form of
8549 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8551 if (GOMP_single_start ())
8552 BODY;
8553 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8555 FIXME. It may be better to delay expanding the logic of this until
8556 pass_expand_omp. The expanded logic may make the job more difficult
8557 to a synchronization analysis pass. */
8559 static void
8560 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8562 location_t loc = gimple_location (single_stmt);
8563 tree tlabel = create_artificial_label (loc);
8564 tree flabel = create_artificial_label (loc);
8565 gimple call, cond;
8566 tree lhs, decl;
8568 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8569 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8570 call = gimple_build_call (decl, 0);
8571 gimple_call_set_lhs (call, lhs);
8572 gimple_seq_add_stmt (pre_p, call);
8574 cond = gimple_build_cond (EQ_EXPR, lhs,
8575 fold_convert_loc (loc, TREE_TYPE (lhs),
8576 boolean_true_node),
8577 tlabel, flabel);
8578 gimple_seq_add_stmt (pre_p, cond);
8579 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8580 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8581 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8585 /* A subroutine of lower_omp_single. Expand the simple form of
8586 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8588 #pragma omp single copyprivate (a, b, c)
8590 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8593 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8595 BODY;
8596 copyout.a = a;
8597 copyout.b = b;
8598 copyout.c = c;
8599 GOMP_single_copy_end (&copyout);
8601 else
8603 a = copyout_p->a;
8604 b = copyout_p->b;
8605 c = copyout_p->c;
8607 GOMP_barrier ();
8610 FIXME. It may be better to delay expanding the logic of this until
8611 pass_expand_omp. The expanded logic may make the job more difficult
8612 to a synchronization analysis pass. */
8614 static void
8615 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
8617 tree ptr_type, t, l0, l1, l2, bfn_decl;
8618 gimple_seq copyin_seq;
8619 location_t loc = gimple_location (single_stmt);
8621 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8623 ptr_type = build_pointer_type (ctx->record_type);
8624 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8626 l0 = create_artificial_label (loc);
8627 l1 = create_artificial_label (loc);
8628 l2 = create_artificial_label (loc);
8630 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8631 t = build_call_expr_loc (loc, bfn_decl, 0);
8632 t = fold_convert_loc (loc, ptr_type, t);
8633 gimplify_assign (ctx->receiver_decl, t, pre_p);
8635 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8636 build_int_cst (ptr_type, 0));
8637 t = build3 (COND_EXPR, void_type_node, t,
8638 build_and_jump (&l0), build_and_jump (&l1));
8639 gimplify_and_add (t, pre_p);
8641 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8643 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8645 copyin_seq = NULL;
8646 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8647 &copyin_seq, ctx);
8649 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8650 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8651 t = build_call_expr_loc (loc, bfn_decl, 1, t);
8652 gimplify_and_add (t, pre_p);
8654 t = build_and_jump (&l2);
8655 gimplify_and_add (t, pre_p);
8657 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8659 gimple_seq_add_seq (pre_p, copyin_seq);
8661 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8665 /* Expand code for an OpenMP single directive. */
8667 static void
8668 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8670 tree block;
8671 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
8672 gimple_seq bind_body, bind_body_tail = NULL, dlist;
8674 push_gimplify_context ();
8676 block = make_node (BLOCK);
8677 bind = gimple_build_bind (NULL, NULL, block);
8678 gsi_replace (gsi_p, bind, true);
8679 bind_body = NULL;
8680 dlist = NULL;
8681 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8682 &bind_body, &dlist, ctx, NULL);
8683 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8685 gimple_seq_add_stmt (&bind_body, single_stmt);
8687 if (ctx->record_type)
8688 lower_omp_single_copy (single_stmt, &bind_body, ctx);
8689 else
8690 lower_omp_single_simple (single_stmt, &bind_body);
8692 gimple_omp_set_body (single_stmt, NULL);
8694 gimple_seq_add_seq (&bind_body, dlist);
8696 bind_body = maybe_catch_exception (bind_body);
8698 t = gimple_build_omp_return
8699 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
8700 OMP_CLAUSE_NOWAIT));
8701 gimple_seq_add_stmt (&bind_body_tail, t);
8702 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
8703 if (ctx->record_type)
8705 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8706 tree clobber = build_constructor (ctx->record_type, NULL);
8707 TREE_THIS_VOLATILE (clobber) = 1;
8708 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8709 clobber), GSI_SAME_STMT);
8711 gimple_seq_add_seq (&bind_body, bind_body_tail);
8712 gimple_bind_set_body (bind, bind_body);
8714 pop_gimplify_context (bind);
8716 gimple_bind_append_vars (bind, ctx->block_vars);
8717 BLOCK_VARS (block) = ctx->block_vars;
8718 if (BLOCK_VARS (block))
8719 TREE_USED (block) = 1;
8723 /* Expand code for an OpenMP master directive. */
8725 static void
8726 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8728 tree block, lab = NULL, x, bfn_decl;
8729 gimple stmt = gsi_stmt (*gsi_p), bind;
8730 location_t loc = gimple_location (stmt);
8731 gimple_seq tseq;
8733 push_gimplify_context ();
8735 block = make_node (BLOCK);
8736 bind = gimple_build_bind (NULL, NULL, block);
8737 gsi_replace (gsi_p, bind, true);
8738 gimple_bind_add_stmt (bind, stmt);
8740 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8741 x = build_call_expr_loc (loc, bfn_decl, 0);
8742 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
8743 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
8744 tseq = NULL;
8745 gimplify_and_add (x, &tseq);
8746 gimple_bind_add_seq (bind, tseq);
8748 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8749 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8750 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8751 gimple_omp_set_body (stmt, NULL);
8753 gimple_bind_add_stmt (bind, gimple_build_label (lab));
8755 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8757 pop_gimplify_context (bind);
8759 gimple_bind_append_vars (bind, ctx->block_vars);
8760 BLOCK_VARS (block) = ctx->block_vars;
8764 /* Expand code for an OpenMP taskgroup directive. */
8766 static void
8767 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8769 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8770 tree block = make_node (BLOCK);
8772 bind = gimple_build_bind (NULL, NULL, block);
8773 gsi_replace (gsi_p, bind, true);
8774 gimple_bind_add_stmt (bind, stmt);
8776 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
8778 gimple_bind_add_stmt (bind, x);
8780 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8781 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8782 gimple_omp_set_body (stmt, NULL);
8784 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8786 gimple_bind_append_vars (bind, ctx->block_vars);
8787 BLOCK_VARS (block) = ctx->block_vars;
8791 /* Expand code for an OpenMP ordered directive. */
8793 static void
8794 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8796 tree block;
8797 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8799 push_gimplify_context ();
8801 block = make_node (BLOCK);
8802 bind = gimple_build_bind (NULL, NULL, block);
8803 gsi_replace (gsi_p, bind, true);
8804 gimple_bind_add_stmt (bind, stmt);
8806 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
8808 gimple_bind_add_stmt (bind, x);
8810 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8811 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8812 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8813 gimple_omp_set_body (stmt, NULL);
8815 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
8816 gimple_bind_add_stmt (bind, x);
8818 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8820 pop_gimplify_context (bind);
8822 gimple_bind_append_vars (bind, ctx->block_vars);
8823 BLOCK_VARS (block) = gimple_bind_vars (bind);
8827 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
8828 substitution of a couple of function calls. But in the NAMED case,
8829 requires that languages coordinate a symbol name. It is therefore
8830 best put here in common code. */
8832 static GTY((param1_is (tree), param2_is (tree)))
8833 splay_tree critical_name_mutexes;
8835 static void
8836 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8838 tree block;
8839 tree name, lock, unlock;
8840 gimple stmt = gsi_stmt (*gsi_p), bind;
8841 location_t loc = gimple_location (stmt);
8842 gimple_seq tbody;
8844 name = gimple_omp_critical_name (stmt);
8845 if (name)
8847 tree decl;
8848 splay_tree_node n;
8850 if (!critical_name_mutexes)
8851 critical_name_mutexes
8852 = splay_tree_new_ggc (splay_tree_compare_pointers,
8853 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
8854 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
8856 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
8857 if (n == NULL)
8859 char *new_str;
8861 decl = create_tmp_var_raw (ptr_type_node, NULL);
8863 new_str = ACONCAT ((".gomp_critical_user_",
8864 IDENTIFIER_POINTER (name), NULL));
8865 DECL_NAME (decl) = get_identifier (new_str);
8866 TREE_PUBLIC (decl) = 1;
8867 TREE_STATIC (decl) = 1;
8868 DECL_COMMON (decl) = 1;
8869 DECL_ARTIFICIAL (decl) = 1;
8870 DECL_IGNORED_P (decl) = 1;
8871 varpool_finalize_decl (decl);
8873 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
8874 (splay_tree_value) decl);
8876 else
8877 decl = (tree) n->value;
8879 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
8880 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
8882 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
8883 unlock = build_call_expr_loc (loc, unlock, 1,
8884 build_fold_addr_expr_loc (loc, decl));
8886 else
8888 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
8889 lock = build_call_expr_loc (loc, lock, 0);
8891 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
8892 unlock = build_call_expr_loc (loc, unlock, 0);
8895 push_gimplify_context ();
8897 block = make_node (BLOCK);
8898 bind = gimple_build_bind (NULL, NULL, block);
8899 gsi_replace (gsi_p, bind, true);
8900 gimple_bind_add_stmt (bind, stmt);
8902 tbody = gimple_bind_body (bind);
8903 gimplify_and_add (lock, &tbody);
8904 gimple_bind_set_body (bind, tbody);
8906 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8907 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8908 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8909 gimple_omp_set_body (stmt, NULL);
8911 tbody = gimple_bind_body (bind);
8912 gimplify_and_add (unlock, &tbody);
8913 gimple_bind_set_body (bind, tbody);
8915 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8917 pop_gimplify_context (bind);
8918 gimple_bind_append_vars (bind, ctx->block_vars);
8919 BLOCK_VARS (block) = gimple_bind_vars (bind);
8923 /* A subroutine of lower_omp_for. Generate code to emit the predicate
8924 for a lastprivate clause. Given a loop control predicate of (V
8925 cond N2), we gate the clause on (!(V cond N2)). The lowered form
8926 is appended to *DLIST, iterator initialization is appended to
8927 *BODY_P. */
8929 static void
8930 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
8931 gimple_seq *dlist, struct omp_context *ctx)
8933 tree clauses, cond, vinit;
8934 enum tree_code cond_code;
8935 gimple_seq stmts;
8937 cond_code = fd->loop.cond_code;
8938 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
8940 /* When possible, use a strict equality expression. This can let VRP
8941 type optimizations deduce the value and remove a copy. */
8942 if (tree_fits_shwi_p (fd->loop.step))
8944 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
8945 if (step == 1 || step == -1)
8946 cond_code = EQ_EXPR;
8949 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
8951 clauses = gimple_omp_for_clauses (fd->for_stmt);
8952 stmts = NULL;
8953 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
8954 if (!gimple_seq_empty_p (stmts))
8956 gimple_seq_add_seq (&stmts, *dlist);
8957 *dlist = stmts;
8959 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
8960 vinit = fd->loop.n1;
8961 if (cond_code == EQ_EXPR
8962 && tree_fits_shwi_p (fd->loop.n2)
8963 && ! integer_zerop (fd->loop.n2))
8964 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
8965 else
8966 vinit = unshare_expr (vinit);
8968 /* Initialize the iterator variable, so that threads that don't execute
8969 any iterations don't execute the lastprivate clauses by accident. */
8970 gimplify_assign (fd->loop.v, vinit, body_p);
8975 /* Lower code for an OpenMP loop directive. */
8977 static void
8978 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8980 tree *rhs_p, block;
8981 struct omp_for_data fd, *fdp = NULL;
8982 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
8983 gimple_seq omp_for_body, body, dlist;
8984 size_t i;
8986 push_gimplify_context ();
8988 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
8990 block = make_node (BLOCK);
8991 new_stmt = gimple_build_bind (NULL, NULL, block);
8992 /* Replace at gsi right away, so that 'stmt' is no member
8993 of a sequence anymore as we're going to add to to a different
8994 one below. */
8995 gsi_replace (gsi_p, new_stmt, true);
8997 /* Move declaration of temporaries in the loop body before we make
8998 it go away. */
8999 omp_for_body = gimple_omp_body (stmt);
9000 if (!gimple_seq_empty_p (omp_for_body)
9001 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9003 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
9004 tree vars = gimple_bind_vars (inner_bind);
9005 gimple_bind_append_vars (new_stmt, vars);
9006 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9007 keep them on the inner_bind and it's block. */
9008 gimple_bind_set_vars (inner_bind, NULL_TREE);
9009 if (gimple_bind_block (inner_bind))
9010 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9013 if (gimple_omp_for_combined_into_p (stmt))
9015 extract_omp_for_data (stmt, &fd, NULL);
9016 fdp = &fd;
9018 /* We need two temporaries with fd.loop.v type (istart/iend)
9019 and then (fd.collapse - 1) temporaries with the same
9020 type for count2 ... countN-1 vars if not constant. */
9021 size_t count = 2;
9022 tree type = fd.iter_type;
9023 if (fd.collapse > 1
9024 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9025 count += fd.collapse - 1;
9026 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9027 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9028 tree clauses = *pc;
9029 if (parallel_for)
9030 outerc
9031 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9032 OMP_CLAUSE__LOOPTEMP_);
9033 for (i = 0; i < count; i++)
9035 tree temp;
9036 if (parallel_for)
9038 gcc_assert (outerc);
9039 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9040 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9041 OMP_CLAUSE__LOOPTEMP_);
9043 else
9044 temp = create_tmp_var (type, NULL);
9045 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9046 OMP_CLAUSE_DECL (*pc) = temp;
9047 pc = &OMP_CLAUSE_CHAIN (*pc);
9049 *pc = clauses;
9052 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9053 dlist = NULL;
9054 body = NULL;
9055 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9056 fdp);
9057 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9059 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9061 /* Lower the header expressions. At this point, we can assume that
9062 the header is of the form:
9064 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9066 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9067 using the .omp_data_s mapping, if needed. */
9068 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9070 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9071 if (!is_gimple_min_invariant (*rhs_p))
9072 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9074 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9075 if (!is_gimple_min_invariant (*rhs_p))
9076 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9078 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9079 if (!is_gimple_min_invariant (*rhs_p))
9080 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9083 /* Once lowered, extract the bounds and clauses. */
9084 extract_omp_for_data (stmt, &fd, NULL);
9086 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9088 gimple_seq_add_stmt (&body, stmt);
9089 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9091 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9092 fd.loop.v));
9094 /* After the loop, add exit clauses. */
9095 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9097 if (ctx->cancellable)
9098 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9100 gimple_seq_add_seq (&body, dlist);
9102 body = maybe_catch_exception (body);
9104 /* Region exit marker goes at the end of the loop body. */
9105 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9106 maybe_add_implicit_barrier_cancel (ctx, &body);
9107 pop_gimplify_context (new_stmt);
9109 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9110 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9111 if (BLOCK_VARS (block))
9112 TREE_USED (block) = 1;
9114 gimple_bind_set_body (new_stmt, body);
9115 gimple_omp_set_body (stmt, NULL);
9116 gimple_omp_for_set_pre_body (stmt, NULL);
9119 /* Callback for walk_stmts. Check if the current statement only contains
9120 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9122 static tree
9123 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9124 bool *handled_ops_p,
9125 struct walk_stmt_info *wi)
9127 int *info = (int *) wi->info;
9128 gimple stmt = gsi_stmt (*gsi_p);
9130 *handled_ops_p = true;
9131 switch (gimple_code (stmt))
9133 WALK_SUBSTMTS;
9135 case GIMPLE_OMP_FOR:
9136 case GIMPLE_OMP_SECTIONS:
9137 *info = *info == 0 ? 1 : -1;
9138 break;
9139 default:
9140 *info = -1;
9141 break;
9143 return NULL;
9146 struct omp_taskcopy_context
9148 /* This field must be at the beginning, as we do "inheritance": Some
9149 callback functions for tree-inline.c (e.g., omp_copy_decl)
9150 receive a copy_body_data pointer that is up-casted to an
9151 omp_context pointer. */
9152 copy_body_data cb;
9153 omp_context *ctx;
9156 static tree
9157 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9159 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9161 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9162 return create_tmp_var (TREE_TYPE (var), NULL);
9164 return var;
9167 static tree
9168 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9170 tree name, new_fields = NULL, type, f;
9172 type = lang_hooks.types.make_type (RECORD_TYPE);
9173 name = DECL_NAME (TYPE_NAME (orig_type));
9174 name = build_decl (gimple_location (tcctx->ctx->stmt),
9175 TYPE_DECL, name, type);
9176 TYPE_NAME (type) = name;
9178 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9180 tree new_f = copy_node (f);
9181 DECL_CONTEXT (new_f) = type;
9182 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9183 TREE_CHAIN (new_f) = new_fields;
9184 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9185 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9186 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9187 &tcctx->cb, NULL);
9188 new_fields = new_f;
9189 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
9191 TYPE_FIELDS (type) = nreverse (new_fields);
9192 layout_type (type);
9193 return type;
9196 /* Create task copyfn. */
9198 static void
9199 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9201 struct function *child_cfun;
9202 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9203 tree record_type, srecord_type, bind, list;
9204 bool record_needs_remap = false, srecord_needs_remap = false;
9205 splay_tree_node n;
9206 struct omp_taskcopy_context tcctx;
9207 location_t loc = gimple_location (task_stmt);
9209 child_fn = gimple_omp_task_copy_fn (task_stmt);
9210 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9211 gcc_assert (child_cfun->cfg == NULL);
9212 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9214 /* Reset DECL_CONTEXT on function arguments. */
9215 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9216 DECL_CONTEXT (t) = child_fn;
9218 /* Populate the function. */
9219 push_gimplify_context ();
9220 push_cfun (child_cfun);
9222 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9223 TREE_SIDE_EFFECTS (bind) = 1;
9224 list = NULL;
9225 DECL_SAVED_TREE (child_fn) = bind;
9226 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9228 /* Remap src and dst argument types if needed. */
9229 record_type = ctx->record_type;
9230 srecord_type = ctx->srecord_type;
9231 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9232 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9234 record_needs_remap = true;
9235 break;
9237 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9238 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9240 srecord_needs_remap = true;
9241 break;
9244 if (record_needs_remap || srecord_needs_remap)
9246 memset (&tcctx, '\0', sizeof (tcctx));
9247 tcctx.cb.src_fn = ctx->cb.src_fn;
9248 tcctx.cb.dst_fn = child_fn;
9249 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
9250 gcc_checking_assert (tcctx.cb.src_node);
9251 tcctx.cb.dst_node = tcctx.cb.src_node;
9252 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9253 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9254 tcctx.cb.eh_lp_nr = 0;
9255 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9256 tcctx.cb.decl_map = pointer_map_create ();
9257 tcctx.ctx = ctx;
9259 if (record_needs_remap)
9260 record_type = task_copyfn_remap_type (&tcctx, record_type);
9261 if (srecord_needs_remap)
9262 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9264 else
9265 tcctx.cb.decl_map = NULL;
9267 arg = DECL_ARGUMENTS (child_fn);
9268 TREE_TYPE (arg) = build_pointer_type (record_type);
9269 sarg = DECL_CHAIN (arg);
9270 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9272 /* First pass: initialize temporaries used in record_type and srecord_type
9273 sizes and field offsets. */
9274 if (tcctx.cb.decl_map)
9275 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9276 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9278 tree *p;
9280 decl = OMP_CLAUSE_DECL (c);
9281 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
9282 if (p == NULL)
9283 continue;
9284 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9285 sf = (tree) n->value;
9286 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9287 src = build_simple_mem_ref_loc (loc, sarg);
9288 src = omp_build_component_ref (src, sf);
9289 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9290 append_to_statement_list (t, &list);
9293 /* Second pass: copy shared var pointers and copy construct non-VLA
9294 firstprivate vars. */
9295 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9296 switch (OMP_CLAUSE_CODE (c))
9298 case OMP_CLAUSE_SHARED:
9299 decl = OMP_CLAUSE_DECL (c);
9300 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9301 if (n == NULL)
9302 break;
9303 f = (tree) n->value;
9304 if (tcctx.cb.decl_map)
9305 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9306 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9307 sf = (tree) n->value;
9308 if (tcctx.cb.decl_map)
9309 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9310 src = build_simple_mem_ref_loc (loc, sarg);
9311 src = omp_build_component_ref (src, sf);
9312 dst = build_simple_mem_ref_loc (loc, arg);
9313 dst = omp_build_component_ref (dst, f);
9314 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9315 append_to_statement_list (t, &list);
9316 break;
9317 case OMP_CLAUSE_FIRSTPRIVATE:
9318 decl = OMP_CLAUSE_DECL (c);
9319 if (is_variable_sized (decl))
9320 break;
9321 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9322 if (n == NULL)
9323 break;
9324 f = (tree) n->value;
9325 if (tcctx.cb.decl_map)
9326 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9327 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9328 if (n != NULL)
9330 sf = (tree) n->value;
9331 if (tcctx.cb.decl_map)
9332 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9333 src = build_simple_mem_ref_loc (loc, sarg);
9334 src = omp_build_component_ref (src, sf);
9335 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9336 src = build_simple_mem_ref_loc (loc, src);
9338 else
9339 src = decl;
9340 dst = build_simple_mem_ref_loc (loc, arg);
9341 dst = omp_build_component_ref (dst, f);
9342 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9343 append_to_statement_list (t, &list);
9344 break;
9345 case OMP_CLAUSE_PRIVATE:
9346 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9347 break;
9348 decl = OMP_CLAUSE_DECL (c);
9349 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9350 f = (tree) n->value;
9351 if (tcctx.cb.decl_map)
9352 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9353 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9354 if (n != NULL)
9356 sf = (tree) n->value;
9357 if (tcctx.cb.decl_map)
9358 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9359 src = build_simple_mem_ref_loc (loc, sarg);
9360 src = omp_build_component_ref (src, sf);
9361 if (use_pointer_for_field (decl, NULL))
9362 src = build_simple_mem_ref_loc (loc, src);
9364 else
9365 src = decl;
9366 dst = build_simple_mem_ref_loc (loc, arg);
9367 dst = omp_build_component_ref (dst, f);
9368 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9369 append_to_statement_list (t, &list);
9370 break;
9371 default:
9372 break;
9375 /* Last pass: handle VLA firstprivates. */
9376 if (tcctx.cb.decl_map)
9377 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9378 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9380 tree ind, ptr, df;
9382 decl = OMP_CLAUSE_DECL (c);
9383 if (!is_variable_sized (decl))
9384 continue;
9385 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9386 if (n == NULL)
9387 continue;
9388 f = (tree) n->value;
9389 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9390 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9391 ind = DECL_VALUE_EXPR (decl);
9392 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9393 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9394 n = splay_tree_lookup (ctx->sfield_map,
9395 (splay_tree_key) TREE_OPERAND (ind, 0));
9396 sf = (tree) n->value;
9397 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9398 src = build_simple_mem_ref_loc (loc, sarg);
9399 src = omp_build_component_ref (src, sf);
9400 src = build_simple_mem_ref_loc (loc, src);
9401 dst = build_simple_mem_ref_loc (loc, arg);
9402 dst = omp_build_component_ref (dst, f);
9403 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9404 append_to_statement_list (t, &list);
9405 n = splay_tree_lookup (ctx->field_map,
9406 (splay_tree_key) TREE_OPERAND (ind, 0));
9407 df = (tree) n->value;
9408 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
9409 ptr = build_simple_mem_ref_loc (loc, arg);
9410 ptr = omp_build_component_ref (ptr, df);
9411 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9412 build_fold_addr_expr_loc (loc, dst));
9413 append_to_statement_list (t, &list);
9416 t = build1 (RETURN_EXPR, void_type_node, NULL);
9417 append_to_statement_list (t, &list);
9419 if (tcctx.cb.decl_map)
9420 pointer_map_destroy (tcctx.cb.decl_map);
9421 pop_gimplify_context (NULL);
9422 BIND_EXPR_BODY (bind) = list;
9423 pop_cfun ();
9426 static void
9427 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9429 tree c, clauses;
9430 gimple g;
9431 size_t n_in = 0, n_out = 0, idx = 2, i;
9433 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9434 OMP_CLAUSE_DEPEND);
9435 gcc_assert (clauses);
9436 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9437 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9438 switch (OMP_CLAUSE_DEPEND_KIND (c))
9440 case OMP_CLAUSE_DEPEND_IN:
9441 n_in++;
9442 break;
9443 case OMP_CLAUSE_DEPEND_OUT:
9444 case OMP_CLAUSE_DEPEND_INOUT:
9445 n_out++;
9446 break;
9447 default:
9448 gcc_unreachable ();
9450 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9451 tree array = create_tmp_var (type, NULL);
9452 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9453 NULL_TREE);
9454 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9455 gimple_seq_add_stmt (iseq, g);
9456 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9457 NULL_TREE);
9458 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9459 gimple_seq_add_stmt (iseq, g);
9460 for (i = 0; i < 2; i++)
9462 if ((i ? n_in : n_out) == 0)
9463 continue;
9464 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9465 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9466 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9468 tree t = OMP_CLAUSE_DECL (c);
9469 t = fold_convert (ptr_type_node, t);
9470 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9471 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9472 NULL_TREE, NULL_TREE);
9473 g = gimple_build_assign (r, t);
9474 gimple_seq_add_stmt (iseq, g);
9477 tree *p = gimple_omp_task_clauses_ptr (stmt);
9478 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9479 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9480 OMP_CLAUSE_CHAIN (c) = *p;
9481 *p = c;
9482 tree clobber = build_constructor (type, NULL);
9483 TREE_THIS_VOLATILE (clobber) = 1;
9484 g = gimple_build_assign (array, clobber);
9485 gimple_seq_add_stmt (oseq, g);
9488 /* Lower the OpenMP parallel or task directive in the current statement
9489 in GSI_P. CTX holds context information for the directive. */
9491 static void
9492 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9494 tree clauses;
9495 tree child_fn, t;
9496 gimple stmt = gsi_stmt (*gsi_p);
9497 gimple par_bind, bind, dep_bind = NULL;
9498 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9499 location_t loc = gimple_location (stmt);
9501 clauses = gimple_omp_taskreg_clauses (stmt);
9502 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9503 par_body = gimple_bind_body (par_bind);
9504 child_fn = ctx->cb.dst_fn;
9505 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9506 && !gimple_omp_parallel_combined_p (stmt))
9508 struct walk_stmt_info wi;
9509 int ws_num = 0;
9511 memset (&wi, 0, sizeof (wi));
9512 wi.info = &ws_num;
9513 wi.val_only = true;
9514 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9515 if (ws_num == 1)
9516 gimple_omp_parallel_set_combined_p (stmt, true);
9518 gimple_seq dep_ilist = NULL;
9519 gimple_seq dep_olist = NULL;
9520 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9521 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9523 push_gimplify_context ();
9524 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9525 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9528 if (ctx->srecord_type)
9529 create_task_copyfn (stmt, ctx);
9531 push_gimplify_context ();
9533 par_olist = NULL;
9534 par_ilist = NULL;
9535 par_rlist = NULL;
9536 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9537 lower_omp (&par_body, ctx);
9538 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9539 lower_reduction_clauses (clauses, &par_rlist, ctx);
9541 /* Declare all the variables created by mapping and the variables
9542 declared in the scope of the parallel body. */
9543 record_vars_into (ctx->block_vars, child_fn);
9544 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9546 if (ctx->record_type)
9548 ctx->sender_decl
9549 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9550 : ctx->record_type, ".omp_data_o");
9551 DECL_NAMELESS (ctx->sender_decl) = 1;
9552 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9553 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9556 olist = NULL;
9557 ilist = NULL;
9558 lower_send_clauses (clauses, &ilist, &olist, ctx);
9559 lower_send_shared_vars (&ilist, &olist, ctx);
9561 if (ctx->record_type)
9563 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9564 TREE_THIS_VOLATILE (clobber) = 1;
9565 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9566 clobber));
9569 /* Once all the expansions are done, sequence all the different
9570 fragments inside gimple_omp_body. */
9572 new_body = NULL;
9574 if (ctx->record_type)
9576 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9577 /* fixup_child_record_type might have changed receiver_decl's type. */
9578 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9579 gimple_seq_add_stmt (&new_body,
9580 gimple_build_assign (ctx->receiver_decl, t));
9583 gimple_seq_add_seq (&new_body, par_ilist);
9584 gimple_seq_add_seq (&new_body, par_body);
9585 gimple_seq_add_seq (&new_body, par_rlist);
9586 if (ctx->cancellable)
9587 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9588 gimple_seq_add_seq (&new_body, par_olist);
9589 new_body = maybe_catch_exception (new_body);
9590 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9591 gimple_omp_set_body (stmt, new_body);
9593 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9594 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
9595 gimple_bind_add_seq (bind, ilist);
9596 gimple_bind_add_stmt (bind, stmt);
9597 gimple_bind_add_seq (bind, olist);
9599 pop_gimplify_context (NULL);
9601 if (dep_bind)
9603 gimple_bind_add_seq (dep_bind, dep_ilist);
9604 gimple_bind_add_stmt (dep_bind, bind);
9605 gimple_bind_add_seq (dep_bind, dep_olist);
9606 pop_gimplify_context (dep_bind);
9610 /* Lower the OpenMP target directive in the current statement
9611 in GSI_P. CTX holds context information for the directive. */
9613 static void
9614 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9616 tree clauses;
9617 tree child_fn, t, c;
9618 gimple stmt = gsi_stmt (*gsi_p);
9619 gimple tgt_bind = NULL, bind;
9620 gimple_seq tgt_body = NULL, olist, ilist, new_body;
9621 location_t loc = gimple_location (stmt);
9622 int kind = gimple_omp_target_kind (stmt);
9623 unsigned int map_cnt = 0;
9625 clauses = gimple_omp_target_clauses (stmt);
9626 if (kind == GF_OMP_TARGET_KIND_REGION)
9628 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9629 tgt_body = gimple_bind_body (tgt_bind);
9631 else if (kind == GF_OMP_TARGET_KIND_DATA)
9632 tgt_body = gimple_omp_body (stmt);
9633 child_fn = ctx->cb.dst_fn;
9635 push_gimplify_context ();
9637 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9638 switch (OMP_CLAUSE_CODE (c))
9640 tree var, x;
9642 default:
9643 break;
9644 case OMP_CLAUSE_MAP:
9645 case OMP_CLAUSE_TO:
9646 case OMP_CLAUSE_FROM:
9647 var = OMP_CLAUSE_DECL (c);
9648 if (!DECL_P (var))
9650 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
9651 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9652 map_cnt++;
9653 continue;
9656 if (DECL_SIZE (var)
9657 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
9659 tree var2 = DECL_VALUE_EXPR (var);
9660 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
9661 var2 = TREE_OPERAND (var2, 0);
9662 gcc_assert (DECL_P (var2));
9663 var = var2;
9666 if (!maybe_lookup_field (var, ctx))
9667 continue;
9669 if (kind == GF_OMP_TARGET_KIND_REGION)
9671 x = build_receiver_ref (var, true, ctx);
9672 tree new_var = lookup_decl (var, ctx);
9673 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9674 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9675 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9676 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
9677 x = build_simple_mem_ref (x);
9678 SET_DECL_VALUE_EXPR (new_var, x);
9679 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
9681 map_cnt++;
9684 if (kind == GF_OMP_TARGET_KIND_REGION)
9686 target_nesting_level++;
9687 lower_omp (&tgt_body, ctx);
9688 target_nesting_level--;
9690 else if (kind == GF_OMP_TARGET_KIND_DATA)
9691 lower_omp (&tgt_body, ctx);
9693 if (kind == GF_OMP_TARGET_KIND_REGION)
9695 /* Declare all the variables created by mapping and the variables
9696 declared in the scope of the target body. */
9697 record_vars_into (ctx->block_vars, child_fn);
9698 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
9701 olist = NULL;
9702 ilist = NULL;
9703 if (ctx->record_type)
9705 ctx->sender_decl
9706 = create_tmp_var (ctx->record_type, ".omp_data_arr");
9707 DECL_NAMELESS (ctx->sender_decl) = 1;
9708 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9709 t = make_tree_vec (3);
9710 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
9711 TREE_VEC_ELT (t, 1)
9712 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
9713 ".omp_data_sizes");
9714 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
9715 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
9716 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
9717 TREE_VEC_ELT (t, 2)
9718 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
9719 map_cnt),
9720 ".omp_data_kinds");
9721 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
9722 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
9723 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
9724 gimple_omp_target_set_data_arg (stmt, t);
9726 vec<constructor_elt, va_gc> *vsize;
9727 vec<constructor_elt, va_gc> *vkind;
9728 vec_alloc (vsize, map_cnt);
9729 vec_alloc (vkind, map_cnt);
9730 unsigned int map_idx = 0;
9732 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9733 switch (OMP_CLAUSE_CODE (c))
9735 tree ovar, nc;
9737 default:
9738 break;
9739 case OMP_CLAUSE_MAP:
9740 case OMP_CLAUSE_TO:
9741 case OMP_CLAUSE_FROM:
9742 nc = c;
9743 ovar = OMP_CLAUSE_DECL (c);
9744 if (!DECL_P (ovar))
9746 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9747 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9749 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
9750 == get_base_address (ovar));
9751 nc = OMP_CLAUSE_CHAIN (c);
9752 ovar = OMP_CLAUSE_DECL (nc);
9754 else
9756 tree x = build_sender_ref (ovar, ctx);
9757 tree v
9758 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
9759 gimplify_assign (x, v, &ilist);
9760 nc = NULL_TREE;
9763 else
9765 if (DECL_SIZE (ovar)
9766 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
9768 tree ovar2 = DECL_VALUE_EXPR (ovar);
9769 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
9770 ovar2 = TREE_OPERAND (ovar2, 0);
9771 gcc_assert (DECL_P (ovar2));
9772 ovar = ovar2;
9774 if (!maybe_lookup_field (ovar, ctx))
9775 continue;
9778 if (nc)
9780 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
9781 tree x = build_sender_ref (ovar, ctx);
9782 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9783 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9784 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9785 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
9787 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9788 tree avar
9789 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
9790 mark_addressable (avar);
9791 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
9792 avar = build_fold_addr_expr (avar);
9793 gimplify_assign (x, avar, &ilist);
9795 else if (is_gimple_reg (var))
9797 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9798 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
9799 mark_addressable (avar);
9800 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
9801 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
9802 gimplify_assign (avar, var, &ilist);
9803 avar = build_fold_addr_expr (avar);
9804 gimplify_assign (x, avar, &ilist);
9805 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
9806 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
9807 && !TYPE_READONLY (TREE_TYPE (var)))
9809 x = build_sender_ref (ovar, ctx);
9810 x = build_simple_mem_ref (x);
9811 gimplify_assign (var, x, &olist);
9814 else
9816 var = build_fold_addr_expr (var);
9817 gimplify_assign (x, var, &ilist);
9820 tree s = OMP_CLAUSE_SIZE (c);
9821 if (s == NULL_TREE)
9822 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
9823 s = fold_convert (size_type_node, s);
9824 tree purpose = size_int (map_idx++);
9825 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
9826 if (TREE_CODE (s) != INTEGER_CST)
9827 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
9829 unsigned char tkind = 0;
9830 switch (OMP_CLAUSE_CODE (c))
9832 case OMP_CLAUSE_MAP:
9833 tkind = OMP_CLAUSE_MAP_KIND (c);
9834 break;
9835 case OMP_CLAUSE_TO:
9836 tkind = OMP_CLAUSE_MAP_TO;
9837 break;
9838 case OMP_CLAUSE_FROM:
9839 tkind = OMP_CLAUSE_MAP_FROM;
9840 break;
9841 default:
9842 gcc_unreachable ();
9844 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
9845 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
9846 talign = DECL_ALIGN_UNIT (ovar);
9847 talign = ceil_log2 (talign);
9848 tkind |= talign << 3;
9849 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
9850 build_int_cst (unsigned_char_type_node,
9851 tkind));
9852 if (nc && nc != c)
9853 c = nc;
9856 gcc_assert (map_idx == map_cnt);
9858 DECL_INITIAL (TREE_VEC_ELT (t, 1))
9859 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
9860 DECL_INITIAL (TREE_VEC_ELT (t, 2))
9861 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
9862 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
9864 gimple_seq initlist = NULL;
9865 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
9866 TREE_VEC_ELT (t, 1)),
9867 &initlist, true, NULL_TREE);
9868 gimple_seq_add_seq (&ilist, initlist);
9870 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
9871 NULL);
9872 TREE_THIS_VOLATILE (clobber) = 1;
9873 gimple_seq_add_stmt (&olist,
9874 gimple_build_assign (TREE_VEC_ELT (t, 1),
9875 clobber));
9878 tree clobber = build_constructor (ctx->record_type, NULL);
9879 TREE_THIS_VOLATILE (clobber) = 1;
9880 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9881 clobber));
9884 /* Once all the expansions are done, sequence all the different
9885 fragments inside gimple_omp_body. */
9887 new_body = NULL;
9889 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
9891 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9892 /* fixup_child_record_type might have changed receiver_decl's type. */
9893 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9894 gimple_seq_add_stmt (&new_body,
9895 gimple_build_assign (ctx->receiver_decl, t));
9898 if (kind == GF_OMP_TARGET_KIND_REGION)
9900 gimple_seq_add_seq (&new_body, tgt_body);
9901 new_body = maybe_catch_exception (new_body);
9903 else if (kind == GF_OMP_TARGET_KIND_DATA)
9904 new_body = tgt_body;
9905 if (kind != GF_OMP_TARGET_KIND_UPDATE)
9907 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9908 gimple_omp_set_body (stmt, new_body);
9911 bind = gimple_build_bind (NULL, NULL,
9912 tgt_bind ? gimple_bind_block (tgt_bind)
9913 : NULL_TREE);
9914 gsi_replace (gsi_p, bind, true);
9915 gimple_bind_add_seq (bind, ilist);
9916 gimple_bind_add_stmt (bind, stmt);
9917 gimple_bind_add_seq (bind, olist);
9919 pop_gimplify_context (NULL);
9922 /* Expand code for an OpenMP teams directive. */
9924 static void
9925 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9927 gimple teams_stmt = gsi_stmt (*gsi_p);
9928 push_gimplify_context ();
9930 tree block = make_node (BLOCK);
9931 gimple bind = gimple_build_bind (NULL, NULL, block);
9932 gsi_replace (gsi_p, bind, true);
9933 gimple_seq bind_body = NULL;
9934 gimple_seq dlist = NULL;
9935 gimple_seq olist = NULL;
9937 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9938 OMP_CLAUSE_NUM_TEAMS);
9939 if (num_teams == NULL_TREE)
9940 num_teams = build_int_cst (unsigned_type_node, 0);
9941 else
9943 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
9944 num_teams = fold_convert (unsigned_type_node, num_teams);
9945 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
9947 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9948 OMP_CLAUSE_THREAD_LIMIT);
9949 if (thread_limit == NULL_TREE)
9950 thread_limit = build_int_cst (unsigned_type_node, 0);
9951 else
9953 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
9954 thread_limit = fold_convert (unsigned_type_node, thread_limit);
9955 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
9956 fb_rvalue);
9959 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
9960 &bind_body, &dlist, ctx, NULL);
9961 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
9962 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
9963 gimple_seq_add_stmt (&bind_body, teams_stmt);
9965 location_t loc = gimple_location (teams_stmt);
9966 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
9967 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
9968 gimple_set_location (call, loc);
9969 gimple_seq_add_stmt (&bind_body, call);
9971 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
9972 gimple_omp_set_body (teams_stmt, NULL);
9973 gimple_seq_add_seq (&bind_body, olist);
9974 gimple_seq_add_seq (&bind_body, dlist);
9975 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
9976 gimple_bind_set_body (bind, bind_body);
9978 pop_gimplify_context (bind);
9980 gimple_bind_append_vars (bind, ctx->block_vars);
9981 BLOCK_VARS (block) = ctx->block_vars;
9982 if (BLOCK_VARS (block))
9983 TREE_USED (block) = 1;
9987 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
9988 regimplified. If DATA is non-NULL, lower_omp_1 is outside
9989 of OpenMP context, but with task_shared_vars set. */
9991 static tree
9992 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
9993 void *data)
9995 tree t = *tp;
9997 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
9998 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9999 return t;
10001 if (task_shared_vars
10002 && DECL_P (t)
10003 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10004 return t;
10006 /* If a global variable has been privatized, TREE_CONSTANT on
10007 ADDR_EXPR might be wrong. */
10008 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10009 recompute_tree_invariant_for_addr_expr (t);
10011 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10012 return NULL_TREE;
10015 static void
10016 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10018 gimple stmt = gsi_stmt (*gsi_p);
10019 struct walk_stmt_info wi;
10021 if (gimple_has_location (stmt))
10022 input_location = gimple_location (stmt);
10024 if (task_shared_vars)
10025 memset (&wi, '\0', sizeof (wi));
10027 /* If we have issued syntax errors, avoid doing any heavy lifting.
10028 Just replace the OpenMP directives with a NOP to avoid
10029 confusing RTL expansion. */
10030 if (seen_error () && is_gimple_omp (stmt))
10032 gsi_replace (gsi_p, gimple_build_nop (), true);
10033 return;
10036 switch (gimple_code (stmt))
10038 case GIMPLE_COND:
10039 if ((ctx || task_shared_vars)
10040 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
10041 ctx ? NULL : &wi, NULL)
10042 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
10043 ctx ? NULL : &wi, NULL)))
10044 gimple_regimplify_operands (stmt, gsi_p);
10045 break;
10046 case GIMPLE_CATCH:
10047 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
10048 break;
10049 case GIMPLE_EH_FILTER:
10050 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10051 break;
10052 case GIMPLE_TRY:
10053 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10054 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10055 break;
10056 case GIMPLE_TRANSACTION:
10057 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
10058 break;
10059 case GIMPLE_BIND:
10060 lower_omp (gimple_bind_body_ptr (stmt), ctx);
10061 break;
10062 case GIMPLE_OMP_PARALLEL:
10063 case GIMPLE_OMP_TASK:
10064 ctx = maybe_lookup_ctx (stmt);
10065 gcc_assert (ctx);
10066 if (ctx->cancellable)
10067 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10068 lower_omp_taskreg (gsi_p, ctx);
10069 break;
10070 case GIMPLE_OMP_FOR:
10071 ctx = maybe_lookup_ctx (stmt);
10072 gcc_assert (ctx);
10073 if (ctx->cancellable)
10074 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10075 lower_omp_for (gsi_p, ctx);
10076 break;
10077 case GIMPLE_OMP_SECTIONS:
10078 ctx = maybe_lookup_ctx (stmt);
10079 gcc_assert (ctx);
10080 if (ctx->cancellable)
10081 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10082 lower_omp_sections (gsi_p, ctx);
10083 break;
10084 case GIMPLE_OMP_SINGLE:
10085 ctx = maybe_lookup_ctx (stmt);
10086 gcc_assert (ctx);
10087 lower_omp_single (gsi_p, ctx);
10088 break;
10089 case GIMPLE_OMP_MASTER:
10090 ctx = maybe_lookup_ctx (stmt);
10091 gcc_assert (ctx);
10092 lower_omp_master (gsi_p, ctx);
10093 break;
10094 case GIMPLE_OMP_TASKGROUP:
10095 ctx = maybe_lookup_ctx (stmt);
10096 gcc_assert (ctx);
10097 lower_omp_taskgroup (gsi_p, ctx);
10098 break;
10099 case GIMPLE_OMP_ORDERED:
10100 ctx = maybe_lookup_ctx (stmt);
10101 gcc_assert (ctx);
10102 lower_omp_ordered (gsi_p, ctx);
10103 break;
10104 case GIMPLE_OMP_CRITICAL:
10105 ctx = maybe_lookup_ctx (stmt);
10106 gcc_assert (ctx);
10107 lower_omp_critical (gsi_p, ctx);
10108 break;
10109 case GIMPLE_OMP_ATOMIC_LOAD:
10110 if ((ctx || task_shared_vars)
10111 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
10112 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10113 gimple_regimplify_operands (stmt, gsi_p);
10114 break;
10115 case GIMPLE_OMP_TARGET:
10116 ctx = maybe_lookup_ctx (stmt);
10117 gcc_assert (ctx);
10118 lower_omp_target (gsi_p, ctx);
10119 break;
10120 case GIMPLE_OMP_TEAMS:
10121 ctx = maybe_lookup_ctx (stmt);
10122 gcc_assert (ctx);
10123 lower_omp_teams (gsi_p, ctx);
10124 break;
10125 case GIMPLE_CALL:
10126 tree fndecl;
10127 fndecl = gimple_call_fndecl (stmt);
10128 if (fndecl
10129 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10130 switch (DECL_FUNCTION_CODE (fndecl))
10132 case BUILT_IN_GOMP_BARRIER:
10133 if (ctx == NULL)
10134 break;
10135 /* FALLTHRU */
10136 case BUILT_IN_GOMP_CANCEL:
10137 case BUILT_IN_GOMP_CANCELLATION_POINT:
10138 omp_context *cctx;
10139 cctx = ctx;
10140 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10141 cctx = cctx->outer;
10142 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10143 if (!cctx->cancellable)
10145 if (DECL_FUNCTION_CODE (fndecl)
10146 == BUILT_IN_GOMP_CANCELLATION_POINT)
10148 stmt = gimple_build_nop ();
10149 gsi_replace (gsi_p, stmt, false);
10151 break;
10153 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10155 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10156 gimple_call_set_fndecl (stmt, fndecl);
10157 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10159 tree lhs;
10160 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
10161 gimple_call_set_lhs (stmt, lhs);
10162 tree fallthru_label;
10163 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10164 gimple g;
10165 g = gimple_build_label (fallthru_label);
10166 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10167 g = gimple_build_cond (NE_EXPR, lhs,
10168 fold_convert (TREE_TYPE (lhs),
10169 boolean_false_node),
10170 cctx->cancel_label, fallthru_label);
10171 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10172 break;
10173 default:
10174 break;
10176 /* FALLTHRU */
10177 default:
10178 if ((ctx || task_shared_vars)
10179 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10180 ctx ? NULL : &wi))
10182 /* Just remove clobbers, this should happen only if we have
10183 "privatized" local addressable variables in SIMD regions,
10184 the clobber isn't needed in that case and gimplifying address
10185 of the ARRAY_REF into a pointer and creating MEM_REF based
10186 clobber would create worse code than we get with the clobber
10187 dropped. */
10188 if (gimple_clobber_p (stmt))
10190 gsi_replace (gsi_p, gimple_build_nop (), true);
10191 break;
10193 gimple_regimplify_operands (stmt, gsi_p);
10195 break;
10199 static void
10200 lower_omp (gimple_seq *body, omp_context *ctx)
10202 location_t saved_location = input_location;
10203 gimple_stmt_iterator gsi;
10204 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10205 lower_omp_1 (&gsi, ctx);
10206 /* During gimplification, we have not always invoked fold_stmt
10207 (gimplify.c:maybe_fold_stmt); call it now. */
10208 if (target_nesting_level)
10209 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10210 fold_stmt (&gsi);
10211 input_location = saved_location;
10214 /* Main entry point. */
10216 static unsigned int
10217 execute_lower_omp (void)
10219 gimple_seq body;
10221 /* This pass always runs, to provide PROP_gimple_lomp.
10222 But there is nothing to do unless -fopenmp is given. */
10223 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10224 return 0;
10226 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10227 delete_omp_context);
10229 body = gimple_body (current_function_decl);
10230 scan_omp (&body, NULL);
10231 gcc_assert (taskreg_nesting_level == 0);
10233 if (all_contexts->root)
10235 if (task_shared_vars)
10236 push_gimplify_context ();
10237 lower_omp (&body, NULL);
10238 if (task_shared_vars)
10239 pop_gimplify_context (NULL);
10242 if (all_contexts)
10244 splay_tree_delete (all_contexts);
10245 all_contexts = NULL;
10247 BITMAP_FREE (task_shared_vars);
10248 return 0;
10251 namespace {
10253 const pass_data pass_data_lower_omp =
10255 GIMPLE_PASS, /* type */
10256 "omplower", /* name */
10257 OPTGROUP_NONE, /* optinfo_flags */
10258 true, /* has_execute */
10259 TV_NONE, /* tv_id */
10260 PROP_gimple_any, /* properties_required */
10261 PROP_gimple_lomp, /* properties_provided */
10262 0, /* properties_destroyed */
10263 0, /* todo_flags_start */
10264 0, /* todo_flags_finish */
10267 class pass_lower_omp : public gimple_opt_pass
10269 public:
10270 pass_lower_omp (gcc::context *ctxt)
10271 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10274 /* opt_pass methods: */
10275 virtual unsigned int execute (function *) { return execute_lower_omp (); }
10277 }; // class pass_lower_omp
10279 } // anon namespace
10281 gimple_opt_pass *
10282 make_pass_lower_omp (gcc::context *ctxt)
10284 return new pass_lower_omp (ctxt);
10287 /* The following is a utility to diagnose OpenMP structured block violations.
10288 It is not part of the "omplower" pass, as that's invoked too late. It
10289 should be invoked by the respective front ends after gimplification. */
10291 static splay_tree all_labels;
10293 /* Check for mismatched contexts and generate an error if needed. Return
10294 true if an error is detected. */
10296 static bool
10297 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10298 gimple branch_ctx, gimple label_ctx)
10300 if (label_ctx == branch_ctx)
10301 return false;
10305 Previously we kept track of the label's entire context in diagnose_sb_[12]
10306 so we could traverse it and issue a correct "exit" or "enter" error
10307 message upon a structured block violation.
10309 We built the context by building a list with tree_cons'ing, but there is
10310 no easy counterpart in gimple tuples. It seems like far too much work
10311 for issuing exit/enter error messages. If someone really misses the
10312 distinct error message... patches welcome.
10315 #if 0
10316 /* Try to avoid confusing the user by producing and error message
10317 with correct "exit" or "enter" verbiage. We prefer "exit"
10318 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10319 if (branch_ctx == NULL)
10320 exit_p = false;
10321 else
10323 while (label_ctx)
10325 if (TREE_VALUE (label_ctx) == branch_ctx)
10327 exit_p = false;
10328 break;
10330 label_ctx = TREE_CHAIN (label_ctx);
10334 if (exit_p)
10335 error ("invalid exit from OpenMP structured block");
10336 else
10337 error ("invalid entry to OpenMP structured block");
10338 #endif
10340 bool cilkplus_block = false;
10341 if (flag_cilkplus)
10343 if ((branch_ctx
10344 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10345 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10346 || (label_ctx
10347 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10348 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10349 cilkplus_block = true;
10352 /* If it's obvious we have an invalid entry, be specific about the error. */
10353 if (branch_ctx == NULL)
10355 if (cilkplus_block)
10356 error ("invalid entry to Cilk Plus structured block");
10357 else
10358 error ("invalid entry to OpenMP structured block");
10360 else
10362 /* Otherwise, be vague and lazy, but efficient. */
10363 if (cilkplus_block)
10364 error ("invalid branch to/from a Cilk Plus structured block");
10365 else
10366 error ("invalid branch to/from an OpenMP structured block");
10369 gsi_replace (gsi_p, gimple_build_nop (), false);
10370 return true;
10373 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10374 where each label is found. */
10376 static tree
10377 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10378 struct walk_stmt_info *wi)
10380 gimple context = (gimple) wi->info;
10381 gimple inner_context;
10382 gimple stmt = gsi_stmt (*gsi_p);
10384 *handled_ops_p = true;
10386 switch (gimple_code (stmt))
10388 WALK_SUBSTMTS;
10390 case GIMPLE_OMP_PARALLEL:
10391 case GIMPLE_OMP_TASK:
10392 case GIMPLE_OMP_SECTIONS:
10393 case GIMPLE_OMP_SINGLE:
10394 case GIMPLE_OMP_SECTION:
10395 case GIMPLE_OMP_MASTER:
10396 case GIMPLE_OMP_ORDERED:
10397 case GIMPLE_OMP_CRITICAL:
10398 case GIMPLE_OMP_TARGET:
10399 case GIMPLE_OMP_TEAMS:
10400 case GIMPLE_OMP_TASKGROUP:
10401 /* The minimal context here is just the current OMP construct. */
10402 inner_context = stmt;
10403 wi->info = inner_context;
10404 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10405 wi->info = context;
10406 break;
10408 case GIMPLE_OMP_FOR:
10409 inner_context = stmt;
10410 wi->info = inner_context;
10411 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10412 walk them. */
10413 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10414 diagnose_sb_1, NULL, wi);
10415 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10416 wi->info = context;
10417 break;
10419 case GIMPLE_LABEL:
10420 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10421 (splay_tree_value) context);
10422 break;
10424 default:
10425 break;
10428 return NULL_TREE;
10431 /* Pass 2: Check each branch and see if its context differs from that of
10432 the destination label's context. */
10434 static tree
10435 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10436 struct walk_stmt_info *wi)
10438 gimple context = (gimple) wi->info;
10439 splay_tree_node n;
10440 gimple stmt = gsi_stmt (*gsi_p);
10442 *handled_ops_p = true;
10444 switch (gimple_code (stmt))
10446 WALK_SUBSTMTS;
10448 case GIMPLE_OMP_PARALLEL:
10449 case GIMPLE_OMP_TASK:
10450 case GIMPLE_OMP_SECTIONS:
10451 case GIMPLE_OMP_SINGLE:
10452 case GIMPLE_OMP_SECTION:
10453 case GIMPLE_OMP_MASTER:
10454 case GIMPLE_OMP_ORDERED:
10455 case GIMPLE_OMP_CRITICAL:
10456 case GIMPLE_OMP_TARGET:
10457 case GIMPLE_OMP_TEAMS:
10458 case GIMPLE_OMP_TASKGROUP:
10459 wi->info = stmt;
10460 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10461 wi->info = context;
10462 break;
10464 case GIMPLE_OMP_FOR:
10465 wi->info = stmt;
10466 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10467 walk them. */
10468 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10469 diagnose_sb_2, NULL, wi);
10470 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10471 wi->info = context;
10472 break;
10474 case GIMPLE_COND:
10476 tree lab = gimple_cond_true_label (stmt);
10477 if (lab)
10479 n = splay_tree_lookup (all_labels,
10480 (splay_tree_key) lab);
10481 diagnose_sb_0 (gsi_p, context,
10482 n ? (gimple) n->value : NULL);
10484 lab = gimple_cond_false_label (stmt);
10485 if (lab)
10487 n = splay_tree_lookup (all_labels,
10488 (splay_tree_key) lab);
10489 diagnose_sb_0 (gsi_p, context,
10490 n ? (gimple) n->value : NULL);
10493 break;
10495 case GIMPLE_GOTO:
10497 tree lab = gimple_goto_dest (stmt);
10498 if (TREE_CODE (lab) != LABEL_DECL)
10499 break;
10501 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10502 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10504 break;
10506 case GIMPLE_SWITCH:
10508 unsigned int i;
10509 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10511 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10512 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10513 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10514 break;
10517 break;
10519 case GIMPLE_RETURN:
10520 diagnose_sb_0 (gsi_p, context, NULL);
10521 break;
10523 default:
10524 break;
10527 return NULL_TREE;
10530 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10531 codes. */
10532 bool
10533 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
10534 int *region_idx)
10536 gimple last = last_stmt (bb);
10537 enum gimple_code code = gimple_code (last);
10538 struct omp_region *cur_region = *region;
10539 bool fallthru = false;
10541 switch (code)
10543 case GIMPLE_OMP_PARALLEL:
10544 case GIMPLE_OMP_TASK:
10545 case GIMPLE_OMP_FOR:
10546 case GIMPLE_OMP_SINGLE:
10547 case GIMPLE_OMP_TEAMS:
10548 case GIMPLE_OMP_MASTER:
10549 case GIMPLE_OMP_TASKGROUP:
10550 case GIMPLE_OMP_ORDERED:
10551 case GIMPLE_OMP_CRITICAL:
10552 case GIMPLE_OMP_SECTION:
10553 cur_region = new_omp_region (bb, code, cur_region);
10554 fallthru = true;
10555 break;
10557 case GIMPLE_OMP_TARGET:
10558 cur_region = new_omp_region (bb, code, cur_region);
10559 fallthru = true;
10560 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10561 cur_region = cur_region->outer;
10562 break;
10564 case GIMPLE_OMP_SECTIONS:
10565 cur_region = new_omp_region (bb, code, cur_region);
10566 fallthru = true;
10567 break;
10569 case GIMPLE_OMP_SECTIONS_SWITCH:
10570 fallthru = false;
10571 break;
10573 case GIMPLE_OMP_ATOMIC_LOAD:
10574 case GIMPLE_OMP_ATOMIC_STORE:
10575 fallthru = true;
10576 break;
10578 case GIMPLE_OMP_RETURN:
10579 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10580 somewhere other than the next block. This will be
10581 created later. */
10582 cur_region->exit = bb;
10583 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
10584 cur_region = cur_region->outer;
10585 break;
10587 case GIMPLE_OMP_CONTINUE:
10588 cur_region->cont = bb;
10589 switch (cur_region->type)
10591 case GIMPLE_OMP_FOR:
10592 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
10593 succs edges as abnormal to prevent splitting
10594 them. */
10595 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
10596 /* Make the loopback edge. */
10597 make_edge (bb, single_succ (cur_region->entry),
10598 EDGE_ABNORMAL);
10600 /* Create an edge from GIMPLE_OMP_FOR to exit, which
10601 corresponds to the case that the body of the loop
10602 is not executed at all. */
10603 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
10604 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
10605 fallthru = false;
10606 break;
10608 case GIMPLE_OMP_SECTIONS:
10609 /* Wire up the edges into and out of the nested sections. */
10611 basic_block switch_bb = single_succ (cur_region->entry);
10613 struct omp_region *i;
10614 for (i = cur_region->inner; i ; i = i->next)
10616 gcc_assert (i->type == GIMPLE_OMP_SECTION);
10617 make_edge (switch_bb, i->entry, 0);
10618 make_edge (i->exit, bb, EDGE_FALLTHRU);
10621 /* Make the loopback edge to the block with
10622 GIMPLE_OMP_SECTIONS_SWITCH. */
10623 make_edge (bb, switch_bb, 0);
10625 /* Make the edge from the switch to exit. */
10626 make_edge (switch_bb, bb->next_bb, 0);
10627 fallthru = false;
10629 break;
10631 default:
10632 gcc_unreachable ();
10634 break;
10636 default:
10637 gcc_unreachable ();
10640 if (*region != cur_region)
10642 *region = cur_region;
10643 if (cur_region)
10644 *region_idx = cur_region->entry->index;
10645 else
10646 *region_idx = 0;
10649 return fallthru;
10652 static unsigned int
10653 diagnose_omp_structured_block_errors (void)
10655 struct walk_stmt_info wi;
10656 gimple_seq body = gimple_body (current_function_decl);
10658 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
10660 memset (&wi, 0, sizeof (wi));
10661 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
10663 memset (&wi, 0, sizeof (wi));
10664 wi.want_locations = true;
10665 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
10667 gimple_set_body (current_function_decl, body);
10669 splay_tree_delete (all_labels);
10670 all_labels = NULL;
10672 return 0;
10675 namespace {
10677 const pass_data pass_data_diagnose_omp_blocks =
10679 GIMPLE_PASS, /* type */
10680 "*diagnose_omp_blocks", /* name */
10681 OPTGROUP_NONE, /* optinfo_flags */
10682 true, /* has_execute */
10683 TV_NONE, /* tv_id */
10684 PROP_gimple_any, /* properties_required */
10685 0, /* properties_provided */
10686 0, /* properties_destroyed */
10687 0, /* todo_flags_start */
10688 0, /* todo_flags_finish */
10691 class pass_diagnose_omp_blocks : public gimple_opt_pass
10693 public:
10694 pass_diagnose_omp_blocks (gcc::context *ctxt)
10695 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
10698 /* opt_pass methods: */
10699 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
10700 virtual unsigned int execute (function *)
10702 return diagnose_omp_structured_block_errors ();
10705 }; // class pass_diagnose_omp_blocks
10707 } // anon namespace
10709 gimple_opt_pass *
10710 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
10712 return new pass_diagnose_omp_blocks (ctxt);
10715 /* SIMD clone supporting code. */
10717 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
10718 of arguments to reserve space for. */
10720 static struct cgraph_simd_clone *
10721 simd_clone_struct_alloc (int nargs)
10723 struct cgraph_simd_clone *clone_info;
10724 size_t len = (sizeof (struct cgraph_simd_clone)
10725 + nargs * sizeof (struct cgraph_simd_clone_arg));
10726 clone_info = (struct cgraph_simd_clone *)
10727 ggc_internal_cleared_alloc (len);
10728 return clone_info;
10731 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
10733 static inline void
10734 simd_clone_struct_copy (struct cgraph_simd_clone *to,
10735 struct cgraph_simd_clone *from)
10737 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
10738 + ((from->nargs - from->inbranch)
10739 * sizeof (struct cgraph_simd_clone_arg))));
10742 /* Return vector of parameter types of function FNDECL. This uses
10743 TYPE_ARG_TYPES if available, otherwise falls back to types of
10744 DECL_ARGUMENTS types. */
10746 vec<tree>
10747 simd_clone_vector_of_formal_parm_types (tree fndecl)
10749 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
10750 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
10751 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
10752 unsigned int i;
10753 tree arg;
10754 FOR_EACH_VEC_ELT (args, i, arg)
10755 args[i] = TREE_TYPE (args[i]);
10756 return args;
10759 /* Given a simd function in NODE, extract the simd specific
10760 information from the OMP clauses passed in CLAUSES, and return
10761 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
10762 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
10763 otherwise set to FALSE. */
10765 static struct cgraph_simd_clone *
10766 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
10767 bool *inbranch_specified)
10769 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
10770 tree t;
10771 int n;
10772 *inbranch_specified = false;
10774 n = args.length ();
10775 if (n > 0 && args.last () == void_type_node)
10776 n--;
10778 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
10779 be cloned have a distinctive artificial label in addition to "omp
10780 declare simd". */
10781 bool cilk_clone
10782 = (flag_cilkplus
10783 && lookup_attribute ("cilk simd function",
10784 DECL_ATTRIBUTES (node->decl)));
10786 /* Allocate one more than needed just in case this is an in-branch
10787 clone which will require a mask argument. */
10788 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
10789 clone_info->nargs = n;
10790 clone_info->cilk_elemental = cilk_clone;
10792 if (!clauses)
10794 args.release ();
10795 return clone_info;
10797 clauses = TREE_VALUE (clauses);
10798 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
10799 return clone_info;
10801 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
10803 switch (OMP_CLAUSE_CODE (t))
10805 case OMP_CLAUSE_INBRANCH:
10806 clone_info->inbranch = 1;
10807 *inbranch_specified = true;
10808 break;
10809 case OMP_CLAUSE_NOTINBRANCH:
10810 clone_info->inbranch = 0;
10811 *inbranch_specified = true;
10812 break;
10813 case OMP_CLAUSE_SIMDLEN:
10814 clone_info->simdlen
10815 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
10816 break;
10817 case OMP_CLAUSE_LINEAR:
10819 tree decl = OMP_CLAUSE_DECL (t);
10820 tree step = OMP_CLAUSE_LINEAR_STEP (t);
10821 int argno = TREE_INT_CST_LOW (decl);
10822 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
10824 clone_info->args[argno].arg_type
10825 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
10826 clone_info->args[argno].linear_step = tree_to_shwi (step);
10827 gcc_assert (clone_info->args[argno].linear_step >= 0
10828 && clone_info->args[argno].linear_step < n);
10830 else
10832 if (POINTER_TYPE_P (args[argno]))
10833 step = fold_convert (ssizetype, step);
10834 if (!tree_fits_shwi_p (step))
10836 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10837 "ignoring large linear step");
10838 args.release ();
10839 return NULL;
10841 else if (integer_zerop (step))
10843 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10844 "ignoring zero linear step");
10845 args.release ();
10846 return NULL;
10848 else
10850 clone_info->args[argno].arg_type
10851 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
10852 clone_info->args[argno].linear_step = tree_to_shwi (step);
10855 break;
10857 case OMP_CLAUSE_UNIFORM:
10859 tree decl = OMP_CLAUSE_DECL (t);
10860 int argno = tree_to_uhwi (decl);
10861 clone_info->args[argno].arg_type
10862 = SIMD_CLONE_ARG_TYPE_UNIFORM;
10863 break;
10865 case OMP_CLAUSE_ALIGNED:
10867 tree decl = OMP_CLAUSE_DECL (t);
10868 int argno = tree_to_uhwi (decl);
10869 clone_info->args[argno].alignment
10870 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
10871 break;
10873 default:
10874 break;
10877 args.release ();
10878 return clone_info;
10881 /* Given a SIMD clone in NODE, calculate the characteristic data
10882 type and return the coresponding type. The characteristic data
10883 type is computed as described in the Intel Vector ABI. */
10885 static tree
10886 simd_clone_compute_base_data_type (struct cgraph_node *node,
10887 struct cgraph_simd_clone *clone_info)
10889 tree type = integer_type_node;
10890 tree fndecl = node->decl;
10892 /* a) For non-void function, the characteristic data type is the
10893 return type. */
10894 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
10895 type = TREE_TYPE (TREE_TYPE (fndecl));
10897 /* b) If the function has any non-uniform, non-linear parameters,
10898 then the characteristic data type is the type of the first
10899 such parameter. */
10900 else
10902 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
10903 for (unsigned int i = 0; i < clone_info->nargs; ++i)
10904 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
10906 type = map[i];
10907 break;
10909 map.release ();
10912 /* c) If the characteristic data type determined by a) or b) above
10913 is struct, union, or class type which is pass-by-value (except
10914 for the type that maps to the built-in complex data type), the
10915 characteristic data type is int. */
10916 if (RECORD_OR_UNION_TYPE_P (type)
10917 && !aggregate_value_p (type, NULL)
10918 && TREE_CODE (type) != COMPLEX_TYPE)
10919 return integer_type_node;
10921 /* d) If none of the above three classes is applicable, the
10922 characteristic data type is int. */
10924 return type;
10926 /* e) For Intel Xeon Phi native and offload compilation, if the
10927 resulting characteristic data type is 8-bit or 16-bit integer
10928 data type, the characteristic data type is int. */
10929 /* Well, we don't handle Xeon Phi yet. */
10932 static tree
10933 simd_clone_mangle (struct cgraph_node *node,
10934 struct cgraph_simd_clone *clone_info)
10936 char vecsize_mangle = clone_info->vecsize_mangle;
10937 char mask = clone_info->inbranch ? 'M' : 'N';
10938 unsigned int simdlen = clone_info->simdlen;
10939 unsigned int n;
10940 pretty_printer pp;
10942 gcc_assert (vecsize_mangle && simdlen);
10944 pp_string (&pp, "_ZGV");
10945 pp_character (&pp, vecsize_mangle);
10946 pp_character (&pp, mask);
10947 pp_decimal_int (&pp, simdlen);
10949 for (n = 0; n < clone_info->nargs; ++n)
10951 struct cgraph_simd_clone_arg arg = clone_info->args[n];
10953 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
10954 pp_character (&pp, 'u');
10955 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
10957 gcc_assert (arg.linear_step != 0);
10958 pp_character (&pp, 'l');
10959 if (arg.linear_step > 1)
10960 pp_unsigned_wide_integer (&pp, arg.linear_step);
10961 else if (arg.linear_step < 0)
10963 pp_character (&pp, 'n');
10964 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
10965 arg.linear_step));
10968 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
10970 pp_character (&pp, 's');
10971 pp_unsigned_wide_integer (&pp, arg.linear_step);
10973 else
10974 pp_character (&pp, 'v');
10975 if (arg.alignment)
10977 pp_character (&pp, 'a');
10978 pp_decimal_int (&pp, arg.alignment);
10982 pp_underscore (&pp);
10983 pp_string (&pp,
10984 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
10985 const char *str = pp_formatted_text (&pp);
10987 /* If there already is a SIMD clone with the same mangled name, don't
10988 add another one. This can happen e.g. for
10989 #pragma omp declare simd
10990 #pragma omp declare simd simdlen(8)
10991 int foo (int, int);
10992 if the simdlen is assumed to be 8 for the first one, etc. */
10993 for (struct cgraph_node *clone = node->simd_clones; clone;
10994 clone = clone->simdclone->next_clone)
10995 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
10996 str) == 0)
10997 return NULL_TREE;
10999 return get_identifier (str);
11002 /* Create a simd clone of OLD_NODE and return it. */
11004 static struct cgraph_node *
11005 simd_clone_create (struct cgraph_node *old_node)
11007 struct cgraph_node *new_node;
11008 if (old_node->definition)
11010 if (!cgraph_function_with_gimple_body_p (old_node))
11011 return NULL;
11012 cgraph_get_body (old_node);
11013 new_node = cgraph_function_versioning (old_node, vNULL, NULL, NULL,
11014 false, NULL, NULL, "simdclone");
11016 else
11018 tree old_decl = old_node->decl;
11019 tree new_decl = copy_node (old_node->decl);
11020 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11021 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11022 SET_DECL_RTL (new_decl, NULL);
11023 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11024 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11025 new_node
11026 = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL);
11027 cgraph_call_function_insertion_hooks (new_node);
11029 if (new_node == NULL)
11030 return new_node;
11032 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11034 /* The function cgraph_function_versioning () will force the new
11035 symbol local. Undo this, and inherit external visability from
11036 the old node. */
11037 new_node->local.local = old_node->local.local;
11038 new_node->externally_visible = old_node->externally_visible;
11040 return new_node;
11043 /* Adjust the return type of the given function to its appropriate
11044 vector counterpart. Returns a simd array to be used throughout the
11045 function as a return value. */
11047 static tree
11048 simd_clone_adjust_return_type (struct cgraph_node *node)
11050 tree fndecl = node->decl;
11051 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11052 unsigned int veclen;
11053 tree t;
11055 /* Adjust the function return type. */
11056 if (orig_rettype == void_type_node)
11057 return NULL_TREE;
11058 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11059 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11060 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11061 veclen = node->simdclone->vecsize_int;
11062 else
11063 veclen = node->simdclone->vecsize_float;
11064 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11065 if (veclen > node->simdclone->simdlen)
11066 veclen = node->simdclone->simdlen;
11067 if (veclen == node->simdclone->simdlen)
11068 TREE_TYPE (TREE_TYPE (fndecl))
11069 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11070 node->simdclone->simdlen);
11071 else
11073 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11074 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11075 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11077 if (!node->definition)
11078 return NULL_TREE;
11080 t = DECL_RESULT (fndecl);
11081 /* Adjust the DECL_RESULT. */
11082 gcc_assert (TREE_TYPE (t) != void_type_node);
11083 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11084 relayout_decl (t);
11086 tree atype = build_array_type_nelts (orig_rettype,
11087 node->simdclone->simdlen);
11088 if (veclen != node->simdclone->simdlen)
11089 return build1 (VIEW_CONVERT_EXPR, atype, t);
11091 /* Set up a SIMD array to use as the return value. */
11092 tree retval = create_tmp_var_raw (atype, "retval");
11093 gimple_add_tmp_var (retval);
11094 return retval;
11097 /* Each vector argument has a corresponding array to be used locally
11098 as part of the eventual loop. Create such temporary array and
11099 return it.
11101 PREFIX is the prefix to be used for the temporary.
11103 TYPE is the inner element type.
11105 SIMDLEN is the number of elements. */
11107 static tree
11108 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11110 tree atype = build_array_type_nelts (type, simdlen);
11111 tree avar = create_tmp_var_raw (atype, prefix);
11112 gimple_add_tmp_var (avar);
11113 return avar;
11116 /* Modify the function argument types to their corresponding vector
11117 counterparts if appropriate. Also, create one array for each simd
11118 argument to be used locally when using the function arguments as
11119 part of the loop.
11121 NODE is the function whose arguments are to be adjusted.
11123 Returns an adjustment vector that will be filled describing how the
11124 argument types will be adjusted. */
11126 static ipa_parm_adjustment_vec
11127 simd_clone_adjust_argument_types (struct cgraph_node *node)
11129 vec<tree> args;
11130 ipa_parm_adjustment_vec adjustments;
11132 if (node->definition)
11133 args = ipa_get_vector_of_formal_parms (node->decl);
11134 else
11135 args = simd_clone_vector_of_formal_parm_types (node->decl);
11136 adjustments.create (args.length ());
11137 unsigned i, j, veclen;
11138 struct ipa_parm_adjustment adj;
11139 for (i = 0; i < node->simdclone->nargs; ++i)
11141 memset (&adj, 0, sizeof (adj));
11142 tree parm = args[i];
11143 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11144 adj.base_index = i;
11145 adj.base = parm;
11147 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11148 node->simdclone->args[i].orig_type = parm_type;
11150 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11152 /* No adjustment necessary for scalar arguments. */
11153 adj.op = IPA_PARM_OP_COPY;
11155 else
11157 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11158 veclen = node->simdclone->vecsize_int;
11159 else
11160 veclen = node->simdclone->vecsize_float;
11161 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11162 if (veclen > node->simdclone->simdlen)
11163 veclen = node->simdclone->simdlen;
11164 adj.arg_prefix = "simd";
11165 adj.type = build_vector_type (parm_type, veclen);
11166 node->simdclone->args[i].vector_type = adj.type;
11167 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11169 adjustments.safe_push (adj);
11170 if (j == veclen)
11172 memset (&adj, 0, sizeof (adj));
11173 adj.op = IPA_PARM_OP_NEW;
11174 adj.arg_prefix = "simd";
11175 adj.base_index = i;
11176 adj.type = node->simdclone->args[i].vector_type;
11180 if (node->definition)
11181 node->simdclone->args[i].simd_array
11182 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11183 parm_type, node->simdclone->simdlen);
11185 adjustments.safe_push (adj);
11188 if (node->simdclone->inbranch)
11190 tree base_type
11191 = simd_clone_compute_base_data_type (node->simdclone->origin,
11192 node->simdclone);
11194 memset (&adj, 0, sizeof (adj));
11195 adj.op = IPA_PARM_OP_NEW;
11196 adj.arg_prefix = "mask";
11198 adj.base_index = i;
11199 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11200 veclen = node->simdclone->vecsize_int;
11201 else
11202 veclen = node->simdclone->vecsize_float;
11203 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11204 if (veclen > node->simdclone->simdlen)
11205 veclen = node->simdclone->simdlen;
11206 adj.type = build_vector_type (base_type, veclen);
11207 adjustments.safe_push (adj);
11209 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11210 adjustments.safe_push (adj);
11212 /* We have previously allocated one extra entry for the mask. Use
11213 it and fill it. */
11214 struct cgraph_simd_clone *sc = node->simdclone;
11215 sc->nargs++;
11216 if (node->definition)
11218 sc->args[i].orig_arg
11219 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11220 sc->args[i].simd_array
11221 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11223 sc->args[i].orig_type = base_type;
11224 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11227 if (node->definition)
11228 ipa_modify_formal_parameters (node->decl, adjustments);
11229 else
11231 tree new_arg_types = NULL_TREE, new_reversed;
11232 bool last_parm_void = false;
11233 if (args.length () > 0 && args.last () == void_type_node)
11234 last_parm_void = true;
11236 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11237 j = adjustments.length ();
11238 for (i = 0; i < j; i++)
11240 struct ipa_parm_adjustment *adj = &adjustments[i];
11241 tree ptype;
11242 if (adj->op == IPA_PARM_OP_COPY)
11243 ptype = args[adj->base_index];
11244 else
11245 ptype = adj->type;
11246 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11248 new_reversed = nreverse (new_arg_types);
11249 if (last_parm_void)
11251 if (new_reversed)
11252 TREE_CHAIN (new_arg_types) = void_list_node;
11253 else
11254 new_reversed = void_list_node;
11257 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11258 TYPE_ARG_TYPES (new_type) = new_reversed;
11259 TREE_TYPE (node->decl) = new_type;
11261 adjustments.release ();
11263 args.release ();
11264 return adjustments;
11267 /* Initialize and copy the function arguments in NODE to their
11268 corresponding local simd arrays. Returns a fresh gimple_seq with
11269 the instruction sequence generated. */
11271 static gimple_seq
11272 simd_clone_init_simd_arrays (struct cgraph_node *node,
11273 ipa_parm_adjustment_vec adjustments)
11275 gimple_seq seq = NULL;
11276 unsigned i = 0, j = 0, k;
11278 for (tree arg = DECL_ARGUMENTS (node->decl);
11279 arg;
11280 arg = DECL_CHAIN (arg), i++, j++)
11282 if (adjustments[j].op == IPA_PARM_OP_COPY)
11283 continue;
11285 node->simdclone->args[i].vector_arg = arg;
11287 tree array = node->simdclone->args[i].simd_array;
11288 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11290 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11291 tree ptr = build_fold_addr_expr (array);
11292 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11293 build_int_cst (ptype, 0));
11294 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11295 gimplify_and_add (t, &seq);
11297 else
11299 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11300 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11301 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11303 tree ptr = build_fold_addr_expr (array);
11304 int elemsize;
11305 if (k)
11307 arg = DECL_CHAIN (arg);
11308 j++;
11310 elemsize
11311 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11312 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11313 build_int_cst (ptype, k * elemsize));
11314 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11315 gimplify_and_add (t, &seq);
11319 return seq;
11322 /* Callback info for ipa_simd_modify_stmt_ops below. */
11324 struct modify_stmt_info {
11325 ipa_parm_adjustment_vec adjustments;
11326 gimple stmt;
11327 /* True if the parent statement was modified by
11328 ipa_simd_modify_stmt_ops. */
11329 bool modified;
11332 /* Callback for walk_gimple_op.
11334 Adjust operands from a given statement as specified in the
11335 adjustments vector in the callback data. */
11337 static tree
11338 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11340 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11341 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11342 tree *orig_tp = tp;
11343 if (TREE_CODE (*tp) == ADDR_EXPR)
11344 tp = &TREE_OPERAND (*tp, 0);
11345 struct ipa_parm_adjustment *cand = NULL;
11346 if (TREE_CODE (*tp) == PARM_DECL)
11347 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11348 else
11350 if (TYPE_P (*tp))
11351 *walk_subtrees = 0;
11354 tree repl = NULL_TREE;
11355 if (cand)
11356 repl = unshare_expr (cand->new_decl);
11357 else
11359 if (tp != orig_tp)
11361 *walk_subtrees = 0;
11362 bool modified = info->modified;
11363 info->modified = false;
11364 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11365 if (!info->modified)
11367 info->modified = modified;
11368 return NULL_TREE;
11370 info->modified = modified;
11371 repl = *tp;
11373 else
11374 return NULL_TREE;
11377 if (tp != orig_tp)
11379 repl = build_fold_addr_expr (repl);
11380 gimple stmt
11381 = gimple_build_assign (make_ssa_name (TREE_TYPE (repl), NULL), repl);
11382 repl = gimple_assign_lhs (stmt);
11383 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11384 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11385 *orig_tp = repl;
11387 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11389 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11390 *tp = vce;
11392 else
11393 *tp = repl;
11395 info->modified = true;
11396 return NULL_TREE;
11399 /* Traverse the function body and perform all modifications as
11400 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11401 modified such that the replacement/reduction value will now be an
11402 offset into the corresponding simd_array.
11404 This function will replace all function argument uses with their
11405 corresponding simd array elements, and ajust the return values
11406 accordingly. */
11408 static void
11409 ipa_simd_modify_function_body (struct cgraph_node *node,
11410 ipa_parm_adjustment_vec adjustments,
11411 tree retval_array, tree iter)
11413 basic_block bb;
11414 unsigned int i, j, l;
11416 /* Re-use the adjustments array, but this time use it to replace
11417 every function argument use to an offset into the corresponding
11418 simd_array. */
11419 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11421 if (!node->simdclone->args[i].vector_arg)
11422 continue;
11424 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11425 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11426 adjustments[j].new_decl
11427 = build4 (ARRAY_REF,
11428 basetype,
11429 node->simdclone->args[i].simd_array,
11430 iter,
11431 NULL_TREE, NULL_TREE);
11432 if (adjustments[j].op == IPA_PARM_OP_NONE
11433 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11434 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11437 l = adjustments.length ();
11438 for (i = 1; i < num_ssa_names; i++)
11440 tree name = ssa_name (i);
11441 if (name
11442 && SSA_NAME_VAR (name)
11443 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11445 for (j = 0; j < l; j++)
11446 if (SSA_NAME_VAR (name) == adjustments[j].base
11447 && adjustments[j].new_decl)
11449 tree base_var;
11450 if (adjustments[j].new_ssa_base == NULL_TREE)
11452 base_var
11453 = copy_var_decl (adjustments[j].base,
11454 DECL_NAME (adjustments[j].base),
11455 TREE_TYPE (adjustments[j].base));
11456 adjustments[j].new_ssa_base = base_var;
11458 else
11459 base_var = adjustments[j].new_ssa_base;
11460 if (SSA_NAME_IS_DEFAULT_DEF (name))
11462 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11463 gimple_stmt_iterator gsi = gsi_after_labels (bb);
11464 tree new_decl = unshare_expr (adjustments[j].new_decl);
11465 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
11466 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11467 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
11468 gimple stmt = gimple_build_assign (name, new_decl);
11469 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11471 else
11472 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11477 struct modify_stmt_info info;
11478 info.adjustments = adjustments;
11480 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
11482 gimple_stmt_iterator gsi;
11484 gsi = gsi_start_bb (bb);
11485 while (!gsi_end_p (gsi))
11487 gimple stmt = gsi_stmt (gsi);
11488 info.stmt = stmt;
11489 struct walk_stmt_info wi;
11491 memset (&wi, 0, sizeof (wi));
11492 info.modified = false;
11493 wi.info = &info;
11494 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
11496 if (gimple_code (stmt) == GIMPLE_RETURN)
11498 tree retval = gimple_return_retval (stmt);
11499 if (!retval)
11501 gsi_remove (&gsi, true);
11502 continue;
11505 /* Replace `return foo' with `retval_array[iter] = foo'. */
11506 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
11507 retval_array, iter, NULL, NULL);
11508 stmt = gimple_build_assign (ref, retval);
11509 gsi_replace (&gsi, stmt, true);
11510 info.modified = true;
11513 if (info.modified)
11515 update_stmt (stmt);
11516 if (maybe_clean_eh_stmt (stmt))
11517 gimple_purge_dead_eh_edges (gimple_bb (stmt));
11519 gsi_next (&gsi);
11524 /* Adjust the argument types in NODE to their appropriate vector
11525 counterparts. */
11527 static void
11528 simd_clone_adjust (struct cgraph_node *node)
11530 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
11532 targetm.simd_clone.adjust (node);
11534 tree retval = simd_clone_adjust_return_type (node);
11535 ipa_parm_adjustment_vec adjustments
11536 = simd_clone_adjust_argument_types (node);
11538 push_gimplify_context ();
11540 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
11542 /* Adjust all uses of vector arguments accordingly. Adjust all
11543 return values accordingly. */
11544 tree iter = create_tmp_var (unsigned_type_node, "iter");
11545 tree iter1 = make_ssa_name (iter, NULL);
11546 tree iter2 = make_ssa_name (iter, NULL);
11547 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
11549 /* Initialize the iteration variable. */
11550 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11551 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
11552 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
11553 /* Insert the SIMD array and iv initialization at function
11554 entry. */
11555 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
11557 pop_gimplify_context (NULL);
11559 /* Create a new BB right before the original exit BB, to hold the
11560 iteration increment and the condition/branch. */
11561 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
11562 basic_block incr_bb = create_empty_bb (orig_exit);
11563 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11564 flag. Set it now to be a FALLTHRU_EDGE. */
11565 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
11566 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
11567 for (unsigned i = 0;
11568 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
11570 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
11571 redirect_edge_succ (e, incr_bb);
11573 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
11574 e->probability = REG_BR_PROB_BASE;
11575 gsi = gsi_last_bb (incr_bb);
11576 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
11577 build_int_cst (unsigned_type_node,
11578 1));
11579 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11581 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
11582 struct loop *loop = alloc_loop ();
11583 cfun->has_force_vectorize_loops = true;
11584 loop->safelen = node->simdclone->simdlen;
11585 loop->force_vectorize = true;
11586 loop->header = body_bb;
11587 add_bb_to_loop (incr_bb, loop);
11589 /* Branch around the body if the mask applies. */
11590 if (node->simdclone->inbranch)
11592 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
11593 tree mask_array
11594 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
11595 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
11596 tree aref = build4 (ARRAY_REF,
11597 TREE_TYPE (TREE_TYPE (mask_array)),
11598 mask_array, iter1,
11599 NULL, NULL);
11600 g = gimple_build_assign (mask, aref);
11601 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11602 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
11603 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
11605 aref = build1 (VIEW_CONVERT_EXPR,
11606 build_nonstandard_integer_type (bitsize, 0), mask);
11607 mask = make_ssa_name (TREE_TYPE (aref), NULL);
11608 g = gimple_build_assign (mask, aref);
11609 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11612 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
11613 NULL, NULL);
11614 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11615 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
11616 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
11619 /* Generate the condition. */
11620 g = gimple_build_cond (LT_EXPR,
11621 iter2,
11622 build_int_cst (unsigned_type_node,
11623 node->simdclone->simdlen),
11624 NULL, NULL);
11625 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11626 e = split_block (incr_bb, gsi_stmt (gsi));
11627 basic_block latch_bb = e->dest;
11628 basic_block new_exit_bb = e->dest;
11629 new_exit_bb = split_block (latch_bb, NULL)->dest;
11630 loop->latch = latch_bb;
11632 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
11634 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
11635 /* The successor of incr_bb is already pointing to latch_bb; just
11636 change the flags.
11637 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
11638 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
11640 gimple phi = create_phi_node (iter1, body_bb);
11641 edge preheader_edge = find_edge (entry_bb, body_bb);
11642 edge latch_edge = single_succ_edge (latch_bb);
11643 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
11644 UNKNOWN_LOCATION);
11645 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11647 /* Generate the new return. */
11648 gsi = gsi_last_bb (new_exit_bb);
11649 if (retval
11650 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
11651 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
11652 retval = TREE_OPERAND (retval, 0);
11653 else if (retval)
11655 retval = build1 (VIEW_CONVERT_EXPR,
11656 TREE_TYPE (TREE_TYPE (node->decl)),
11657 retval);
11658 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
11659 false, GSI_CONTINUE_LINKING);
11661 g = gimple_build_return (retval);
11662 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11664 /* Handle aligned clauses by replacing default defs of the aligned
11665 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
11666 lhs. Handle linear by adding PHIs. */
11667 for (unsigned i = 0; i < node->simdclone->nargs; i++)
11668 if (node->simdclone->args[i].alignment
11669 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
11670 && (node->simdclone->args[i].alignment
11671 & (node->simdclone->args[i].alignment - 1)) == 0
11672 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
11673 == POINTER_TYPE)
11675 unsigned int alignment = node->simdclone->args[i].alignment;
11676 tree orig_arg = node->simdclone->args[i].orig_arg;
11677 tree def = ssa_default_def (cfun, orig_arg);
11678 if (def && !has_zero_uses (def))
11680 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
11681 gimple_seq seq = NULL;
11682 bool need_cvt = false;
11683 gimple call
11684 = gimple_build_call (fn, 2, def, size_int (alignment));
11685 g = call;
11686 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
11687 ptr_type_node))
11688 need_cvt = true;
11689 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
11690 gimple_call_set_lhs (g, t);
11691 gimple_seq_add_stmt_without_update (&seq, g);
11692 if (need_cvt)
11694 t = make_ssa_name (orig_arg, NULL);
11695 g = gimple_build_assign_with_ops (NOP_EXPR, t,
11696 gimple_call_lhs (g),
11697 NULL_TREE);
11698 gimple_seq_add_stmt_without_update (&seq, g);
11700 gsi_insert_seq_on_edge_immediate
11701 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
11703 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11704 int freq = compute_call_stmt_bb_frequency (current_function_decl,
11705 entry_bb);
11706 cgraph_create_edge (node, cgraph_get_create_node (fn),
11707 call, entry_bb->count, freq);
11709 imm_use_iterator iter;
11710 use_operand_p use_p;
11711 gimple use_stmt;
11712 tree repl = gimple_get_lhs (g);
11713 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11714 if (is_gimple_debug (use_stmt) || use_stmt == call)
11715 continue;
11716 else
11717 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11718 SET_USE (use_p, repl);
11721 else if (node->simdclone->args[i].arg_type
11722 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11724 tree orig_arg = node->simdclone->args[i].orig_arg;
11725 tree def = ssa_default_def (cfun, orig_arg);
11726 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11727 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
11728 if (def && !has_zero_uses (def))
11730 iter1 = make_ssa_name (orig_arg, NULL);
11731 iter2 = make_ssa_name (orig_arg, NULL);
11732 phi = create_phi_node (iter1, body_bb);
11733 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
11734 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11735 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11736 ? PLUS_EXPR : POINTER_PLUS_EXPR;
11737 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11738 ? TREE_TYPE (orig_arg) : sizetype;
11739 tree addcst
11740 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
11741 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
11742 gsi = gsi_last_bb (incr_bb);
11743 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
11745 imm_use_iterator iter;
11746 use_operand_p use_p;
11747 gimple use_stmt;
11748 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11749 if (use_stmt == phi)
11750 continue;
11751 else
11752 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11753 SET_USE (use_p, iter1);
11757 calculate_dominance_info (CDI_DOMINATORS);
11758 add_loop (loop, loop->header->loop_father);
11759 update_ssa (TODO_update_ssa);
11761 pop_cfun ();
11764 /* If the function in NODE is tagged as an elemental SIMD function,
11765 create the appropriate SIMD clones. */
11767 static void
11768 expand_simd_clones (struct cgraph_node *node)
11770 tree attr = lookup_attribute ("omp declare simd",
11771 DECL_ATTRIBUTES (node->decl));
11772 if (attr == NULL_TREE
11773 || node->global.inlined_to
11774 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
11775 return;
11777 /* Ignore
11778 #pragma omp declare simd
11779 extern int foo ();
11780 in C, there we don't know the argument types at all. */
11781 if (!node->definition
11782 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
11783 return;
11787 /* Start with parsing the "omp declare simd" attribute(s). */
11788 bool inbranch_clause_specified;
11789 struct cgraph_simd_clone *clone_info
11790 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
11791 &inbranch_clause_specified);
11792 if (clone_info == NULL)
11793 continue;
11795 int orig_simdlen = clone_info->simdlen;
11796 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
11797 /* The target can return 0 (no simd clones should be created),
11798 1 (just one ISA of simd clones should be created) or higher
11799 count of ISA variants. In that case, clone_info is initialized
11800 for the first ISA variant. */
11801 int count
11802 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
11803 base_type, 0);
11804 if (count == 0)
11805 continue;
11807 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
11808 also create one inbranch and one !inbranch clone of it. */
11809 for (int i = 0; i < count * 2; i++)
11811 struct cgraph_simd_clone *clone = clone_info;
11812 if (inbranch_clause_specified && (i & 1) != 0)
11813 continue;
11815 if (i != 0)
11817 clone = simd_clone_struct_alloc (clone_info->nargs
11818 + ((i & 1) != 0));
11819 simd_clone_struct_copy (clone, clone_info);
11820 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
11821 and simd_clone_adjust_argument_types did to the first
11822 clone's info. */
11823 clone->nargs -= clone_info->inbranch;
11824 clone->simdlen = orig_simdlen;
11825 /* And call the target hook again to get the right ISA. */
11826 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
11827 base_type,
11828 i / 2);
11829 if ((i & 1) != 0)
11830 clone->inbranch = 1;
11833 /* simd_clone_mangle might fail if such a clone has been created
11834 already. */
11835 tree id = simd_clone_mangle (node, clone);
11836 if (id == NULL_TREE)
11837 continue;
11839 /* Only when we are sure we want to create the clone actually
11840 clone the function (or definitions) or create another
11841 extern FUNCTION_DECL (for prototypes without definitions). */
11842 struct cgraph_node *n = simd_clone_create (node);
11843 if (n == NULL)
11844 continue;
11846 n->simdclone = clone;
11847 clone->origin = node;
11848 clone->next_clone = NULL;
11849 if (node->simd_clones == NULL)
11851 clone->prev_clone = n;
11852 node->simd_clones = n;
11854 else
11856 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
11857 clone->prev_clone->simdclone->next_clone = n;
11858 node->simd_clones->simdclone->prev_clone = n;
11860 change_decl_assembler_name (n->decl, id);
11861 /* And finally adjust the return type, parameters and for
11862 definitions also function body. */
11863 if (node->definition)
11864 simd_clone_adjust (n);
11865 else
11867 simd_clone_adjust_return_type (n);
11868 simd_clone_adjust_argument_types (n);
11872 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
11875 /* Entry point for IPA simd clone creation pass. */
11877 static unsigned int
11878 ipa_omp_simd_clone (void)
11880 struct cgraph_node *node;
11881 FOR_EACH_FUNCTION (node)
11882 expand_simd_clones (node);
11883 return 0;
11886 namespace {
11888 const pass_data pass_data_omp_simd_clone =
11890 SIMPLE_IPA_PASS, /* type */
11891 "simdclone", /* name */
11892 OPTGROUP_NONE, /* optinfo_flags */
11893 true, /* has_execute */
11894 TV_NONE, /* tv_id */
11895 ( PROP_ssa | PROP_cfg ), /* properties_required */
11896 0, /* properties_provided */
11897 0, /* properties_destroyed */
11898 0, /* todo_flags_start */
11899 0, /* todo_flags_finish */
11902 class pass_omp_simd_clone : public simple_ipa_opt_pass
11904 public:
11905 pass_omp_simd_clone(gcc::context *ctxt)
11906 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
11909 /* opt_pass methods: */
11910 virtual bool gate (function *);
11911 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
11914 bool
11915 pass_omp_simd_clone::gate (function *)
11917 return ((flag_openmp || flag_openmp_simd
11918 || flag_cilkplus
11919 || (in_lto_p && !flag_wpa))
11920 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
11923 } // anon namespace
11925 simple_ipa_opt_pass *
11926 make_pass_omp_simd_clone (gcc::context *ctxt)
11928 return new pass_omp_simd_clone (ctxt);
11931 #include "gt-omp-low.h"