Sync with upstream 4.9 branch
[official-gcc.git] / embedded-4_9-branch / gcc / omp-low.c
blobf77df897679ce582143b3bf33d4c698859834827
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;
207 static vec<omp_context *> taskreg_contexts;
209 static void scan_omp (gimple_seq *, omp_context *);
210 static tree scan_omp_1_op (tree *, int *, void *);
212 #define WALK_SUBSTMTS \
213 case GIMPLE_BIND: \
214 case GIMPLE_TRY: \
215 case GIMPLE_CATCH: \
216 case GIMPLE_EH_FILTER: \
217 case GIMPLE_TRANSACTION: \
218 /* The sub-statements for these should be walked. */ \
219 *handled_ops_p = false; \
220 break;
222 /* Convenience function for calling scan_omp_1_op on tree operands. */
224 static inline tree
225 scan_omp_op (tree *tp, omp_context *ctx)
227 struct walk_stmt_info wi;
229 memset (&wi, 0, sizeof (wi));
230 wi.info = ctx;
231 wi.want_locations = true;
233 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
236 static void lower_omp (gimple_seq *, omp_context *);
237 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
238 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
240 /* Find an OpenMP clause of type KIND within CLAUSES. */
242 tree
243 find_omp_clause (tree clauses, enum omp_clause_code kind)
245 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
246 if (OMP_CLAUSE_CODE (clauses) == kind)
247 return clauses;
249 return NULL_TREE;
252 /* Return true if CTX is for an omp parallel. */
254 static inline bool
255 is_parallel_ctx (omp_context *ctx)
257 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
261 /* Return true if CTX is for an omp task. */
263 static inline bool
264 is_task_ctx (omp_context *ctx)
266 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
270 /* Return true if CTX is for an omp parallel or omp task. */
272 static inline bool
273 is_taskreg_ctx (omp_context *ctx)
275 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
276 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
280 /* Return true if REGION is a combined parallel+workshare region. */
282 static inline bool
283 is_combined_parallel (struct omp_region *region)
285 return region->is_combined_parallel;
289 /* Extract the header elements of parallel loop FOR_STMT and store
290 them into *FD. */
292 static void
293 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
294 struct omp_for_data_loop *loops)
296 tree t, var, *collapse_iter, *collapse_count;
297 tree count = NULL_TREE, iter_type = long_integer_type_node;
298 struct omp_for_data_loop *loop;
299 int i;
300 struct omp_for_data_loop dummy_loop;
301 location_t loc = gimple_location (for_stmt);
302 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_KIND_SIMD;
303 bool distribute = gimple_omp_for_kind (for_stmt)
304 == GF_OMP_FOR_KIND_DISTRIBUTE;
306 fd->for_stmt = for_stmt;
307 fd->pre = NULL;
308 fd->collapse = gimple_omp_for_collapse (for_stmt);
309 if (fd->collapse > 1)
310 fd->loops = loops;
311 else
312 fd->loops = &fd->loop;
314 fd->have_nowait = distribute || simd;
315 fd->have_ordered = false;
316 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
317 fd->chunk_size = NULL_TREE;
318 collapse_iter = NULL;
319 collapse_count = NULL;
321 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
322 switch (OMP_CLAUSE_CODE (t))
324 case OMP_CLAUSE_NOWAIT:
325 fd->have_nowait = true;
326 break;
327 case OMP_CLAUSE_ORDERED:
328 fd->have_ordered = true;
329 break;
330 case OMP_CLAUSE_SCHEDULE:
331 gcc_assert (!distribute);
332 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
333 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
334 break;
335 case OMP_CLAUSE_DIST_SCHEDULE:
336 gcc_assert (distribute);
337 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
338 break;
339 case OMP_CLAUSE_COLLAPSE:
340 if (fd->collapse > 1)
342 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
343 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
345 default:
346 break;
349 /* FIXME: for now map schedule(auto) to schedule(static).
350 There should be analysis to determine whether all iterations
351 are approximately the same amount of work (then schedule(static)
352 is best) or if it varies (then schedule(dynamic,N) is better). */
353 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
355 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
356 gcc_assert (fd->chunk_size == NULL);
358 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
359 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
360 gcc_assert (fd->chunk_size == NULL);
361 else if (fd->chunk_size == NULL)
363 /* We only need to compute a default chunk size for ordered
364 static loops and dynamic loops. */
365 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
366 || fd->have_ordered)
367 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
368 ? integer_zero_node : integer_one_node;
371 for (i = 0; i < fd->collapse; i++)
373 if (fd->collapse == 1)
374 loop = &fd->loop;
375 else if (loops != NULL)
376 loop = loops + i;
377 else
378 loop = &dummy_loop;
380 loop->v = gimple_omp_for_index (for_stmt, i);
381 gcc_assert (SSA_VAR_P (loop->v));
382 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
383 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
384 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
385 loop->n1 = gimple_omp_for_initial (for_stmt, i);
387 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
388 loop->n2 = gimple_omp_for_final (for_stmt, i);
389 switch (loop->cond_code)
391 case LT_EXPR:
392 case GT_EXPR:
393 break;
394 case NE_EXPR:
395 gcc_assert (gimple_omp_for_kind (for_stmt)
396 == GF_OMP_FOR_KIND_CILKSIMD);
397 break;
398 case LE_EXPR:
399 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
400 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
401 else
402 loop->n2 = fold_build2_loc (loc,
403 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
404 build_int_cst (TREE_TYPE (loop->n2), 1));
405 loop->cond_code = LT_EXPR;
406 break;
407 case GE_EXPR:
408 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
409 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
410 else
411 loop->n2 = fold_build2_loc (loc,
412 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
413 build_int_cst (TREE_TYPE (loop->n2), 1));
414 loop->cond_code = GT_EXPR;
415 break;
416 default:
417 gcc_unreachable ();
420 t = gimple_omp_for_incr (for_stmt, i);
421 gcc_assert (TREE_OPERAND (t, 0) == var);
422 switch (TREE_CODE (t))
424 case PLUS_EXPR:
425 loop->step = TREE_OPERAND (t, 1);
426 break;
427 case POINTER_PLUS_EXPR:
428 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
429 break;
430 case MINUS_EXPR:
431 loop->step = TREE_OPERAND (t, 1);
432 loop->step = fold_build1_loc (loc,
433 NEGATE_EXPR, TREE_TYPE (loop->step),
434 loop->step);
435 break;
436 default:
437 gcc_unreachable ();
440 if (simd
441 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
442 && !fd->have_ordered))
444 if (fd->collapse == 1)
445 iter_type = TREE_TYPE (loop->v);
446 else if (i == 0
447 || TYPE_PRECISION (iter_type)
448 < TYPE_PRECISION (TREE_TYPE (loop->v)))
449 iter_type
450 = build_nonstandard_integer_type
451 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
453 else if (iter_type != long_long_unsigned_type_node)
455 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
456 iter_type = long_long_unsigned_type_node;
457 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
458 && TYPE_PRECISION (TREE_TYPE (loop->v))
459 >= TYPE_PRECISION (iter_type))
461 tree n;
463 if (loop->cond_code == LT_EXPR)
464 n = fold_build2_loc (loc,
465 PLUS_EXPR, TREE_TYPE (loop->v),
466 loop->n2, loop->step);
467 else
468 n = loop->n1;
469 if (TREE_CODE (n) != INTEGER_CST
470 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
471 iter_type = long_long_unsigned_type_node;
473 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
474 > TYPE_PRECISION (iter_type))
476 tree n1, n2;
478 if (loop->cond_code == LT_EXPR)
480 n1 = loop->n1;
481 n2 = fold_build2_loc (loc,
482 PLUS_EXPR, TREE_TYPE (loop->v),
483 loop->n2, loop->step);
485 else
487 n1 = fold_build2_loc (loc,
488 MINUS_EXPR, TREE_TYPE (loop->v),
489 loop->n2, loop->step);
490 n2 = loop->n1;
492 if (TREE_CODE (n1) != INTEGER_CST
493 || TREE_CODE (n2) != INTEGER_CST
494 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
495 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
496 iter_type = long_long_unsigned_type_node;
500 if (collapse_count && *collapse_count == NULL)
502 t = fold_binary (loop->cond_code, boolean_type_node,
503 fold_convert (TREE_TYPE (loop->v), loop->n1),
504 fold_convert (TREE_TYPE (loop->v), loop->n2));
505 if (t && integer_zerop (t))
506 count = build_zero_cst (long_long_unsigned_type_node);
507 else if ((i == 0 || count != NULL_TREE)
508 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
509 && TREE_CONSTANT (loop->n1)
510 && TREE_CONSTANT (loop->n2)
511 && TREE_CODE (loop->step) == INTEGER_CST)
513 tree itype = TREE_TYPE (loop->v);
515 if (POINTER_TYPE_P (itype))
516 itype = signed_type_for (itype);
517 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
518 t = fold_build2_loc (loc,
519 PLUS_EXPR, itype,
520 fold_convert_loc (loc, itype, loop->step), t);
521 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
522 fold_convert_loc (loc, itype, loop->n2));
523 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
524 fold_convert_loc (loc, itype, loop->n1));
525 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
526 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
527 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
528 fold_build1_loc (loc, NEGATE_EXPR, itype,
529 fold_convert_loc (loc, itype,
530 loop->step)));
531 else
532 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
533 fold_convert_loc (loc, itype, loop->step));
534 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
535 if (count != NULL_TREE)
536 count = fold_build2_loc (loc,
537 MULT_EXPR, long_long_unsigned_type_node,
538 count, t);
539 else
540 count = t;
541 if (TREE_CODE (count) != INTEGER_CST)
542 count = NULL_TREE;
544 else if (count && !integer_zerop (count))
545 count = NULL_TREE;
549 if (count
550 && !simd
551 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
552 || fd->have_ordered))
554 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
555 iter_type = long_long_unsigned_type_node;
556 else
557 iter_type = long_integer_type_node;
559 else if (collapse_iter && *collapse_iter != NULL)
560 iter_type = TREE_TYPE (*collapse_iter);
561 fd->iter_type = iter_type;
562 if (collapse_iter && *collapse_iter == NULL)
563 *collapse_iter = create_tmp_var (iter_type, ".iter");
564 if (collapse_count && *collapse_count == NULL)
566 if (count)
567 *collapse_count = fold_convert_loc (loc, iter_type, count);
568 else
569 *collapse_count = create_tmp_var (iter_type, ".count");
572 if (fd->collapse > 1)
574 fd->loop.v = *collapse_iter;
575 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
576 fd->loop.n2 = *collapse_count;
577 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
578 fd->loop.cond_code = LT_EXPR;
583 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
584 is the immediate dominator of PAR_ENTRY_BB, return true if there
585 are no data dependencies that would prevent expanding the parallel
586 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
588 When expanding a combined parallel+workshare region, the call to
589 the child function may need additional arguments in the case of
590 GIMPLE_OMP_FOR regions. In some cases, these arguments are
591 computed out of variables passed in from the parent to the child
592 via 'struct .omp_data_s'. For instance:
594 #pragma omp parallel for schedule (guided, i * 4)
595 for (j ...)
597 Is lowered into:
599 # BLOCK 2 (PAR_ENTRY_BB)
600 .omp_data_o.i = i;
601 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
603 # BLOCK 3 (WS_ENTRY_BB)
604 .omp_data_i = &.omp_data_o;
605 D.1667 = .omp_data_i->i;
606 D.1598 = D.1667 * 4;
607 #pragma omp for schedule (guided, D.1598)
609 When we outline the parallel region, the call to the child function
610 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
611 that value is computed *after* the call site. So, in principle we
612 cannot do the transformation.
614 To see whether the code in WS_ENTRY_BB blocks the combined
615 parallel+workshare call, we collect all the variables used in the
616 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
617 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
618 call.
620 FIXME. If we had the SSA form built at this point, we could merely
621 hoist the code in block 3 into block 2 and be done with it. But at
622 this point we don't have dataflow information and though we could
623 hack something up here, it is really not worth the aggravation. */
625 static bool
626 workshare_safe_to_combine_p (basic_block ws_entry_bb)
628 struct omp_for_data fd;
629 gimple ws_stmt = last_stmt (ws_entry_bb);
631 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
632 return true;
634 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
636 extract_omp_for_data (ws_stmt, &fd, NULL);
638 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
639 return false;
640 if (fd.iter_type != long_integer_type_node)
641 return false;
643 /* FIXME. We give up too easily here. If any of these arguments
644 are not constants, they will likely involve variables that have
645 been mapped into fields of .omp_data_s for sharing with the child
646 function. With appropriate data flow, it would be possible to
647 see through this. */
648 if (!is_gimple_min_invariant (fd.loop.n1)
649 || !is_gimple_min_invariant (fd.loop.n2)
650 || !is_gimple_min_invariant (fd.loop.step)
651 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
652 return false;
654 return true;
658 /* Collect additional arguments needed to emit a combined
659 parallel+workshare call. WS_STMT is the workshare directive being
660 expanded. */
662 static vec<tree, va_gc> *
663 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
665 tree t;
666 location_t loc = gimple_location (ws_stmt);
667 vec<tree, va_gc> *ws_args;
669 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
671 struct omp_for_data fd;
672 tree n1, n2;
674 extract_omp_for_data (ws_stmt, &fd, NULL);
675 n1 = fd.loop.n1;
676 n2 = fd.loop.n2;
678 if (gimple_omp_for_combined_into_p (ws_stmt))
680 tree innerc
681 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
682 OMP_CLAUSE__LOOPTEMP_);
683 gcc_assert (innerc);
684 n1 = OMP_CLAUSE_DECL (innerc);
685 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
686 OMP_CLAUSE__LOOPTEMP_);
687 gcc_assert (innerc);
688 n2 = OMP_CLAUSE_DECL (innerc);
691 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
693 t = fold_convert_loc (loc, long_integer_type_node, n1);
694 ws_args->quick_push (t);
696 t = fold_convert_loc (loc, long_integer_type_node, n2);
697 ws_args->quick_push (t);
699 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
700 ws_args->quick_push (t);
702 if (fd.chunk_size)
704 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
705 ws_args->quick_push (t);
708 return ws_args;
710 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
712 /* Number of sections is equal to the number of edges from the
713 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
714 the exit of the sections region. */
715 basic_block bb = single_succ (gimple_bb (ws_stmt));
716 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
717 vec_alloc (ws_args, 1);
718 ws_args->quick_push (t);
719 return ws_args;
722 gcc_unreachable ();
726 /* Discover whether REGION is a combined parallel+workshare region. */
728 static void
729 determine_parallel_type (struct omp_region *region)
731 basic_block par_entry_bb, par_exit_bb;
732 basic_block ws_entry_bb, ws_exit_bb;
734 if (region == NULL || region->inner == NULL
735 || region->exit == NULL || region->inner->exit == NULL
736 || region->inner->cont == NULL)
737 return;
739 /* We only support parallel+for and parallel+sections. */
740 if (region->type != GIMPLE_OMP_PARALLEL
741 || (region->inner->type != GIMPLE_OMP_FOR
742 && region->inner->type != GIMPLE_OMP_SECTIONS))
743 return;
745 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
746 WS_EXIT_BB -> PAR_EXIT_BB. */
747 par_entry_bb = region->entry;
748 par_exit_bb = region->exit;
749 ws_entry_bb = region->inner->entry;
750 ws_exit_bb = region->inner->exit;
752 if (single_succ (par_entry_bb) == ws_entry_bb
753 && single_succ (ws_exit_bb) == par_exit_bb
754 && workshare_safe_to_combine_p (ws_entry_bb)
755 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
756 || (last_and_only_stmt (ws_entry_bb)
757 && last_and_only_stmt (par_exit_bb))))
759 gimple par_stmt = last_stmt (par_entry_bb);
760 gimple ws_stmt = last_stmt (ws_entry_bb);
762 if (region->inner->type == GIMPLE_OMP_FOR)
764 /* If this is a combined parallel loop, we need to determine
765 whether or not to use the combined library calls. There
766 are two cases where we do not apply the transformation:
767 static loops and any kind of ordered loop. In the first
768 case, we already open code the loop so there is no need
769 to do anything else. In the latter case, the combined
770 parallel loop call would still need extra synchronization
771 to implement ordered semantics, so there would not be any
772 gain in using the combined call. */
773 tree clauses = gimple_omp_for_clauses (ws_stmt);
774 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
775 if (c == NULL
776 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
777 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
779 region->is_combined_parallel = false;
780 region->inner->is_combined_parallel = false;
781 return;
785 region->is_combined_parallel = true;
786 region->inner->is_combined_parallel = true;
787 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
792 /* Return true if EXPR is variable sized. */
794 static inline bool
795 is_variable_sized (const_tree expr)
797 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
800 /* Return true if DECL is a reference type. */
802 static inline bool
803 is_reference (tree decl)
805 return lang_hooks.decls.omp_privatize_by_reference (decl);
808 /* Lookup variables in the decl or field splay trees. The "maybe" form
809 allows for the variable form to not have been entered, otherwise we
810 assert that the variable must have been entered. */
812 static inline tree
813 lookup_decl (tree var, omp_context *ctx)
815 tree *n;
816 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
817 return *n;
820 static inline tree
821 maybe_lookup_decl (const_tree var, omp_context *ctx)
823 tree *n;
824 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
825 return n ? *n : NULL_TREE;
828 static inline tree
829 lookup_field (tree var, omp_context *ctx)
831 splay_tree_node n;
832 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
833 return (tree) n->value;
836 static inline tree
837 lookup_sfield (tree var, omp_context *ctx)
839 splay_tree_node n;
840 n = splay_tree_lookup (ctx->sfield_map
841 ? ctx->sfield_map : ctx->field_map,
842 (splay_tree_key) var);
843 return (tree) n->value;
846 static inline tree
847 maybe_lookup_field (tree var, omp_context *ctx)
849 splay_tree_node n;
850 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
851 return n ? (tree) n->value : NULL_TREE;
854 /* Return true if DECL should be copied by pointer. SHARED_CTX is
855 the parallel context if DECL is to be shared. */
857 static bool
858 use_pointer_for_field (tree decl, omp_context *shared_ctx)
860 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
861 return true;
863 /* We can only use copy-in/copy-out semantics for shared variables
864 when we know the value is not accessible from an outer scope. */
865 if (shared_ctx)
867 /* ??? Trivially accessible from anywhere. But why would we even
868 be passing an address in this case? Should we simply assert
869 this to be false, or should we have a cleanup pass that removes
870 these from the list of mappings? */
871 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
872 return true;
874 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
875 without analyzing the expression whether or not its location
876 is accessible to anyone else. In the case of nested parallel
877 regions it certainly may be. */
878 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
879 return true;
881 /* Do not use copy-in/copy-out for variables that have their
882 address taken. */
883 if (TREE_ADDRESSABLE (decl))
884 return true;
886 /* lower_send_shared_vars only uses copy-in, but not copy-out
887 for these. */
888 if (TREE_READONLY (decl)
889 || ((TREE_CODE (decl) == RESULT_DECL
890 || TREE_CODE (decl) == PARM_DECL)
891 && DECL_BY_REFERENCE (decl)))
892 return false;
894 /* Disallow copy-in/out in nested parallel if
895 decl is shared in outer parallel, otherwise
896 each thread could store the shared variable
897 in its own copy-in location, making the
898 variable no longer really shared. */
899 if (shared_ctx->is_nested)
901 omp_context *up;
903 for (up = shared_ctx->outer; up; up = up->outer)
904 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
905 break;
907 if (up)
909 tree c;
911 for (c = gimple_omp_taskreg_clauses (up->stmt);
912 c; c = OMP_CLAUSE_CHAIN (c))
913 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
914 && OMP_CLAUSE_DECL (c) == decl)
915 break;
917 if (c)
918 goto maybe_mark_addressable_and_ret;
922 /* For tasks avoid using copy-in/out. As tasks can be
923 deferred or executed in different thread, when GOMP_task
924 returns, the task hasn't necessarily terminated. */
925 if (is_task_ctx (shared_ctx))
927 tree outer;
928 maybe_mark_addressable_and_ret:
929 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
930 if (is_gimple_reg (outer))
932 /* Taking address of OUTER in lower_send_shared_vars
933 might need regimplification of everything that uses the
934 variable. */
935 if (!task_shared_vars)
936 task_shared_vars = BITMAP_ALLOC (NULL);
937 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
938 TREE_ADDRESSABLE (outer) = 1;
940 return true;
944 return false;
947 /* Construct a new automatic decl similar to VAR. */
949 static tree
950 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
952 tree copy = copy_var_decl (var, name, type);
954 DECL_CONTEXT (copy) = current_function_decl;
955 DECL_CHAIN (copy) = ctx->block_vars;
956 ctx->block_vars = copy;
958 return copy;
961 static tree
962 omp_copy_decl_1 (tree var, omp_context *ctx)
964 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
967 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
968 as appropriate. */
969 static tree
970 omp_build_component_ref (tree obj, tree field)
972 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
973 if (TREE_THIS_VOLATILE (field))
974 TREE_THIS_VOLATILE (ret) |= 1;
975 if (TREE_READONLY (field))
976 TREE_READONLY (ret) |= 1;
977 return ret;
980 /* Build tree nodes to access the field for VAR on the receiver side. */
982 static tree
983 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
985 tree x, field = lookup_field (var, ctx);
987 /* If the receiver record type was remapped in the child function,
988 remap the field into the new record type. */
989 x = maybe_lookup_field (field, ctx);
990 if (x != NULL)
991 field = x;
993 x = build_simple_mem_ref (ctx->receiver_decl);
994 x = omp_build_component_ref (x, field);
995 if (by_ref)
996 x = build_simple_mem_ref (x);
998 return x;
1001 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1002 of a parallel, this is a component reference; for workshare constructs
1003 this is some variable. */
1005 static tree
1006 build_outer_var_ref (tree var, omp_context *ctx)
1008 tree x;
1010 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1011 x = var;
1012 else if (is_variable_sized (var))
1014 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1015 x = build_outer_var_ref (x, ctx);
1016 x = build_simple_mem_ref (x);
1018 else if (is_taskreg_ctx (ctx))
1020 bool by_ref = use_pointer_for_field (var, NULL);
1021 x = build_receiver_ref (var, by_ref, ctx);
1023 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1024 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
1026 /* #pragma omp simd isn't a worksharing construct, and can reference even
1027 private vars in its linear etc. clauses. */
1028 x = NULL_TREE;
1029 if (ctx->outer && is_taskreg_ctx (ctx))
1030 x = lookup_decl (var, ctx->outer);
1031 else if (ctx->outer)
1032 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1033 if (x == NULL_TREE)
1034 x = var;
1036 else if (ctx->outer)
1037 x = lookup_decl (var, ctx->outer);
1038 else if (is_reference (var))
1039 /* This can happen with orphaned constructs. If var is reference, it is
1040 possible it is shared and as such valid. */
1041 x = var;
1042 else
1043 gcc_unreachable ();
1045 if (is_reference (var))
1046 x = build_simple_mem_ref (x);
1048 return x;
1051 /* Build tree nodes to access the field for VAR on the sender side. */
1053 static tree
1054 build_sender_ref (tree var, omp_context *ctx)
1056 tree field = lookup_sfield (var, ctx);
1057 return omp_build_component_ref (ctx->sender_decl, field);
1060 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1062 static void
1063 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1065 tree field, type, sfield = NULL_TREE;
1067 gcc_assert ((mask & 1) == 0
1068 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1069 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1070 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1072 type = TREE_TYPE (var);
1073 if (mask & 4)
1075 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1076 type = build_pointer_type (build_pointer_type (type));
1078 else if (by_ref)
1079 type = build_pointer_type (type);
1080 else if ((mask & 3) == 1 && is_reference (var))
1081 type = TREE_TYPE (type);
1083 field = build_decl (DECL_SOURCE_LOCATION (var),
1084 FIELD_DECL, DECL_NAME (var), type);
1086 /* Remember what variable this field was created for. This does have a
1087 side effect of making dwarf2out ignore this member, so for helpful
1088 debugging we clear it later in delete_omp_context. */
1089 DECL_ABSTRACT_ORIGIN (field) = var;
1090 if (type == TREE_TYPE (var))
1092 DECL_ALIGN (field) = DECL_ALIGN (var);
1093 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1094 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1096 else
1097 DECL_ALIGN (field) = TYPE_ALIGN (type);
1099 if ((mask & 3) == 3)
1101 insert_field_into_struct (ctx->record_type, field);
1102 if (ctx->srecord_type)
1104 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1105 FIELD_DECL, DECL_NAME (var), type);
1106 DECL_ABSTRACT_ORIGIN (sfield) = var;
1107 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1108 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1109 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1110 insert_field_into_struct (ctx->srecord_type, sfield);
1113 else
1115 if (ctx->srecord_type == NULL_TREE)
1117 tree t;
1119 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1120 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1121 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1123 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1124 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1125 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1126 insert_field_into_struct (ctx->srecord_type, sfield);
1127 splay_tree_insert (ctx->sfield_map,
1128 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1129 (splay_tree_value) sfield);
1132 sfield = field;
1133 insert_field_into_struct ((mask & 1) ? ctx->record_type
1134 : ctx->srecord_type, field);
1137 if (mask & 1)
1138 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1139 (splay_tree_value) field);
1140 if ((mask & 2) && ctx->sfield_map)
1141 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1142 (splay_tree_value) sfield);
1145 static tree
1146 install_var_local (tree var, omp_context *ctx)
1148 tree new_var = omp_copy_decl_1 (var, ctx);
1149 insert_decl_map (&ctx->cb, var, new_var);
1150 return new_var;
1153 /* Adjust the replacement for DECL in CTX for the new context. This means
1154 copying the DECL_VALUE_EXPR, and fixing up the type. */
1156 static void
1157 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1159 tree new_decl, size;
1161 new_decl = lookup_decl (decl, ctx);
1163 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1165 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1166 && DECL_HAS_VALUE_EXPR_P (decl))
1168 tree ve = DECL_VALUE_EXPR (decl);
1169 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1170 SET_DECL_VALUE_EXPR (new_decl, ve);
1171 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1174 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1176 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1177 if (size == error_mark_node)
1178 size = TYPE_SIZE (TREE_TYPE (new_decl));
1179 DECL_SIZE (new_decl) = size;
1181 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1182 if (size == error_mark_node)
1183 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1184 DECL_SIZE_UNIT (new_decl) = size;
1188 /* The callback for remap_decl. Search all containing contexts for a
1189 mapping of the variable; this avoids having to duplicate the splay
1190 tree ahead of time. We know a mapping doesn't already exist in the
1191 given context. Create new mappings to implement default semantics. */
1193 static tree
1194 omp_copy_decl (tree var, copy_body_data *cb)
1196 omp_context *ctx = (omp_context *) cb;
1197 tree new_var;
1199 if (TREE_CODE (var) == LABEL_DECL)
1201 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1202 DECL_CONTEXT (new_var) = current_function_decl;
1203 insert_decl_map (&ctx->cb, var, new_var);
1204 return new_var;
1207 while (!is_taskreg_ctx (ctx))
1209 ctx = ctx->outer;
1210 if (ctx == NULL)
1211 return var;
1212 new_var = maybe_lookup_decl (var, ctx);
1213 if (new_var)
1214 return new_var;
1217 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1218 return var;
1220 return error_mark_node;
1224 /* Debugging dumps for parallel regions. */
1225 void dump_omp_region (FILE *, struct omp_region *, int);
1226 void debug_omp_region (struct omp_region *);
1227 void debug_all_omp_regions (void);
1229 /* Dump the parallel region tree rooted at REGION. */
1231 void
1232 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1234 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1235 gimple_code_name[region->type]);
1237 if (region->inner)
1238 dump_omp_region (file, region->inner, indent + 4);
1240 if (region->cont)
1242 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1243 region->cont->index);
1246 if (region->exit)
1247 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1248 region->exit->index);
1249 else
1250 fprintf (file, "%*s[no exit marker]\n", indent, "");
1252 if (region->next)
1253 dump_omp_region (file, region->next, indent);
1256 DEBUG_FUNCTION void
1257 debug_omp_region (struct omp_region *region)
1259 dump_omp_region (stderr, region, 0);
1262 DEBUG_FUNCTION void
1263 debug_all_omp_regions (void)
1265 dump_omp_region (stderr, root_omp_region, 0);
1269 /* Create a new parallel region starting at STMT inside region PARENT. */
1271 static struct omp_region *
1272 new_omp_region (basic_block bb, enum gimple_code type,
1273 struct omp_region *parent)
1275 struct omp_region *region = XCNEW (struct omp_region);
1277 region->outer = parent;
1278 region->entry = bb;
1279 region->type = type;
1281 if (parent)
1283 /* This is a nested region. Add it to the list of inner
1284 regions in PARENT. */
1285 region->next = parent->inner;
1286 parent->inner = region;
1288 else
1290 /* This is a toplevel region. Add it to the list of toplevel
1291 regions in ROOT_OMP_REGION. */
1292 region->next = root_omp_region;
1293 root_omp_region = region;
1296 return region;
1299 /* Release the memory associated with the region tree rooted at REGION. */
1301 static void
1302 free_omp_region_1 (struct omp_region *region)
1304 struct omp_region *i, *n;
1306 for (i = region->inner; i ; i = n)
1308 n = i->next;
1309 free_omp_region_1 (i);
1312 free (region);
1315 /* Release the memory for the entire omp region tree. */
1317 void
1318 free_omp_regions (void)
1320 struct omp_region *r, *n;
1321 for (r = root_omp_region; r ; r = n)
1323 n = r->next;
1324 free_omp_region_1 (r);
1326 root_omp_region = NULL;
1330 /* Create a new context, with OUTER_CTX being the surrounding context. */
1332 static omp_context *
1333 new_omp_context (gimple stmt, omp_context *outer_ctx)
1335 omp_context *ctx = XCNEW (omp_context);
1337 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1338 (splay_tree_value) ctx);
1339 ctx->stmt = stmt;
1341 if (outer_ctx)
1343 ctx->outer = outer_ctx;
1344 ctx->cb = outer_ctx->cb;
1345 ctx->cb.block = NULL;
1346 ctx->depth = outer_ctx->depth + 1;
1348 else
1350 ctx->cb.src_fn = current_function_decl;
1351 ctx->cb.dst_fn = current_function_decl;
1352 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1353 gcc_checking_assert (ctx->cb.src_node);
1354 ctx->cb.dst_node = ctx->cb.src_node;
1355 ctx->cb.src_cfun = cfun;
1356 ctx->cb.copy_decl = omp_copy_decl;
1357 ctx->cb.eh_lp_nr = 0;
1358 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1359 ctx->depth = 1;
1362 ctx->cb.decl_map = pointer_map_create ();
1364 return ctx;
1367 static gimple_seq maybe_catch_exception (gimple_seq);
1369 /* Finalize task copyfn. */
1371 static void
1372 finalize_task_copyfn (gimple task_stmt)
1374 struct function *child_cfun;
1375 tree child_fn;
1376 gimple_seq seq = NULL, new_seq;
1377 gimple bind;
1379 child_fn = gimple_omp_task_copy_fn (task_stmt);
1380 if (child_fn == NULL_TREE)
1381 return;
1383 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1384 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1386 push_cfun (child_cfun);
1387 bind = gimplify_body (child_fn, false);
1388 gimple_seq_add_stmt (&seq, bind);
1389 new_seq = maybe_catch_exception (seq);
1390 if (new_seq != seq)
1392 bind = gimple_build_bind (NULL, new_seq, NULL);
1393 seq = NULL;
1394 gimple_seq_add_stmt (&seq, bind);
1396 gimple_set_body (child_fn, seq);
1397 pop_cfun ();
1399 /* Inform the callgraph about the new function. */
1400 cgraph_add_new_function (child_fn, false);
1403 /* Destroy a omp_context data structures. Called through the splay tree
1404 value delete callback. */
1406 static void
1407 delete_omp_context (splay_tree_value value)
1409 omp_context *ctx = (omp_context *) value;
1411 pointer_map_destroy (ctx->cb.decl_map);
1413 if (ctx->field_map)
1414 splay_tree_delete (ctx->field_map);
1415 if (ctx->sfield_map)
1416 splay_tree_delete (ctx->sfield_map);
1418 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1419 it produces corrupt debug information. */
1420 if (ctx->record_type)
1422 tree t;
1423 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1424 DECL_ABSTRACT_ORIGIN (t) = NULL;
1426 if (ctx->srecord_type)
1428 tree t;
1429 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1430 DECL_ABSTRACT_ORIGIN (t) = NULL;
1433 if (is_task_ctx (ctx))
1434 finalize_task_copyfn (ctx->stmt);
1436 XDELETE (ctx);
1439 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1440 context. */
1442 static void
1443 fixup_child_record_type (omp_context *ctx)
1445 tree f, type = ctx->record_type;
1447 /* ??? It isn't sufficient to just call remap_type here, because
1448 variably_modified_type_p doesn't work the way we expect for
1449 record types. Testing each field for whether it needs remapping
1450 and creating a new record by hand works, however. */
1451 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1452 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1453 break;
1454 if (f)
1456 tree name, new_fields = NULL;
1458 type = lang_hooks.types.make_type (RECORD_TYPE);
1459 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1460 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1461 TYPE_DECL, name, type);
1462 TYPE_NAME (type) = name;
1464 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1466 tree new_f = copy_node (f);
1467 DECL_CONTEXT (new_f) = type;
1468 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1469 DECL_CHAIN (new_f) = new_fields;
1470 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1471 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1472 &ctx->cb, NULL);
1473 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1474 &ctx->cb, NULL);
1475 new_fields = new_f;
1477 /* Arrange to be able to look up the receiver field
1478 given the sender field. */
1479 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1480 (splay_tree_value) new_f);
1482 TYPE_FIELDS (type) = nreverse (new_fields);
1483 layout_type (type);
1486 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1489 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1490 specified by CLAUSES. */
1492 static void
1493 scan_sharing_clauses (tree clauses, omp_context *ctx)
1495 tree c, decl;
1496 bool scan_array_reductions = false;
1498 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1500 bool by_ref;
1502 switch (OMP_CLAUSE_CODE (c))
1504 case OMP_CLAUSE_PRIVATE:
1505 decl = OMP_CLAUSE_DECL (c);
1506 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1507 goto do_private;
1508 else if (!is_variable_sized (decl))
1509 install_var_local (decl, ctx);
1510 break;
1512 case OMP_CLAUSE_SHARED:
1513 decl = OMP_CLAUSE_DECL (c);
1514 /* Ignore shared directives in teams construct. */
1515 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1517 /* Global variables don't need to be copied,
1518 the receiver side will use them directly. */
1519 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1520 if (is_global_var (odecl))
1521 break;
1522 insert_decl_map (&ctx->cb, decl, odecl);
1523 break;
1525 gcc_assert (is_taskreg_ctx (ctx));
1526 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1527 || !is_variable_sized (decl));
1528 /* Global variables don't need to be copied,
1529 the receiver side will use them directly. */
1530 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1531 break;
1532 by_ref = use_pointer_for_field (decl, ctx);
1533 if (! TREE_READONLY (decl)
1534 || TREE_ADDRESSABLE (decl)
1535 || by_ref
1536 || is_reference (decl))
1538 install_var_field (decl, by_ref, 3, ctx);
1539 install_var_local (decl, ctx);
1540 break;
1542 /* We don't need to copy const scalar vars back. */
1543 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1544 goto do_private;
1546 case OMP_CLAUSE_LASTPRIVATE:
1547 /* Let the corresponding firstprivate clause create
1548 the variable. */
1549 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1550 break;
1551 /* FALLTHRU */
1553 case OMP_CLAUSE_FIRSTPRIVATE:
1554 case OMP_CLAUSE_REDUCTION:
1555 case OMP_CLAUSE_LINEAR:
1556 decl = OMP_CLAUSE_DECL (c);
1557 do_private:
1558 if (is_variable_sized (decl))
1560 if (is_task_ctx (ctx))
1561 install_var_field (decl, false, 1, ctx);
1562 break;
1564 else if (is_taskreg_ctx (ctx))
1566 bool global
1567 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1568 by_ref = use_pointer_for_field (decl, NULL);
1570 if (is_task_ctx (ctx)
1571 && (global || by_ref || is_reference (decl)))
1573 install_var_field (decl, false, 1, ctx);
1574 if (!global)
1575 install_var_field (decl, by_ref, 2, ctx);
1577 else if (!global)
1578 install_var_field (decl, by_ref, 3, ctx);
1580 install_var_local (decl, ctx);
1581 break;
1583 case OMP_CLAUSE__LOOPTEMP_:
1584 gcc_assert (is_parallel_ctx (ctx));
1585 decl = OMP_CLAUSE_DECL (c);
1586 install_var_field (decl, false, 3, ctx);
1587 install_var_local (decl, ctx);
1588 break;
1590 case OMP_CLAUSE_COPYPRIVATE:
1591 case OMP_CLAUSE_COPYIN:
1592 decl = OMP_CLAUSE_DECL (c);
1593 by_ref = use_pointer_for_field (decl, NULL);
1594 install_var_field (decl, by_ref, 3, ctx);
1595 break;
1597 case OMP_CLAUSE_DEFAULT:
1598 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1599 break;
1601 case OMP_CLAUSE_FINAL:
1602 case OMP_CLAUSE_IF:
1603 case OMP_CLAUSE_NUM_THREADS:
1604 case OMP_CLAUSE_NUM_TEAMS:
1605 case OMP_CLAUSE_THREAD_LIMIT:
1606 case OMP_CLAUSE_DEVICE:
1607 case OMP_CLAUSE_SCHEDULE:
1608 case OMP_CLAUSE_DIST_SCHEDULE:
1609 case OMP_CLAUSE_DEPEND:
1610 if (ctx->outer)
1611 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1612 break;
1614 case OMP_CLAUSE_TO:
1615 case OMP_CLAUSE_FROM:
1616 case OMP_CLAUSE_MAP:
1617 if (ctx->outer)
1618 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1619 decl = OMP_CLAUSE_DECL (c);
1620 /* Global variables with "omp declare target" attribute
1621 don't need to be copied, the receiver side will use them
1622 directly. */
1623 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1624 && DECL_P (decl)
1625 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1626 && lookup_attribute ("omp declare target",
1627 DECL_ATTRIBUTES (decl)))
1628 break;
1629 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1630 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1632 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1633 #pragma omp target data, there is nothing to map for
1634 those. */
1635 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1636 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1637 break;
1639 if (DECL_P (decl))
1641 if (DECL_SIZE (decl)
1642 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1644 tree decl2 = DECL_VALUE_EXPR (decl);
1645 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1646 decl2 = TREE_OPERAND (decl2, 0);
1647 gcc_assert (DECL_P (decl2));
1648 install_var_field (decl2, true, 3, ctx);
1649 install_var_local (decl2, ctx);
1650 install_var_local (decl, ctx);
1652 else
1654 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1655 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1656 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1657 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1658 install_var_field (decl, true, 7, ctx);
1659 else
1660 install_var_field (decl, true, 3, ctx);
1661 if (gimple_omp_target_kind (ctx->stmt)
1662 == GF_OMP_TARGET_KIND_REGION)
1663 install_var_local (decl, ctx);
1666 else
1668 tree base = get_base_address (decl);
1669 tree nc = OMP_CLAUSE_CHAIN (c);
1670 if (DECL_P (base)
1671 && nc != NULL_TREE
1672 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1673 && OMP_CLAUSE_DECL (nc) == base
1674 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1675 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1677 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1678 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1680 else
1682 if (ctx->outer)
1684 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1685 decl = OMP_CLAUSE_DECL (c);
1687 gcc_assert (!splay_tree_lookup (ctx->field_map,
1688 (splay_tree_key) decl));
1689 tree field
1690 = build_decl (OMP_CLAUSE_LOCATION (c),
1691 FIELD_DECL, NULL_TREE, ptr_type_node);
1692 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1693 insert_field_into_struct (ctx->record_type, field);
1694 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1695 (splay_tree_value) field);
1698 break;
1700 case OMP_CLAUSE_NOWAIT:
1701 case OMP_CLAUSE_ORDERED:
1702 case OMP_CLAUSE_COLLAPSE:
1703 case OMP_CLAUSE_UNTIED:
1704 case OMP_CLAUSE_MERGEABLE:
1705 case OMP_CLAUSE_PROC_BIND:
1706 case OMP_CLAUSE_SAFELEN:
1707 break;
1709 case OMP_CLAUSE_ALIGNED:
1710 decl = OMP_CLAUSE_DECL (c);
1711 if (is_global_var (decl)
1712 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1713 install_var_local (decl, ctx);
1714 break;
1716 default:
1717 gcc_unreachable ();
1721 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1723 switch (OMP_CLAUSE_CODE (c))
1725 case OMP_CLAUSE_LASTPRIVATE:
1726 /* Let the corresponding firstprivate clause create
1727 the variable. */
1728 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1729 scan_array_reductions = true;
1730 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1731 break;
1732 /* FALLTHRU */
1734 case OMP_CLAUSE_PRIVATE:
1735 case OMP_CLAUSE_FIRSTPRIVATE:
1736 case OMP_CLAUSE_REDUCTION:
1737 case OMP_CLAUSE_LINEAR:
1738 decl = OMP_CLAUSE_DECL (c);
1739 if (is_variable_sized (decl))
1740 install_var_local (decl, ctx);
1741 fixup_remapped_decl (decl, ctx,
1742 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1743 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1744 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1745 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1746 scan_array_reductions = true;
1747 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1748 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1749 scan_array_reductions = true;
1750 break;
1752 case OMP_CLAUSE_SHARED:
1753 /* Ignore shared directives in teams construct. */
1754 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1755 break;
1756 decl = OMP_CLAUSE_DECL (c);
1757 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1758 fixup_remapped_decl (decl, ctx, false);
1759 break;
1761 case OMP_CLAUSE_MAP:
1762 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1763 break;
1764 decl = OMP_CLAUSE_DECL (c);
1765 if (DECL_P (decl)
1766 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1767 && lookup_attribute ("omp declare target",
1768 DECL_ATTRIBUTES (decl)))
1769 break;
1770 if (DECL_P (decl))
1772 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1773 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1774 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1776 tree new_decl = lookup_decl (decl, ctx);
1777 TREE_TYPE (new_decl)
1778 = remap_type (TREE_TYPE (decl), &ctx->cb);
1780 else if (DECL_SIZE (decl)
1781 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1783 tree decl2 = DECL_VALUE_EXPR (decl);
1784 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1785 decl2 = TREE_OPERAND (decl2, 0);
1786 gcc_assert (DECL_P (decl2));
1787 fixup_remapped_decl (decl2, ctx, false);
1788 fixup_remapped_decl (decl, ctx, true);
1790 else
1791 fixup_remapped_decl (decl, ctx, false);
1793 break;
1795 case OMP_CLAUSE_COPYPRIVATE:
1796 case OMP_CLAUSE_COPYIN:
1797 case OMP_CLAUSE_DEFAULT:
1798 case OMP_CLAUSE_IF:
1799 case OMP_CLAUSE_NUM_THREADS:
1800 case OMP_CLAUSE_NUM_TEAMS:
1801 case OMP_CLAUSE_THREAD_LIMIT:
1802 case OMP_CLAUSE_DEVICE:
1803 case OMP_CLAUSE_SCHEDULE:
1804 case OMP_CLAUSE_DIST_SCHEDULE:
1805 case OMP_CLAUSE_NOWAIT:
1806 case OMP_CLAUSE_ORDERED:
1807 case OMP_CLAUSE_COLLAPSE:
1808 case OMP_CLAUSE_UNTIED:
1809 case OMP_CLAUSE_FINAL:
1810 case OMP_CLAUSE_MERGEABLE:
1811 case OMP_CLAUSE_PROC_BIND:
1812 case OMP_CLAUSE_SAFELEN:
1813 case OMP_CLAUSE_ALIGNED:
1814 case OMP_CLAUSE_DEPEND:
1815 case OMP_CLAUSE__LOOPTEMP_:
1816 case OMP_CLAUSE_TO:
1817 case OMP_CLAUSE_FROM:
1818 break;
1820 default:
1821 gcc_unreachable ();
1825 if (scan_array_reductions)
1826 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1827 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1828 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1830 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1831 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1833 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1834 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1835 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1836 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1837 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1838 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1841 /* Create a new name for omp child function. Returns an identifier. */
1843 static tree
1844 create_omp_child_function_name (bool task_copy)
1846 return (clone_function_name (current_function_decl,
1847 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1850 /* Build a decl for the omp child function. It'll not contain a body
1851 yet, just the bare decl. */
1853 static void
1854 create_omp_child_function (omp_context *ctx, bool task_copy)
1856 tree decl, type, name, t;
1858 name = create_omp_child_function_name (task_copy);
1859 if (task_copy)
1860 type = build_function_type_list (void_type_node, ptr_type_node,
1861 ptr_type_node, NULL_TREE);
1862 else
1863 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1865 decl = build_decl (gimple_location (ctx->stmt),
1866 FUNCTION_DECL, name, type);
1868 if (!task_copy)
1869 ctx->cb.dst_fn = decl;
1870 else
1871 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1873 TREE_STATIC (decl) = 1;
1874 TREE_USED (decl) = 1;
1875 DECL_ARTIFICIAL (decl) = 1;
1876 DECL_IGNORED_P (decl) = 0;
1877 TREE_PUBLIC (decl) = 0;
1878 DECL_UNINLINABLE (decl) = 1;
1879 DECL_EXTERNAL (decl) = 0;
1880 DECL_CONTEXT (decl) = NULL_TREE;
1881 DECL_INITIAL (decl) = make_node (BLOCK);
1882 bool target_p = false;
1883 if (lookup_attribute ("omp declare target",
1884 DECL_ATTRIBUTES (current_function_decl)))
1885 target_p = true;
1886 else
1888 omp_context *octx;
1889 for (octx = ctx; octx; octx = octx->outer)
1890 if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
1891 && gimple_omp_target_kind (octx->stmt)
1892 == GF_OMP_TARGET_KIND_REGION)
1894 target_p = true;
1895 break;
1898 if (target_p)
1899 DECL_ATTRIBUTES (decl)
1900 = tree_cons (get_identifier ("omp declare target"),
1901 NULL_TREE, DECL_ATTRIBUTES (decl));
1903 t = build_decl (DECL_SOURCE_LOCATION (decl),
1904 RESULT_DECL, NULL_TREE, void_type_node);
1905 DECL_ARTIFICIAL (t) = 1;
1906 DECL_IGNORED_P (t) = 1;
1907 DECL_CONTEXT (t) = decl;
1908 DECL_RESULT (decl) = t;
1910 t = build_decl (DECL_SOURCE_LOCATION (decl),
1911 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1912 DECL_ARTIFICIAL (t) = 1;
1913 DECL_NAMELESS (t) = 1;
1914 DECL_ARG_TYPE (t) = ptr_type_node;
1915 DECL_CONTEXT (t) = current_function_decl;
1916 TREE_USED (t) = 1;
1917 DECL_ARGUMENTS (decl) = t;
1918 if (!task_copy)
1919 ctx->receiver_decl = t;
1920 else
1922 t = build_decl (DECL_SOURCE_LOCATION (decl),
1923 PARM_DECL, get_identifier (".omp_data_o"),
1924 ptr_type_node);
1925 DECL_ARTIFICIAL (t) = 1;
1926 DECL_NAMELESS (t) = 1;
1927 DECL_ARG_TYPE (t) = ptr_type_node;
1928 DECL_CONTEXT (t) = current_function_decl;
1929 TREE_USED (t) = 1;
1930 TREE_ADDRESSABLE (t) = 1;
1931 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1932 DECL_ARGUMENTS (decl) = t;
1935 /* Allocate memory for the function structure. The call to
1936 allocate_struct_function clobbers CFUN, so we need to restore
1937 it afterward. */
1938 push_struct_function (decl);
1939 cfun->function_end_locus = gimple_location (ctx->stmt);
1940 pop_cfun ();
1943 /* Callback for walk_gimple_seq. Check if combined parallel
1944 contains gimple_omp_for_combined_into_p OMP_FOR. */
1946 static tree
1947 find_combined_for (gimple_stmt_iterator *gsi_p,
1948 bool *handled_ops_p,
1949 struct walk_stmt_info *wi)
1951 gimple stmt = gsi_stmt (*gsi_p);
1953 *handled_ops_p = true;
1954 switch (gimple_code (stmt))
1956 WALK_SUBSTMTS;
1958 case GIMPLE_OMP_FOR:
1959 if (gimple_omp_for_combined_into_p (stmt)
1960 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
1962 wi->info = stmt;
1963 return integer_zero_node;
1965 break;
1966 default:
1967 break;
1969 return NULL;
1972 /* Scan an OpenMP parallel directive. */
1974 static void
1975 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1977 omp_context *ctx;
1978 tree name;
1979 gimple stmt = gsi_stmt (*gsi);
1981 /* Ignore parallel directives with empty bodies, unless there
1982 are copyin clauses. */
1983 if (optimize > 0
1984 && empty_body_p (gimple_omp_body (stmt))
1985 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1986 OMP_CLAUSE_COPYIN) == NULL)
1988 gsi_replace (gsi, gimple_build_nop (), false);
1989 return;
1992 if (gimple_omp_parallel_combined_p (stmt))
1994 gimple for_stmt;
1995 struct walk_stmt_info wi;
1997 memset (&wi, 0, sizeof (wi));
1998 wi.val_only = true;
1999 walk_gimple_seq (gimple_omp_body (stmt),
2000 find_combined_for, NULL, &wi);
2001 for_stmt = (gimple) wi.info;
2002 if (for_stmt)
2004 struct omp_for_data fd;
2005 extract_omp_for_data (for_stmt, &fd, NULL);
2006 /* We need two temporaries with fd.loop.v type (istart/iend)
2007 and then (fd.collapse - 1) temporaries with the same
2008 type for count2 ... countN-1 vars if not constant. */
2009 size_t count = 2, i;
2010 tree type = fd.iter_type;
2011 if (fd.collapse > 1
2012 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2013 count += fd.collapse - 1;
2014 for (i = 0; i < count; i++)
2016 tree temp = create_tmp_var (type, NULL);
2017 tree c = build_omp_clause (UNKNOWN_LOCATION,
2018 OMP_CLAUSE__LOOPTEMP_);
2019 insert_decl_map (&outer_ctx->cb, temp, temp);
2020 OMP_CLAUSE_DECL (c) = temp;
2021 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2022 gimple_omp_parallel_set_clauses (stmt, c);
2027 ctx = new_omp_context (stmt, outer_ctx);
2028 taskreg_contexts.safe_push (ctx);
2029 if (taskreg_nesting_level > 1)
2030 ctx->is_nested = true;
2031 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2032 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2033 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2034 name = create_tmp_var_name (".omp_data_s");
2035 name = build_decl (gimple_location (stmt),
2036 TYPE_DECL, name, ctx->record_type);
2037 DECL_ARTIFICIAL (name) = 1;
2038 DECL_NAMELESS (name) = 1;
2039 TYPE_NAME (ctx->record_type) = name;
2040 create_omp_child_function (ctx, false);
2041 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2043 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2044 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2046 if (TYPE_FIELDS (ctx->record_type) == NULL)
2047 ctx->record_type = ctx->receiver_decl = NULL;
2050 /* Scan an OpenMP task directive. */
2052 static void
2053 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2055 omp_context *ctx;
2056 tree name, t;
2057 gimple stmt = gsi_stmt (*gsi);
2059 /* Ignore task directives with empty bodies. */
2060 if (optimize > 0
2061 && empty_body_p (gimple_omp_body (stmt)))
2063 gsi_replace (gsi, gimple_build_nop (), false);
2064 return;
2067 ctx = new_omp_context (stmt, outer_ctx);
2068 taskreg_contexts.safe_push (ctx);
2069 if (taskreg_nesting_level > 1)
2070 ctx->is_nested = true;
2071 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2072 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2073 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2074 name = create_tmp_var_name (".omp_data_s");
2075 name = build_decl (gimple_location (stmt),
2076 TYPE_DECL, name, ctx->record_type);
2077 DECL_ARTIFICIAL (name) = 1;
2078 DECL_NAMELESS (name) = 1;
2079 TYPE_NAME (ctx->record_type) = name;
2080 create_omp_child_function (ctx, false);
2081 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2083 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2085 if (ctx->srecord_type)
2087 name = create_tmp_var_name (".omp_data_a");
2088 name = build_decl (gimple_location (stmt),
2089 TYPE_DECL, name, ctx->srecord_type);
2090 DECL_ARTIFICIAL (name) = 1;
2091 DECL_NAMELESS (name) = 1;
2092 TYPE_NAME (ctx->srecord_type) = name;
2093 create_omp_child_function (ctx, true);
2096 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2098 if (TYPE_FIELDS (ctx->record_type) == NULL)
2100 ctx->record_type = ctx->receiver_decl = NULL;
2101 t = build_int_cst (long_integer_type_node, 0);
2102 gimple_omp_task_set_arg_size (stmt, t);
2103 t = build_int_cst (long_integer_type_node, 1);
2104 gimple_omp_task_set_arg_align (stmt, t);
2109 /* If any decls have been made addressable during scan_omp,
2110 adjust their fields if needed, and layout record types
2111 of parallel/task constructs. */
2113 static void
2114 finish_taskreg_scan (omp_context *ctx)
2116 if (ctx->record_type == NULL_TREE)
2117 return;
2119 /* If any task_shared_vars were needed, verify all
2120 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2121 statements if use_pointer_for_field hasn't changed
2122 because of that. If it did, update field types now. */
2123 if (task_shared_vars)
2125 tree c;
2127 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2128 c; c = OMP_CLAUSE_CHAIN (c))
2129 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2131 tree decl = OMP_CLAUSE_DECL (c);
2133 /* Global variables don't need to be copied,
2134 the receiver side will use them directly. */
2135 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2136 continue;
2137 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2138 || !use_pointer_for_field (decl, ctx))
2139 continue;
2140 tree field = lookup_field (decl, ctx);
2141 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2142 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2143 continue;
2144 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2145 TREE_THIS_VOLATILE (field) = 0;
2146 DECL_USER_ALIGN (field) = 0;
2147 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2148 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2149 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2150 if (ctx->srecord_type)
2152 tree sfield = lookup_sfield (decl, ctx);
2153 TREE_TYPE (sfield) = TREE_TYPE (field);
2154 TREE_THIS_VOLATILE (sfield) = 0;
2155 DECL_USER_ALIGN (sfield) = 0;
2156 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2157 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2158 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2163 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2165 layout_type (ctx->record_type);
2166 fixup_child_record_type (ctx);
2168 else
2170 location_t loc = gimple_location (ctx->stmt);
2171 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2172 /* Move VLA fields to the end. */
2173 p = &TYPE_FIELDS (ctx->record_type);
2174 while (*p)
2175 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2176 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2178 *q = *p;
2179 *p = TREE_CHAIN (*p);
2180 TREE_CHAIN (*q) = NULL_TREE;
2181 q = &TREE_CHAIN (*q);
2183 else
2184 p = &DECL_CHAIN (*p);
2185 *p = vla_fields;
2186 layout_type (ctx->record_type);
2187 fixup_child_record_type (ctx);
2188 if (ctx->srecord_type)
2189 layout_type (ctx->srecord_type);
2190 tree t = fold_convert_loc (loc, long_integer_type_node,
2191 TYPE_SIZE_UNIT (ctx->record_type));
2192 gimple_omp_task_set_arg_size (ctx->stmt, t);
2193 t = build_int_cst (long_integer_type_node,
2194 TYPE_ALIGN_UNIT (ctx->record_type));
2195 gimple_omp_task_set_arg_align (ctx->stmt, t);
2200 /* Scan an OpenMP loop directive. */
2202 static void
2203 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2205 omp_context *ctx;
2206 size_t i;
2208 ctx = new_omp_context (stmt, outer_ctx);
2210 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2212 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2213 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2215 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2216 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2217 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2218 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2220 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2223 /* Scan an OpenMP sections directive. */
2225 static void
2226 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2228 omp_context *ctx;
2230 ctx = new_omp_context (stmt, outer_ctx);
2231 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2232 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2235 /* Scan an OpenMP single directive. */
2237 static void
2238 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2240 omp_context *ctx;
2241 tree name;
2243 ctx = new_omp_context (stmt, outer_ctx);
2244 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2245 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2246 name = create_tmp_var_name (".omp_copy_s");
2247 name = build_decl (gimple_location (stmt),
2248 TYPE_DECL, name, ctx->record_type);
2249 TYPE_NAME (ctx->record_type) = name;
2251 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2252 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2254 if (TYPE_FIELDS (ctx->record_type) == NULL)
2255 ctx->record_type = NULL;
2256 else
2257 layout_type (ctx->record_type);
2260 /* Scan an OpenMP target{, data, update} directive. */
2262 static void
2263 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2265 omp_context *ctx;
2266 tree name;
2267 int kind = gimple_omp_target_kind (stmt);
2269 ctx = new_omp_context (stmt, outer_ctx);
2270 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2271 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2272 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2273 name = create_tmp_var_name (".omp_data_t");
2274 name = build_decl (gimple_location (stmt),
2275 TYPE_DECL, name, ctx->record_type);
2276 DECL_ARTIFICIAL (name) = 1;
2277 DECL_NAMELESS (name) = 1;
2278 TYPE_NAME (ctx->record_type) = name;
2279 if (kind == GF_OMP_TARGET_KIND_REGION)
2281 create_omp_child_function (ctx, false);
2282 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2285 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2286 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2288 if (TYPE_FIELDS (ctx->record_type) == NULL)
2289 ctx->record_type = ctx->receiver_decl = NULL;
2290 else
2292 TYPE_FIELDS (ctx->record_type)
2293 = nreverse (TYPE_FIELDS (ctx->record_type));
2294 #ifdef ENABLE_CHECKING
2295 tree field;
2296 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2297 for (field = TYPE_FIELDS (ctx->record_type);
2298 field;
2299 field = DECL_CHAIN (field))
2300 gcc_assert (DECL_ALIGN (field) == align);
2301 #endif
2302 layout_type (ctx->record_type);
2303 if (kind == GF_OMP_TARGET_KIND_REGION)
2304 fixup_child_record_type (ctx);
2308 /* Scan an OpenMP teams directive. */
2310 static void
2311 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2313 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2314 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2315 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2318 /* Check OpenMP nesting restrictions. */
2319 static bool
2320 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2322 if (ctx != NULL)
2324 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2325 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2327 error_at (gimple_location (stmt),
2328 "OpenMP constructs may not be nested inside simd region");
2329 return false;
2331 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2333 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2334 || (gimple_omp_for_kind (stmt)
2335 != GF_OMP_FOR_KIND_DISTRIBUTE))
2336 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2338 error_at (gimple_location (stmt),
2339 "only distribute or parallel constructs are allowed to "
2340 "be closely nested inside teams construct");
2341 return false;
2345 switch (gimple_code (stmt))
2347 case GIMPLE_OMP_FOR:
2348 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_KIND_SIMD)
2349 return true;
2350 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2352 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2354 error_at (gimple_location (stmt),
2355 "distribute construct must be closely nested inside "
2356 "teams construct");
2357 return false;
2359 return true;
2361 /* FALLTHRU */
2362 case GIMPLE_CALL:
2363 if (is_gimple_call (stmt)
2364 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2365 == BUILT_IN_GOMP_CANCEL
2366 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2367 == BUILT_IN_GOMP_CANCELLATION_POINT))
2369 const char *bad = NULL;
2370 const char *kind = NULL;
2371 if (ctx == NULL)
2373 error_at (gimple_location (stmt), "orphaned %qs construct",
2374 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2375 == BUILT_IN_GOMP_CANCEL
2376 ? "#pragma omp cancel"
2377 : "#pragma omp cancellation point");
2378 return false;
2380 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2381 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2382 : 0)
2384 case 1:
2385 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2386 bad = "#pragma omp parallel";
2387 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2388 == BUILT_IN_GOMP_CANCEL
2389 && !integer_zerop (gimple_call_arg (stmt, 1)))
2390 ctx->cancellable = true;
2391 kind = "parallel";
2392 break;
2393 case 2:
2394 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2395 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2396 bad = "#pragma omp for";
2397 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2398 == BUILT_IN_GOMP_CANCEL
2399 && !integer_zerop (gimple_call_arg (stmt, 1)))
2401 ctx->cancellable = true;
2402 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2403 OMP_CLAUSE_NOWAIT))
2404 warning_at (gimple_location (stmt), 0,
2405 "%<#pragma omp cancel for%> inside "
2406 "%<nowait%> for construct");
2407 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2408 OMP_CLAUSE_ORDERED))
2409 warning_at (gimple_location (stmt), 0,
2410 "%<#pragma omp cancel for%> inside "
2411 "%<ordered%> for construct");
2413 kind = "for";
2414 break;
2415 case 4:
2416 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2417 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2418 bad = "#pragma omp sections";
2419 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2420 == BUILT_IN_GOMP_CANCEL
2421 && !integer_zerop (gimple_call_arg (stmt, 1)))
2423 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2425 ctx->cancellable = true;
2426 if (find_omp_clause (gimple_omp_sections_clauses
2427 (ctx->stmt),
2428 OMP_CLAUSE_NOWAIT))
2429 warning_at (gimple_location (stmt), 0,
2430 "%<#pragma omp cancel sections%> inside "
2431 "%<nowait%> sections construct");
2433 else
2435 gcc_assert (ctx->outer
2436 && gimple_code (ctx->outer->stmt)
2437 == GIMPLE_OMP_SECTIONS);
2438 ctx->outer->cancellable = true;
2439 if (find_omp_clause (gimple_omp_sections_clauses
2440 (ctx->outer->stmt),
2441 OMP_CLAUSE_NOWAIT))
2442 warning_at (gimple_location (stmt), 0,
2443 "%<#pragma omp cancel sections%> inside "
2444 "%<nowait%> sections construct");
2447 kind = "sections";
2448 break;
2449 case 8:
2450 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2451 bad = "#pragma omp task";
2452 else
2453 ctx->cancellable = true;
2454 kind = "taskgroup";
2455 break;
2456 default:
2457 error_at (gimple_location (stmt), "invalid arguments");
2458 return false;
2460 if (bad)
2462 error_at (gimple_location (stmt),
2463 "%<%s %s%> construct not closely nested inside of %qs",
2464 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2465 == BUILT_IN_GOMP_CANCEL
2466 ? "#pragma omp cancel"
2467 : "#pragma omp cancellation point", kind, bad);
2468 return false;
2471 /* FALLTHRU */
2472 case GIMPLE_OMP_SECTIONS:
2473 case GIMPLE_OMP_SINGLE:
2474 for (; ctx != NULL; ctx = ctx->outer)
2475 switch (gimple_code (ctx->stmt))
2477 case GIMPLE_OMP_FOR:
2478 case GIMPLE_OMP_SECTIONS:
2479 case GIMPLE_OMP_SINGLE:
2480 case GIMPLE_OMP_ORDERED:
2481 case GIMPLE_OMP_MASTER:
2482 case GIMPLE_OMP_TASK:
2483 case GIMPLE_OMP_CRITICAL:
2484 if (is_gimple_call (stmt))
2486 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2487 != BUILT_IN_GOMP_BARRIER)
2488 return true;
2489 error_at (gimple_location (stmt),
2490 "barrier region may not be closely nested inside "
2491 "of work-sharing, critical, ordered, master or "
2492 "explicit task region");
2493 return false;
2495 error_at (gimple_location (stmt),
2496 "work-sharing region may not be closely nested inside "
2497 "of work-sharing, critical, ordered, master or explicit "
2498 "task region");
2499 return false;
2500 case GIMPLE_OMP_PARALLEL:
2501 return true;
2502 default:
2503 break;
2505 break;
2506 case GIMPLE_OMP_MASTER:
2507 for (; ctx != NULL; ctx = ctx->outer)
2508 switch (gimple_code (ctx->stmt))
2510 case GIMPLE_OMP_FOR:
2511 case GIMPLE_OMP_SECTIONS:
2512 case GIMPLE_OMP_SINGLE:
2513 case GIMPLE_OMP_TASK:
2514 error_at (gimple_location (stmt),
2515 "master region may not be closely nested inside "
2516 "of work-sharing or explicit task region");
2517 return false;
2518 case GIMPLE_OMP_PARALLEL:
2519 return true;
2520 default:
2521 break;
2523 break;
2524 case GIMPLE_OMP_ORDERED:
2525 for (; ctx != NULL; ctx = ctx->outer)
2526 switch (gimple_code (ctx->stmt))
2528 case GIMPLE_OMP_CRITICAL:
2529 case GIMPLE_OMP_TASK:
2530 error_at (gimple_location (stmt),
2531 "ordered region may not be closely nested inside "
2532 "of critical or explicit task region");
2533 return false;
2534 case GIMPLE_OMP_FOR:
2535 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2536 OMP_CLAUSE_ORDERED) == NULL)
2538 error_at (gimple_location (stmt),
2539 "ordered region must be closely nested inside "
2540 "a loop region with an ordered clause");
2541 return false;
2543 return true;
2544 case GIMPLE_OMP_PARALLEL:
2545 error_at (gimple_location (stmt),
2546 "ordered region must be closely nested inside "
2547 "a loop region with an ordered clause");
2548 return false;
2549 default:
2550 break;
2552 break;
2553 case GIMPLE_OMP_CRITICAL:
2554 for (; ctx != NULL; ctx = ctx->outer)
2555 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2556 && (gimple_omp_critical_name (stmt)
2557 == gimple_omp_critical_name (ctx->stmt)))
2559 error_at (gimple_location (stmt),
2560 "critical region may not be nested inside a critical "
2561 "region with the same name");
2562 return false;
2564 break;
2565 case GIMPLE_OMP_TEAMS:
2566 if (ctx == NULL
2567 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2568 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2570 error_at (gimple_location (stmt),
2571 "teams construct not closely nested inside of target "
2572 "region");
2573 return false;
2575 break;
2576 case GIMPLE_OMP_TARGET:
2577 for (; ctx != NULL; ctx = ctx->outer)
2578 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
2579 && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION)
2581 const char *name;
2582 switch (gimple_omp_target_kind (stmt))
2584 case GF_OMP_TARGET_KIND_REGION: name = "target"; break;
2585 case GF_OMP_TARGET_KIND_DATA: name = "target data"; break;
2586 case GF_OMP_TARGET_KIND_UPDATE: name = "target update"; break;
2587 default: gcc_unreachable ();
2589 warning_at (gimple_location (stmt), 0,
2590 "%s construct inside of target region", name);
2592 break;
2593 default:
2594 break;
2596 return true;
2600 /* Helper function scan_omp.
2602 Callback for walk_tree or operators in walk_gimple_stmt used to
2603 scan for OpenMP directives in TP. */
2605 static tree
2606 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2608 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2609 omp_context *ctx = (omp_context *) wi->info;
2610 tree t = *tp;
2612 switch (TREE_CODE (t))
2614 case VAR_DECL:
2615 case PARM_DECL:
2616 case LABEL_DECL:
2617 case RESULT_DECL:
2618 if (ctx)
2619 *tp = remap_decl (t, &ctx->cb);
2620 break;
2622 default:
2623 if (ctx && TYPE_P (t))
2624 *tp = remap_type (t, &ctx->cb);
2625 else if (!DECL_P (t))
2627 *walk_subtrees = 1;
2628 if (ctx)
2630 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2631 if (tem != TREE_TYPE (t))
2633 if (TREE_CODE (t) == INTEGER_CST)
2634 *tp = build_int_cst_wide (tem,
2635 TREE_INT_CST_LOW (t),
2636 TREE_INT_CST_HIGH (t));
2637 else
2638 TREE_TYPE (t) = tem;
2642 break;
2645 return NULL_TREE;
2648 /* Return true if FNDECL is a setjmp or a longjmp. */
2650 static bool
2651 setjmp_or_longjmp_p (const_tree fndecl)
2653 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2654 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2655 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2656 return true;
2658 tree declname = DECL_NAME (fndecl);
2659 if (!declname)
2660 return false;
2661 const char *name = IDENTIFIER_POINTER (declname);
2662 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2666 /* Helper function for scan_omp.
2668 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2669 the current statement in GSI. */
2671 static tree
2672 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2673 struct walk_stmt_info *wi)
2675 gimple stmt = gsi_stmt (*gsi);
2676 omp_context *ctx = (omp_context *) wi->info;
2678 if (gimple_has_location (stmt))
2679 input_location = gimple_location (stmt);
2681 /* Check the OpenMP nesting restrictions. */
2682 bool remove = false;
2683 if (is_gimple_omp (stmt))
2684 remove = !check_omp_nesting_restrictions (stmt, ctx);
2685 else if (is_gimple_call (stmt))
2687 tree fndecl = gimple_call_fndecl (stmt);
2688 if (fndecl)
2690 if (setjmp_or_longjmp_p (fndecl)
2691 && ctx
2692 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2693 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2695 remove = true;
2696 error_at (gimple_location (stmt),
2697 "setjmp/longjmp inside simd construct");
2699 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2700 switch (DECL_FUNCTION_CODE (fndecl))
2702 case BUILT_IN_GOMP_BARRIER:
2703 case BUILT_IN_GOMP_CANCEL:
2704 case BUILT_IN_GOMP_CANCELLATION_POINT:
2705 case BUILT_IN_GOMP_TASKYIELD:
2706 case BUILT_IN_GOMP_TASKWAIT:
2707 case BUILT_IN_GOMP_TASKGROUP_START:
2708 case BUILT_IN_GOMP_TASKGROUP_END:
2709 remove = !check_omp_nesting_restrictions (stmt, ctx);
2710 break;
2711 default:
2712 break;
2716 if (remove)
2718 stmt = gimple_build_nop ();
2719 gsi_replace (gsi, stmt, false);
2722 *handled_ops_p = true;
2724 switch (gimple_code (stmt))
2726 case GIMPLE_OMP_PARALLEL:
2727 taskreg_nesting_level++;
2728 scan_omp_parallel (gsi, ctx);
2729 taskreg_nesting_level--;
2730 break;
2732 case GIMPLE_OMP_TASK:
2733 taskreg_nesting_level++;
2734 scan_omp_task (gsi, ctx);
2735 taskreg_nesting_level--;
2736 break;
2738 case GIMPLE_OMP_FOR:
2739 scan_omp_for (stmt, ctx);
2740 break;
2742 case GIMPLE_OMP_SECTIONS:
2743 scan_omp_sections (stmt, ctx);
2744 break;
2746 case GIMPLE_OMP_SINGLE:
2747 scan_omp_single (stmt, ctx);
2748 break;
2750 case GIMPLE_OMP_SECTION:
2751 case GIMPLE_OMP_MASTER:
2752 case GIMPLE_OMP_TASKGROUP:
2753 case GIMPLE_OMP_ORDERED:
2754 case GIMPLE_OMP_CRITICAL:
2755 ctx = new_omp_context (stmt, ctx);
2756 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2757 break;
2759 case GIMPLE_OMP_TARGET:
2760 scan_omp_target (stmt, ctx);
2761 break;
2763 case GIMPLE_OMP_TEAMS:
2764 scan_omp_teams (stmt, ctx);
2765 break;
2767 case GIMPLE_BIND:
2769 tree var;
2771 *handled_ops_p = false;
2772 if (ctx)
2773 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2774 insert_decl_map (&ctx->cb, var, var);
2776 break;
2777 default:
2778 *handled_ops_p = false;
2779 break;
2782 return NULL_TREE;
2786 /* Scan all the statements starting at the current statement. CTX
2787 contains context information about the OpenMP directives and
2788 clauses found during the scan. */
2790 static void
2791 scan_omp (gimple_seq *body_p, omp_context *ctx)
2793 location_t saved_location;
2794 struct walk_stmt_info wi;
2796 memset (&wi, 0, sizeof (wi));
2797 wi.info = ctx;
2798 wi.want_locations = true;
2800 saved_location = input_location;
2801 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2802 input_location = saved_location;
2805 /* Re-gimplification and code generation routines. */
2807 /* Build a call to GOMP_barrier. */
2809 static gimple
2810 build_omp_barrier (tree lhs)
2812 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2813 : BUILT_IN_GOMP_BARRIER);
2814 gimple g = gimple_build_call (fndecl, 0);
2815 if (lhs)
2816 gimple_call_set_lhs (g, lhs);
2817 return g;
2820 /* If a context was created for STMT when it was scanned, return it. */
2822 static omp_context *
2823 maybe_lookup_ctx (gimple stmt)
2825 splay_tree_node n;
2826 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2827 return n ? (omp_context *) n->value : NULL;
2831 /* Find the mapping for DECL in CTX or the immediately enclosing
2832 context that has a mapping for DECL.
2834 If CTX is a nested parallel directive, we may have to use the decl
2835 mappings created in CTX's parent context. Suppose that we have the
2836 following parallel nesting (variable UIDs showed for clarity):
2838 iD.1562 = 0;
2839 #omp parallel shared(iD.1562) -> outer parallel
2840 iD.1562 = iD.1562 + 1;
2842 #omp parallel shared (iD.1562) -> inner parallel
2843 iD.1562 = iD.1562 - 1;
2845 Each parallel structure will create a distinct .omp_data_s structure
2846 for copying iD.1562 in/out of the directive:
2848 outer parallel .omp_data_s.1.i -> iD.1562
2849 inner parallel .omp_data_s.2.i -> iD.1562
2851 A shared variable mapping will produce a copy-out operation before
2852 the parallel directive and a copy-in operation after it. So, in
2853 this case we would have:
2855 iD.1562 = 0;
2856 .omp_data_o.1.i = iD.1562;
2857 #omp parallel shared(iD.1562) -> outer parallel
2858 .omp_data_i.1 = &.omp_data_o.1
2859 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2861 .omp_data_o.2.i = iD.1562; -> **
2862 #omp parallel shared(iD.1562) -> inner parallel
2863 .omp_data_i.2 = &.omp_data_o.2
2864 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2867 ** This is a problem. The symbol iD.1562 cannot be referenced
2868 inside the body of the outer parallel region. But since we are
2869 emitting this copy operation while expanding the inner parallel
2870 directive, we need to access the CTX structure of the outer
2871 parallel directive to get the correct mapping:
2873 .omp_data_o.2.i = .omp_data_i.1->i
2875 Since there may be other workshare or parallel directives enclosing
2876 the parallel directive, it may be necessary to walk up the context
2877 parent chain. This is not a problem in general because nested
2878 parallelism happens only rarely. */
2880 static tree
2881 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2883 tree t;
2884 omp_context *up;
2886 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2887 t = maybe_lookup_decl (decl, up);
2889 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2891 return t ? t : decl;
2895 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2896 in outer contexts. */
2898 static tree
2899 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2901 tree t = NULL;
2902 omp_context *up;
2904 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2905 t = maybe_lookup_decl (decl, up);
2907 return t ? t : decl;
2911 /* Construct the initialization value for reduction CLAUSE. */
2913 tree
2914 omp_reduction_init (tree clause, tree type)
2916 location_t loc = OMP_CLAUSE_LOCATION (clause);
2917 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2919 case PLUS_EXPR:
2920 case MINUS_EXPR:
2921 case BIT_IOR_EXPR:
2922 case BIT_XOR_EXPR:
2923 case TRUTH_OR_EXPR:
2924 case TRUTH_ORIF_EXPR:
2925 case TRUTH_XOR_EXPR:
2926 case NE_EXPR:
2927 return build_zero_cst (type);
2929 case MULT_EXPR:
2930 case TRUTH_AND_EXPR:
2931 case TRUTH_ANDIF_EXPR:
2932 case EQ_EXPR:
2933 return fold_convert_loc (loc, type, integer_one_node);
2935 case BIT_AND_EXPR:
2936 return fold_convert_loc (loc, type, integer_minus_one_node);
2938 case MAX_EXPR:
2939 if (SCALAR_FLOAT_TYPE_P (type))
2941 REAL_VALUE_TYPE max, min;
2942 if (HONOR_INFINITIES (TYPE_MODE (type)))
2944 real_inf (&max);
2945 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2947 else
2948 real_maxval (&min, 1, TYPE_MODE (type));
2949 return build_real (type, min);
2951 else
2953 gcc_assert (INTEGRAL_TYPE_P (type));
2954 return TYPE_MIN_VALUE (type);
2957 case MIN_EXPR:
2958 if (SCALAR_FLOAT_TYPE_P (type))
2960 REAL_VALUE_TYPE max;
2961 if (HONOR_INFINITIES (TYPE_MODE (type)))
2962 real_inf (&max);
2963 else
2964 real_maxval (&max, 0, TYPE_MODE (type));
2965 return build_real (type, max);
2967 else
2969 gcc_assert (INTEGRAL_TYPE_P (type));
2970 return TYPE_MAX_VALUE (type);
2973 default:
2974 gcc_unreachable ();
2978 /* Return alignment to be assumed for var in CLAUSE, which should be
2979 OMP_CLAUSE_ALIGNED. */
2981 static tree
2982 omp_clause_aligned_alignment (tree clause)
2984 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
2985 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
2987 /* Otherwise return implementation defined alignment. */
2988 unsigned int al = 1;
2989 enum machine_mode mode, vmode;
2990 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2991 if (vs)
2992 vs = 1 << floor_log2 (vs);
2993 static enum mode_class classes[]
2994 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
2995 for (int i = 0; i < 4; i += 2)
2996 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
2997 mode != VOIDmode;
2998 mode = GET_MODE_WIDER_MODE (mode))
3000 vmode = targetm.vectorize.preferred_simd_mode (mode);
3001 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3002 continue;
3003 while (vs
3004 && GET_MODE_SIZE (vmode) < vs
3005 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3006 vmode = GET_MODE_2XWIDER_MODE (vmode);
3008 tree type = lang_hooks.types.type_for_mode (mode, 1);
3009 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3010 continue;
3011 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3012 / GET_MODE_SIZE (mode));
3013 if (TYPE_MODE (type) != vmode)
3014 continue;
3015 if (TYPE_ALIGN_UNIT (type) > al)
3016 al = TYPE_ALIGN_UNIT (type);
3018 return build_int_cst (integer_type_node, al);
3021 /* Return maximum possible vectorization factor for the target. */
3023 static int
3024 omp_max_vf (void)
3026 if (!optimize
3027 || optimize_debug
3028 || !flag_tree_loop_optimize
3029 || (!flag_tree_loop_vectorize
3030 && (global_options_set.x_flag_tree_loop_vectorize
3031 || global_options_set.x_flag_tree_vectorize)))
3032 return 1;
3034 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3035 if (vs)
3037 vs = 1 << floor_log2 (vs);
3038 return vs;
3040 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3041 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3042 return GET_MODE_NUNITS (vqimode);
3043 return 1;
3046 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3047 privatization. */
3049 static bool
3050 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3051 tree &idx, tree &lane, tree &ivar, tree &lvar)
3053 if (max_vf == 0)
3055 max_vf = omp_max_vf ();
3056 if (max_vf > 1)
3058 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3059 OMP_CLAUSE_SAFELEN);
3060 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3061 max_vf = 1;
3062 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3063 max_vf) == -1)
3064 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3066 if (max_vf > 1)
3068 idx = create_tmp_var (unsigned_type_node, NULL);
3069 lane = create_tmp_var (unsigned_type_node, NULL);
3072 if (max_vf == 1)
3073 return false;
3075 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3076 tree avar = create_tmp_var_raw (atype, NULL);
3077 if (TREE_ADDRESSABLE (new_var))
3078 TREE_ADDRESSABLE (avar) = 1;
3079 DECL_ATTRIBUTES (avar)
3080 = tree_cons (get_identifier ("omp simd array"), NULL,
3081 DECL_ATTRIBUTES (avar));
3082 gimple_add_tmp_var (avar);
3083 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3084 NULL_TREE, NULL_TREE);
3085 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3086 NULL_TREE, NULL_TREE);
3087 if (DECL_P (new_var))
3089 SET_DECL_VALUE_EXPR (new_var, lvar);
3090 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3092 return true;
3095 /* Helper function of lower_rec_input_clauses. For a reference
3096 in simd reduction, add an underlying variable it will reference. */
3098 static void
3099 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3101 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3102 if (TREE_CONSTANT (z))
3104 const char *name = NULL;
3105 if (DECL_NAME (new_vard))
3106 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3108 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3109 gimple_add_tmp_var (z);
3110 TREE_ADDRESSABLE (z) = 1;
3111 z = build_fold_addr_expr_loc (loc, z);
3112 gimplify_assign (new_vard, z, ilist);
3116 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3117 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3118 private variables. Initialization statements go in ILIST, while calls
3119 to destructors go in DLIST. */
3121 static void
3122 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3123 omp_context *ctx, struct omp_for_data *fd)
3125 tree c, dtor, copyin_seq, x, ptr;
3126 bool copyin_by_ref = false;
3127 bool lastprivate_firstprivate = false;
3128 bool reduction_omp_orig_ref = false;
3129 int pass;
3130 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3131 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD);
3132 int max_vf = 0;
3133 tree lane = NULL_TREE, idx = NULL_TREE;
3134 tree ivar = NULL_TREE, lvar = NULL_TREE;
3135 gimple_seq llist[2] = { NULL, NULL };
3137 copyin_seq = NULL;
3139 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3140 with data sharing clauses referencing variable sized vars. That
3141 is unnecessarily hard to support and very unlikely to result in
3142 vectorized code anyway. */
3143 if (is_simd)
3144 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3145 switch (OMP_CLAUSE_CODE (c))
3147 case OMP_CLAUSE_LINEAR:
3148 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3149 max_vf = 1;
3150 /* FALLTHRU */
3151 case OMP_CLAUSE_REDUCTION:
3152 case OMP_CLAUSE_PRIVATE:
3153 case OMP_CLAUSE_FIRSTPRIVATE:
3154 case OMP_CLAUSE_LASTPRIVATE:
3155 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3156 max_vf = 1;
3157 break;
3158 default:
3159 continue;
3162 /* Do all the fixed sized types in the first pass, and the variable sized
3163 types in the second pass. This makes sure that the scalar arguments to
3164 the variable sized types are processed before we use them in the
3165 variable sized operations. */
3166 for (pass = 0; pass < 2; ++pass)
3168 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3170 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3171 tree var, new_var;
3172 bool by_ref;
3173 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3175 switch (c_kind)
3177 case OMP_CLAUSE_PRIVATE:
3178 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3179 continue;
3180 break;
3181 case OMP_CLAUSE_SHARED:
3182 /* Ignore shared directives in teams construct. */
3183 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3184 continue;
3185 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3187 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3188 continue;
3190 case OMP_CLAUSE_FIRSTPRIVATE:
3191 case OMP_CLAUSE_COPYIN:
3192 case OMP_CLAUSE_LINEAR:
3193 break;
3194 case OMP_CLAUSE_REDUCTION:
3195 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3196 reduction_omp_orig_ref = true;
3197 break;
3198 case OMP_CLAUSE__LOOPTEMP_:
3199 /* Handle _looptemp_ clauses only on parallel. */
3200 if (fd)
3201 continue;
3202 break;
3203 case OMP_CLAUSE_LASTPRIVATE:
3204 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3206 lastprivate_firstprivate = true;
3207 if (pass != 0)
3208 continue;
3210 /* Even without corresponding firstprivate, if
3211 decl is Fortran allocatable, it needs outer var
3212 reference. */
3213 else if (pass == 0
3214 && lang_hooks.decls.omp_private_outer_ref
3215 (OMP_CLAUSE_DECL (c)))
3216 lastprivate_firstprivate = true;
3217 break;
3218 case OMP_CLAUSE_ALIGNED:
3219 if (pass == 0)
3220 continue;
3221 var = OMP_CLAUSE_DECL (c);
3222 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3223 && !is_global_var (var))
3225 new_var = maybe_lookup_decl (var, ctx);
3226 if (new_var == NULL_TREE)
3227 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3228 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3229 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3230 omp_clause_aligned_alignment (c));
3231 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3232 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3233 gimplify_and_add (x, ilist);
3235 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3236 && is_global_var (var))
3238 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3239 new_var = lookup_decl (var, ctx);
3240 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3241 t = build_fold_addr_expr_loc (clause_loc, t);
3242 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3243 t = build_call_expr_loc (clause_loc, t2, 2, t,
3244 omp_clause_aligned_alignment (c));
3245 t = fold_convert_loc (clause_loc, ptype, t);
3246 x = create_tmp_var (ptype, NULL);
3247 t = build2 (MODIFY_EXPR, ptype, x, t);
3248 gimplify_and_add (t, ilist);
3249 t = build_simple_mem_ref_loc (clause_loc, x);
3250 SET_DECL_VALUE_EXPR (new_var, t);
3251 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3253 continue;
3254 default:
3255 continue;
3258 new_var = var = OMP_CLAUSE_DECL (c);
3259 if (c_kind != OMP_CLAUSE_COPYIN)
3260 new_var = lookup_decl (var, ctx);
3262 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3264 if (pass != 0)
3265 continue;
3267 else if (is_variable_sized (var))
3269 /* For variable sized types, we need to allocate the
3270 actual storage here. Call alloca and store the
3271 result in the pointer decl that we created elsewhere. */
3272 if (pass == 0)
3273 continue;
3275 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3277 gimple stmt;
3278 tree tmp, atmp;
3280 ptr = DECL_VALUE_EXPR (new_var);
3281 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3282 ptr = TREE_OPERAND (ptr, 0);
3283 gcc_assert (DECL_P (ptr));
3284 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3286 /* void *tmp = __builtin_alloca */
3287 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3288 stmt = gimple_build_call (atmp, 1, x);
3289 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3290 gimple_add_tmp_var (tmp);
3291 gimple_call_set_lhs (stmt, tmp);
3293 gimple_seq_add_stmt (ilist, stmt);
3295 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3296 gimplify_assign (ptr, x, ilist);
3299 else if (is_reference (var))
3301 /* For references that are being privatized for Fortran,
3302 allocate new backing storage for the new pointer
3303 variable. This allows us to avoid changing all the
3304 code that expects a pointer to something that expects
3305 a direct variable. */
3306 if (pass == 0)
3307 continue;
3309 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3310 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3312 x = build_receiver_ref (var, false, ctx);
3313 x = build_fold_addr_expr_loc (clause_loc, x);
3315 else if (TREE_CONSTANT (x))
3317 /* For reduction in SIMD loop, defer adding the
3318 initialization of the reference, because if we decide
3319 to use SIMD array for it, the initilization could cause
3320 expansion ICE. */
3321 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3322 x = NULL_TREE;
3323 else
3325 const char *name = NULL;
3326 if (DECL_NAME (var))
3327 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3329 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3330 name);
3331 gimple_add_tmp_var (x);
3332 TREE_ADDRESSABLE (x) = 1;
3333 x = build_fold_addr_expr_loc (clause_loc, x);
3336 else
3338 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3339 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3342 if (x)
3344 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3345 gimplify_assign (new_var, x, ilist);
3348 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3350 else if (c_kind == OMP_CLAUSE_REDUCTION
3351 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3353 if (pass == 0)
3354 continue;
3356 else if (pass != 0)
3357 continue;
3359 switch (OMP_CLAUSE_CODE (c))
3361 case OMP_CLAUSE_SHARED:
3362 /* Ignore shared directives in teams construct. */
3363 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3364 continue;
3365 /* Shared global vars are just accessed directly. */
3366 if (is_global_var (new_var))
3367 break;
3368 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3369 needs to be delayed until after fixup_child_record_type so
3370 that we get the correct type during the dereference. */
3371 by_ref = use_pointer_for_field (var, ctx);
3372 x = build_receiver_ref (var, by_ref, ctx);
3373 SET_DECL_VALUE_EXPR (new_var, x);
3374 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3376 /* ??? If VAR is not passed by reference, and the variable
3377 hasn't been initialized yet, then we'll get a warning for
3378 the store into the omp_data_s structure. Ideally, we'd be
3379 able to notice this and not store anything at all, but
3380 we're generating code too early. Suppress the warning. */
3381 if (!by_ref)
3382 TREE_NO_WARNING (var) = 1;
3383 break;
3385 case OMP_CLAUSE_LASTPRIVATE:
3386 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3387 break;
3388 /* FALLTHRU */
3390 case OMP_CLAUSE_PRIVATE:
3391 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3392 x = build_outer_var_ref (var, ctx);
3393 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3395 if (is_task_ctx (ctx))
3396 x = build_receiver_ref (var, false, ctx);
3397 else
3398 x = build_outer_var_ref (var, ctx);
3400 else
3401 x = NULL;
3402 do_private:
3403 tree nx;
3404 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3405 if (is_simd)
3407 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3408 if ((TREE_ADDRESSABLE (new_var) || nx || y
3409 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3410 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3411 idx, lane, ivar, lvar))
3413 if (nx)
3414 x = lang_hooks.decls.omp_clause_default_ctor
3415 (c, unshare_expr (ivar), x);
3416 if (nx && x)
3417 gimplify_and_add (x, &llist[0]);
3418 if (y)
3420 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3421 if (y)
3423 gimple_seq tseq = NULL;
3425 dtor = y;
3426 gimplify_stmt (&dtor, &tseq);
3427 gimple_seq_add_seq (&llist[1], tseq);
3430 break;
3433 if (nx)
3434 gimplify_and_add (nx, ilist);
3435 /* FALLTHRU */
3437 do_dtor:
3438 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3439 if (x)
3441 gimple_seq tseq = NULL;
3443 dtor = x;
3444 gimplify_stmt (&dtor, &tseq);
3445 gimple_seq_add_seq (dlist, tseq);
3447 break;
3449 case OMP_CLAUSE_LINEAR:
3450 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3451 goto do_firstprivate;
3452 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3453 x = NULL;
3454 else
3455 x = build_outer_var_ref (var, ctx);
3456 goto do_private;
3458 case OMP_CLAUSE_FIRSTPRIVATE:
3459 if (is_task_ctx (ctx))
3461 if (is_reference (var) || is_variable_sized (var))
3462 goto do_dtor;
3463 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3464 ctx))
3465 || use_pointer_for_field (var, NULL))
3467 x = build_receiver_ref (var, false, ctx);
3468 SET_DECL_VALUE_EXPR (new_var, x);
3469 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3470 goto do_dtor;
3473 do_firstprivate:
3474 x = build_outer_var_ref (var, ctx);
3475 if (is_simd)
3477 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3478 && gimple_omp_for_combined_into_p (ctx->stmt))
3480 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3481 tree stept = TREE_TYPE (t);
3482 tree ct = find_omp_clause (clauses,
3483 OMP_CLAUSE__LOOPTEMP_);
3484 gcc_assert (ct);
3485 tree l = OMP_CLAUSE_DECL (ct);
3486 tree n1 = fd->loop.n1;
3487 tree step = fd->loop.step;
3488 tree itype = TREE_TYPE (l);
3489 if (POINTER_TYPE_P (itype))
3490 itype = signed_type_for (itype);
3491 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3492 if (TYPE_UNSIGNED (itype)
3493 && fd->loop.cond_code == GT_EXPR)
3494 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3495 fold_build1 (NEGATE_EXPR, itype, l),
3496 fold_build1 (NEGATE_EXPR,
3497 itype, step));
3498 else
3499 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3500 t = fold_build2 (MULT_EXPR, stept,
3501 fold_convert (stept, l), t);
3503 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3505 x = lang_hooks.decls.omp_clause_linear_ctor
3506 (c, new_var, x, t);
3507 gimplify_and_add (x, ilist);
3508 goto do_dtor;
3511 if (POINTER_TYPE_P (TREE_TYPE (x)))
3512 x = fold_build2 (POINTER_PLUS_EXPR,
3513 TREE_TYPE (x), x, t);
3514 else
3515 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3518 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3519 || TREE_ADDRESSABLE (new_var))
3520 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3521 idx, lane, ivar, lvar))
3523 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3525 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3526 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3527 gimplify_and_add (x, ilist);
3528 gimple_stmt_iterator gsi
3529 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3530 gimple g
3531 = gimple_build_assign (unshare_expr (lvar), iv);
3532 gsi_insert_before_without_update (&gsi, g,
3533 GSI_SAME_STMT);
3534 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3535 enum tree_code code = PLUS_EXPR;
3536 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3537 code = POINTER_PLUS_EXPR;
3538 g = gimple_build_assign_with_ops (code, iv, iv, t);
3539 gsi_insert_before_without_update (&gsi, g,
3540 GSI_SAME_STMT);
3541 break;
3543 x = lang_hooks.decls.omp_clause_copy_ctor
3544 (c, unshare_expr (ivar), x);
3545 gimplify_and_add (x, &llist[0]);
3546 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3547 if (x)
3549 gimple_seq tseq = NULL;
3551 dtor = x;
3552 gimplify_stmt (&dtor, &tseq);
3553 gimple_seq_add_seq (&llist[1], tseq);
3555 break;
3558 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3559 gimplify_and_add (x, ilist);
3560 goto do_dtor;
3562 case OMP_CLAUSE__LOOPTEMP_:
3563 gcc_assert (is_parallel_ctx (ctx));
3564 x = build_outer_var_ref (var, ctx);
3565 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3566 gimplify_and_add (x, ilist);
3567 break;
3569 case OMP_CLAUSE_COPYIN:
3570 by_ref = use_pointer_for_field (var, NULL);
3571 x = build_receiver_ref (var, by_ref, ctx);
3572 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3573 append_to_statement_list (x, &copyin_seq);
3574 copyin_by_ref |= by_ref;
3575 break;
3577 case OMP_CLAUSE_REDUCTION:
3578 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3580 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3581 gimple tseq;
3582 x = build_outer_var_ref (var, ctx);
3584 if (is_reference (var)
3585 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3586 TREE_TYPE (x)))
3587 x = build_fold_addr_expr_loc (clause_loc, x);
3588 SET_DECL_VALUE_EXPR (placeholder, x);
3589 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3590 tree new_vard = new_var;
3591 if (is_reference (var))
3593 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3594 new_vard = TREE_OPERAND (new_var, 0);
3595 gcc_assert (DECL_P (new_vard));
3597 if (is_simd
3598 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3599 idx, lane, ivar, lvar))
3601 if (new_vard == new_var)
3603 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3604 SET_DECL_VALUE_EXPR (new_var, ivar);
3606 else
3608 SET_DECL_VALUE_EXPR (new_vard,
3609 build_fold_addr_expr (ivar));
3610 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3612 x = lang_hooks.decls.omp_clause_default_ctor
3613 (c, unshare_expr (ivar),
3614 build_outer_var_ref (var, ctx));
3615 if (x)
3616 gimplify_and_add (x, &llist[0]);
3617 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3619 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3620 lower_omp (&tseq, ctx);
3621 gimple_seq_add_seq (&llist[0], tseq);
3623 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3624 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3625 lower_omp (&tseq, ctx);
3626 gimple_seq_add_seq (&llist[1], tseq);
3627 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3628 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3629 if (new_vard == new_var)
3630 SET_DECL_VALUE_EXPR (new_var, lvar);
3631 else
3632 SET_DECL_VALUE_EXPR (new_vard,
3633 build_fold_addr_expr (lvar));
3634 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3635 if (x)
3637 tseq = NULL;
3638 dtor = x;
3639 gimplify_stmt (&dtor, &tseq);
3640 gimple_seq_add_seq (&llist[1], tseq);
3642 break;
3644 /* If this is a reference to constant size reduction var
3645 with placeholder, we haven't emitted the initializer
3646 for it because it is undesirable if SIMD arrays are used.
3647 But if they aren't used, we need to emit the deferred
3648 initialization now. */
3649 else if (is_reference (var) && is_simd)
3650 handle_simd_reference (clause_loc, new_vard, ilist);
3651 x = lang_hooks.decls.omp_clause_default_ctor
3652 (c, unshare_expr (new_var),
3653 build_outer_var_ref (var, ctx));
3654 if (x)
3655 gimplify_and_add (x, ilist);
3656 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3658 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3659 lower_omp (&tseq, ctx);
3660 gimple_seq_add_seq (ilist, tseq);
3662 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3663 if (is_simd)
3665 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3666 lower_omp (&tseq, ctx);
3667 gimple_seq_add_seq (dlist, tseq);
3668 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3670 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3671 goto do_dtor;
3673 else
3675 x = omp_reduction_init (c, TREE_TYPE (new_var));
3676 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3677 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3679 /* reduction(-:var) sums up the partial results, so it
3680 acts identically to reduction(+:var). */
3681 if (code == MINUS_EXPR)
3682 code = PLUS_EXPR;
3684 tree new_vard = new_var;
3685 if (is_simd && is_reference (var))
3687 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3688 new_vard = TREE_OPERAND (new_var, 0);
3689 gcc_assert (DECL_P (new_vard));
3691 if (is_simd
3692 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3693 idx, lane, ivar, lvar))
3695 tree ref = build_outer_var_ref (var, ctx);
3697 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3699 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3700 ref = build_outer_var_ref (var, ctx);
3701 gimplify_assign (ref, x, &llist[1]);
3703 if (new_vard != new_var)
3705 SET_DECL_VALUE_EXPR (new_vard,
3706 build_fold_addr_expr (lvar));
3707 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3710 else
3712 if (is_reference (var) && is_simd)
3713 handle_simd_reference (clause_loc, new_vard, ilist);
3714 gimplify_assign (new_var, x, ilist);
3715 if (is_simd)
3717 tree ref = build_outer_var_ref (var, ctx);
3719 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3720 ref = build_outer_var_ref (var, ctx);
3721 gimplify_assign (ref, x, dlist);
3725 break;
3727 default:
3728 gcc_unreachable ();
3733 if (lane)
3735 tree uid = create_tmp_var (ptr_type_node, "simduid");
3736 /* Don't want uninit warnings on simduid, it is always uninitialized,
3737 but we use it not for the value, but for the DECL_UID only. */
3738 TREE_NO_WARNING (uid) = 1;
3739 gimple g
3740 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3741 gimple_call_set_lhs (g, lane);
3742 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3743 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3744 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3745 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3746 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3747 gimple_omp_for_set_clauses (ctx->stmt, c);
3748 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3749 build_int_cst (unsigned_type_node, 0),
3750 NULL_TREE);
3751 gimple_seq_add_stmt (ilist, g);
3752 for (int i = 0; i < 2; i++)
3753 if (llist[i])
3755 tree vf = create_tmp_var (unsigned_type_node, NULL);
3756 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3757 gimple_call_set_lhs (g, vf);
3758 gimple_seq *seq = i == 0 ? ilist : dlist;
3759 gimple_seq_add_stmt (seq, g);
3760 tree t = build_int_cst (unsigned_type_node, 0);
3761 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3762 gimple_seq_add_stmt (seq, g);
3763 tree body = create_artificial_label (UNKNOWN_LOCATION);
3764 tree header = create_artificial_label (UNKNOWN_LOCATION);
3765 tree end = create_artificial_label (UNKNOWN_LOCATION);
3766 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3767 gimple_seq_add_stmt (seq, gimple_build_label (body));
3768 gimple_seq_add_seq (seq, llist[i]);
3769 t = build_int_cst (unsigned_type_node, 1);
3770 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3771 gimple_seq_add_stmt (seq, g);
3772 gimple_seq_add_stmt (seq, gimple_build_label (header));
3773 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3774 gimple_seq_add_stmt (seq, g);
3775 gimple_seq_add_stmt (seq, gimple_build_label (end));
3779 /* The copyin sequence is not to be executed by the main thread, since
3780 that would result in self-copies. Perhaps not visible to scalars,
3781 but it certainly is to C++ operator=. */
3782 if (copyin_seq)
3784 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3786 x = build2 (NE_EXPR, boolean_type_node, x,
3787 build_int_cst (TREE_TYPE (x), 0));
3788 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3789 gimplify_and_add (x, ilist);
3792 /* If any copyin variable is passed by reference, we must ensure the
3793 master thread doesn't modify it before it is copied over in all
3794 threads. Similarly for variables in both firstprivate and
3795 lastprivate clauses we need to ensure the lastprivate copying
3796 happens after firstprivate copying in all threads. And similarly
3797 for UDRs if initializer expression refers to omp_orig. */
3798 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3800 /* Don't add any barrier for #pragma omp simd or
3801 #pragma omp distribute. */
3802 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3803 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3804 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3807 /* If max_vf is non-zero, then we can use only a vectorization factor
3808 up to the max_vf we chose. So stick it into the safelen clause. */
3809 if (max_vf)
3811 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3812 OMP_CLAUSE_SAFELEN);
3813 if (c == NULL_TREE
3814 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
3815 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3816 max_vf) == 1))
3818 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3819 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3820 max_vf);
3821 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3822 gimple_omp_for_set_clauses (ctx->stmt, c);
3828 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3829 both parallel and workshare constructs. PREDICATE may be NULL if it's
3830 always true. */
3832 static void
3833 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3834 omp_context *ctx)
3836 tree x, c, label = NULL, orig_clauses = clauses;
3837 bool par_clauses = false;
3838 tree simduid = NULL, lastlane = NULL;
3840 /* Early exit if there are no lastprivate or linear clauses. */
3841 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3842 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3843 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3844 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3845 break;
3846 if (clauses == NULL)
3848 /* If this was a workshare clause, see if it had been combined
3849 with its parallel. In that case, look for the clauses on the
3850 parallel statement itself. */
3851 if (is_parallel_ctx (ctx))
3852 return;
3854 ctx = ctx->outer;
3855 if (ctx == NULL || !is_parallel_ctx (ctx))
3856 return;
3858 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3859 OMP_CLAUSE_LASTPRIVATE);
3860 if (clauses == NULL)
3861 return;
3862 par_clauses = true;
3865 if (predicate)
3867 gimple stmt;
3868 tree label_true, arm1, arm2;
3870 label = create_artificial_label (UNKNOWN_LOCATION);
3871 label_true = create_artificial_label (UNKNOWN_LOCATION);
3872 arm1 = TREE_OPERAND (predicate, 0);
3873 arm2 = TREE_OPERAND (predicate, 1);
3874 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3875 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3876 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3877 label_true, label);
3878 gimple_seq_add_stmt (stmt_list, stmt);
3879 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3882 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3883 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
3885 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3886 if (simduid)
3887 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3890 for (c = clauses; c ;)
3892 tree var, new_var;
3893 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3895 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3896 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3897 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3899 var = OMP_CLAUSE_DECL (c);
3900 new_var = lookup_decl (var, ctx);
3902 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3904 tree val = DECL_VALUE_EXPR (new_var);
3905 if (TREE_CODE (val) == ARRAY_REF
3906 && VAR_P (TREE_OPERAND (val, 0))
3907 && lookup_attribute ("omp simd array",
3908 DECL_ATTRIBUTES (TREE_OPERAND (val,
3909 0))))
3911 if (lastlane == NULL)
3913 lastlane = create_tmp_var (unsigned_type_node, NULL);
3914 gimple g
3915 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
3916 2, simduid,
3917 TREE_OPERAND (val, 1));
3918 gimple_call_set_lhs (g, lastlane);
3919 gimple_seq_add_stmt (stmt_list, g);
3921 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
3922 TREE_OPERAND (val, 0), lastlane,
3923 NULL_TREE, NULL_TREE);
3927 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3928 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
3930 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
3931 gimple_seq_add_seq (stmt_list,
3932 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3933 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
3935 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3936 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
3938 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
3939 gimple_seq_add_seq (stmt_list,
3940 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
3941 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
3944 x = build_outer_var_ref (var, ctx);
3945 if (is_reference (var))
3946 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3947 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
3948 gimplify_and_add (x, stmt_list);
3950 c = OMP_CLAUSE_CHAIN (c);
3951 if (c == NULL && !par_clauses)
3953 /* If this was a workshare clause, see if it had been combined
3954 with its parallel. In that case, continue looking for the
3955 clauses also on the parallel statement itself. */
3956 if (is_parallel_ctx (ctx))
3957 break;
3959 ctx = ctx->outer;
3960 if (ctx == NULL || !is_parallel_ctx (ctx))
3961 break;
3963 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3964 OMP_CLAUSE_LASTPRIVATE);
3965 par_clauses = true;
3969 if (label)
3970 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
3974 /* Generate code to implement the REDUCTION clauses. */
3976 static void
3977 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
3979 gimple_seq sub_seq = NULL;
3980 gimple stmt;
3981 tree x, c;
3982 int count = 0;
3984 /* SIMD reductions are handled in lower_rec_input_clauses. */
3985 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3986 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
3987 return;
3989 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3990 update in that case, otherwise use a lock. */
3991 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
3992 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
3994 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3996 /* Never use OMP_ATOMIC for array reductions or UDRs. */
3997 count = -1;
3998 break;
4000 count++;
4003 if (count == 0)
4004 return;
4006 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4008 tree var, ref, new_var;
4009 enum tree_code code;
4010 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4012 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4013 continue;
4015 var = OMP_CLAUSE_DECL (c);
4016 new_var = lookup_decl (var, ctx);
4017 if (is_reference (var))
4018 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4019 ref = build_outer_var_ref (var, ctx);
4020 code = OMP_CLAUSE_REDUCTION_CODE (c);
4022 /* reduction(-:var) sums up the partial results, so it acts
4023 identically to reduction(+:var). */
4024 if (code == MINUS_EXPR)
4025 code = PLUS_EXPR;
4027 if (count == 1)
4029 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4031 addr = save_expr (addr);
4032 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4033 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4034 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4035 gimplify_and_add (x, stmt_seqp);
4036 return;
4039 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4041 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4043 if (is_reference (var)
4044 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4045 TREE_TYPE (ref)))
4046 ref = build_fold_addr_expr_loc (clause_loc, ref);
4047 SET_DECL_VALUE_EXPR (placeholder, ref);
4048 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4049 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4050 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4051 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4052 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4054 else
4056 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4057 ref = build_outer_var_ref (var, ctx);
4058 gimplify_assign (ref, x, &sub_seq);
4062 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4064 gimple_seq_add_stmt (stmt_seqp, stmt);
4066 gimple_seq_add_seq (stmt_seqp, sub_seq);
4068 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4070 gimple_seq_add_stmt (stmt_seqp, stmt);
4074 /* Generate code to implement the COPYPRIVATE clauses. */
4076 static void
4077 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4078 omp_context *ctx)
4080 tree c;
4082 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4084 tree var, new_var, ref, x;
4085 bool by_ref;
4086 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4088 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4089 continue;
4091 var = OMP_CLAUSE_DECL (c);
4092 by_ref = use_pointer_for_field (var, NULL);
4094 ref = build_sender_ref (var, ctx);
4095 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4096 if (by_ref)
4098 x = build_fold_addr_expr_loc (clause_loc, new_var);
4099 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4101 gimplify_assign (ref, x, slist);
4103 ref = build_receiver_ref (var, false, ctx);
4104 if (by_ref)
4106 ref = fold_convert_loc (clause_loc,
4107 build_pointer_type (TREE_TYPE (new_var)),
4108 ref);
4109 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4111 if (is_reference (var))
4113 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4114 ref = build_simple_mem_ref_loc (clause_loc, ref);
4115 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4117 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4118 gimplify_and_add (x, rlist);
4123 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4124 and REDUCTION from the sender (aka parent) side. */
4126 static void
4127 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4128 omp_context *ctx)
4130 tree c;
4132 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4134 tree val, ref, x, var;
4135 bool by_ref, do_in = false, do_out = false;
4136 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4138 switch (OMP_CLAUSE_CODE (c))
4140 case OMP_CLAUSE_PRIVATE:
4141 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4142 break;
4143 continue;
4144 case OMP_CLAUSE_FIRSTPRIVATE:
4145 case OMP_CLAUSE_COPYIN:
4146 case OMP_CLAUSE_LASTPRIVATE:
4147 case OMP_CLAUSE_REDUCTION:
4148 case OMP_CLAUSE__LOOPTEMP_:
4149 break;
4150 default:
4151 continue;
4154 val = OMP_CLAUSE_DECL (c);
4155 var = lookup_decl_in_outer_ctx (val, ctx);
4157 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4158 && is_global_var (var))
4159 continue;
4160 if (is_variable_sized (val))
4161 continue;
4162 by_ref = use_pointer_for_field (val, NULL);
4164 switch (OMP_CLAUSE_CODE (c))
4166 case OMP_CLAUSE_PRIVATE:
4167 case OMP_CLAUSE_FIRSTPRIVATE:
4168 case OMP_CLAUSE_COPYIN:
4169 case OMP_CLAUSE__LOOPTEMP_:
4170 do_in = true;
4171 break;
4173 case OMP_CLAUSE_LASTPRIVATE:
4174 if (by_ref || is_reference (val))
4176 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4177 continue;
4178 do_in = true;
4180 else
4182 do_out = true;
4183 if (lang_hooks.decls.omp_private_outer_ref (val))
4184 do_in = true;
4186 break;
4188 case OMP_CLAUSE_REDUCTION:
4189 do_in = true;
4190 do_out = !(by_ref || is_reference (val));
4191 break;
4193 default:
4194 gcc_unreachable ();
4197 if (do_in)
4199 ref = build_sender_ref (val, ctx);
4200 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4201 gimplify_assign (ref, x, ilist);
4202 if (is_task_ctx (ctx))
4203 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4206 if (do_out)
4208 ref = build_sender_ref (val, ctx);
4209 gimplify_assign (var, ref, olist);
4214 /* Generate code to implement SHARED from the sender (aka parent)
4215 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4216 list things that got automatically shared. */
4218 static void
4219 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4221 tree var, ovar, nvar, f, x, record_type;
4223 if (ctx->record_type == NULL)
4224 return;
4226 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4227 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4229 ovar = DECL_ABSTRACT_ORIGIN (f);
4230 nvar = maybe_lookup_decl (ovar, ctx);
4231 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4232 continue;
4234 /* If CTX is a nested parallel directive. Find the immediately
4235 enclosing parallel or workshare construct that contains a
4236 mapping for OVAR. */
4237 var = lookup_decl_in_outer_ctx (ovar, ctx);
4239 if (use_pointer_for_field (ovar, ctx))
4241 x = build_sender_ref (ovar, ctx);
4242 var = build_fold_addr_expr (var);
4243 gimplify_assign (x, var, ilist);
4245 else
4247 x = build_sender_ref (ovar, ctx);
4248 gimplify_assign (x, var, ilist);
4250 if (!TREE_READONLY (var)
4251 /* We don't need to receive a new reference to a result
4252 or parm decl. In fact we may not store to it as we will
4253 invalidate any pending RSO and generate wrong gimple
4254 during inlining. */
4255 && !((TREE_CODE (var) == RESULT_DECL
4256 || TREE_CODE (var) == PARM_DECL)
4257 && DECL_BY_REFERENCE (var)))
4259 x = build_sender_ref (ovar, ctx);
4260 gimplify_assign (var, x, olist);
4267 /* A convenience function to build an empty GIMPLE_COND with just the
4268 condition. */
4270 static gimple
4271 gimple_build_cond_empty (tree cond)
4273 enum tree_code pred_code;
4274 tree lhs, rhs;
4276 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4277 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4281 /* Build the function calls to GOMP_parallel_start etc to actually
4282 generate the parallel operation. REGION is the parallel region
4283 being expanded. BB is the block where to insert the code. WS_ARGS
4284 will be set if this is a call to a combined parallel+workshare
4285 construct, it contains the list of additional arguments needed by
4286 the workshare construct. */
4288 static void
4289 expand_parallel_call (struct omp_region *region, basic_block bb,
4290 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4292 tree t, t1, t2, val, cond, c, clauses, flags;
4293 gimple_stmt_iterator gsi;
4294 gimple stmt;
4295 enum built_in_function start_ix;
4296 int start_ix2;
4297 location_t clause_loc;
4298 vec<tree, va_gc> *args;
4300 clauses = gimple_omp_parallel_clauses (entry_stmt);
4302 /* Determine what flavor of GOMP_parallel we will be
4303 emitting. */
4304 start_ix = BUILT_IN_GOMP_PARALLEL;
4305 if (is_combined_parallel (region))
4307 switch (region->inner->type)
4309 case GIMPLE_OMP_FOR:
4310 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4311 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4312 + (region->inner->sched_kind
4313 == OMP_CLAUSE_SCHEDULE_RUNTIME
4314 ? 3 : region->inner->sched_kind));
4315 start_ix = (enum built_in_function)start_ix2;
4316 break;
4317 case GIMPLE_OMP_SECTIONS:
4318 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4319 break;
4320 default:
4321 gcc_unreachable ();
4325 /* By default, the value of NUM_THREADS is zero (selected at run time)
4326 and there is no conditional. */
4327 cond = NULL_TREE;
4328 val = build_int_cst (unsigned_type_node, 0);
4329 flags = build_int_cst (unsigned_type_node, 0);
4331 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4332 if (c)
4333 cond = OMP_CLAUSE_IF_EXPR (c);
4335 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4336 if (c)
4338 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4339 clause_loc = OMP_CLAUSE_LOCATION (c);
4341 else
4342 clause_loc = gimple_location (entry_stmt);
4344 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4345 if (c)
4346 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4348 /* Ensure 'val' is of the correct type. */
4349 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4351 /* If we found the clause 'if (cond)', build either
4352 (cond != 0) or (cond ? val : 1u). */
4353 if (cond)
4355 gimple_stmt_iterator gsi;
4357 cond = gimple_boolify (cond);
4359 if (integer_zerop (val))
4360 val = fold_build2_loc (clause_loc,
4361 EQ_EXPR, unsigned_type_node, cond,
4362 build_int_cst (TREE_TYPE (cond), 0));
4363 else
4365 basic_block cond_bb, then_bb, else_bb;
4366 edge e, e_then, e_else;
4367 tree tmp_then, tmp_else, tmp_join, tmp_var;
4369 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4370 if (gimple_in_ssa_p (cfun))
4372 tmp_then = make_ssa_name (tmp_var, NULL);
4373 tmp_else = make_ssa_name (tmp_var, NULL);
4374 tmp_join = make_ssa_name (tmp_var, NULL);
4376 else
4378 tmp_then = tmp_var;
4379 tmp_else = tmp_var;
4380 tmp_join = tmp_var;
4383 e = split_block (bb, NULL);
4384 cond_bb = e->src;
4385 bb = e->dest;
4386 remove_edge (e);
4388 then_bb = create_empty_bb (cond_bb);
4389 else_bb = create_empty_bb (then_bb);
4390 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4391 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4393 stmt = gimple_build_cond_empty (cond);
4394 gsi = gsi_start_bb (cond_bb);
4395 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4397 gsi = gsi_start_bb (then_bb);
4398 stmt = gimple_build_assign (tmp_then, val);
4399 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4401 gsi = gsi_start_bb (else_bb);
4402 stmt = gimple_build_assign
4403 (tmp_else, build_int_cst (unsigned_type_node, 1));
4404 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4406 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4407 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4408 if (current_loops)
4410 add_bb_to_loop (then_bb, cond_bb->loop_father);
4411 add_bb_to_loop (else_bb, cond_bb->loop_father);
4413 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4414 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4416 if (gimple_in_ssa_p (cfun))
4418 gimple phi = create_phi_node (tmp_join, bb);
4419 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4420 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4423 val = tmp_join;
4426 gsi = gsi_start_bb (bb);
4427 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4428 false, GSI_CONTINUE_LINKING);
4431 gsi = gsi_last_bb (bb);
4432 t = gimple_omp_parallel_data_arg (entry_stmt);
4433 if (t == NULL)
4434 t1 = null_pointer_node;
4435 else
4436 t1 = build_fold_addr_expr (t);
4437 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4439 vec_alloc (args, 4 + vec_safe_length (ws_args));
4440 args->quick_push (t2);
4441 args->quick_push (t1);
4442 args->quick_push (val);
4443 if (ws_args)
4444 args->splice (*ws_args);
4445 args->quick_push (flags);
4447 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4448 builtin_decl_explicit (start_ix), args);
4450 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4451 false, GSI_CONTINUE_LINKING);
4455 /* Build the function call to GOMP_task to actually
4456 generate the task operation. BB is the block where to insert the code. */
4458 static void
4459 expand_task_call (basic_block bb, gimple entry_stmt)
4461 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4462 gimple_stmt_iterator gsi;
4463 location_t loc = gimple_location (entry_stmt);
4465 clauses = gimple_omp_task_clauses (entry_stmt);
4467 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4468 if (c)
4469 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4470 else
4471 cond = boolean_true_node;
4473 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4474 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4475 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4476 flags = build_int_cst (unsigned_type_node,
4477 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4479 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4480 if (c)
4482 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4483 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4484 build_int_cst (unsigned_type_node, 2),
4485 build_int_cst (unsigned_type_node, 0));
4486 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4488 if (depend)
4489 depend = OMP_CLAUSE_DECL (depend);
4490 else
4491 depend = build_int_cst (ptr_type_node, 0);
4493 gsi = gsi_last_bb (bb);
4494 t = gimple_omp_task_data_arg (entry_stmt);
4495 if (t == NULL)
4496 t2 = null_pointer_node;
4497 else
4498 t2 = build_fold_addr_expr_loc (loc, t);
4499 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4500 t = gimple_omp_task_copy_fn (entry_stmt);
4501 if (t == NULL)
4502 t3 = null_pointer_node;
4503 else
4504 t3 = build_fold_addr_expr_loc (loc, t);
4506 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4507 8, t1, t2, t3,
4508 gimple_omp_task_arg_size (entry_stmt),
4509 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4510 depend);
4512 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4513 false, GSI_CONTINUE_LINKING);
4517 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4518 catch handler and return it. This prevents programs from violating the
4519 structured block semantics with throws. */
4521 static gimple_seq
4522 maybe_catch_exception (gimple_seq body)
4524 gimple g;
4525 tree decl;
4527 if (!flag_exceptions)
4528 return body;
4530 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4531 decl = lang_hooks.eh_protect_cleanup_actions ();
4532 else
4533 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4535 g = gimple_build_eh_must_not_throw (decl);
4536 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4537 GIMPLE_TRY_CATCH);
4539 return gimple_seq_alloc_with_stmt (g);
4542 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4544 static tree
4545 vec2chain (vec<tree, va_gc> *v)
4547 tree chain = NULL_TREE, t;
4548 unsigned ix;
4550 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4552 DECL_CHAIN (t) = chain;
4553 chain = t;
4556 return chain;
4560 /* Remove barriers in REGION->EXIT's block. Note that this is only
4561 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4562 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4563 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4564 removed. */
4566 static void
4567 remove_exit_barrier (struct omp_region *region)
4569 gimple_stmt_iterator gsi;
4570 basic_block exit_bb;
4571 edge_iterator ei;
4572 edge e;
4573 gimple stmt;
4574 int any_addressable_vars = -1;
4576 exit_bb = region->exit;
4578 /* If the parallel region doesn't return, we don't have REGION->EXIT
4579 block at all. */
4580 if (! exit_bb)
4581 return;
4583 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4584 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4585 statements that can appear in between are extremely limited -- no
4586 memory operations at all. Here, we allow nothing at all, so the
4587 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4588 gsi = gsi_last_bb (exit_bb);
4589 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4590 gsi_prev (&gsi);
4591 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4592 return;
4594 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4596 gsi = gsi_last_bb (e->src);
4597 if (gsi_end_p (gsi))
4598 continue;
4599 stmt = gsi_stmt (gsi);
4600 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4601 && !gimple_omp_return_nowait_p (stmt))
4603 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4604 in many cases. If there could be tasks queued, the barrier
4605 might be needed to let the tasks run before some local
4606 variable of the parallel that the task uses as shared
4607 runs out of scope. The task can be spawned either
4608 from within current function (this would be easy to check)
4609 or from some function it calls and gets passed an address
4610 of such a variable. */
4611 if (any_addressable_vars < 0)
4613 gimple parallel_stmt = last_stmt (region->entry);
4614 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4615 tree local_decls, block, decl;
4616 unsigned ix;
4618 any_addressable_vars = 0;
4619 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4620 if (TREE_ADDRESSABLE (decl))
4622 any_addressable_vars = 1;
4623 break;
4625 for (block = gimple_block (stmt);
4626 !any_addressable_vars
4627 && block
4628 && TREE_CODE (block) == BLOCK;
4629 block = BLOCK_SUPERCONTEXT (block))
4631 for (local_decls = BLOCK_VARS (block);
4632 local_decls;
4633 local_decls = DECL_CHAIN (local_decls))
4634 if (TREE_ADDRESSABLE (local_decls))
4636 any_addressable_vars = 1;
4637 break;
4639 if (block == gimple_block (parallel_stmt))
4640 break;
4643 if (!any_addressable_vars)
4644 gimple_omp_return_set_nowait (stmt);
4649 static void
4650 remove_exit_barriers (struct omp_region *region)
4652 if (region->type == GIMPLE_OMP_PARALLEL)
4653 remove_exit_barrier (region);
4655 if (region->inner)
4657 region = region->inner;
4658 remove_exit_barriers (region);
4659 while (region->next)
4661 region = region->next;
4662 remove_exit_barriers (region);
4667 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4668 calls. These can't be declared as const functions, but
4669 within one parallel body they are constant, so they can be
4670 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4671 which are declared const. Similarly for task body, except
4672 that in untied task omp_get_thread_num () can change at any task
4673 scheduling point. */
4675 static void
4676 optimize_omp_library_calls (gimple entry_stmt)
4678 basic_block bb;
4679 gimple_stmt_iterator gsi;
4680 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4681 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4682 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4683 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4684 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4685 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4686 OMP_CLAUSE_UNTIED) != NULL);
4688 FOR_EACH_BB_FN (bb, cfun)
4689 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4691 gimple call = gsi_stmt (gsi);
4692 tree decl;
4694 if (is_gimple_call (call)
4695 && (decl = gimple_call_fndecl (call))
4696 && DECL_EXTERNAL (decl)
4697 && TREE_PUBLIC (decl)
4698 && DECL_INITIAL (decl) == NULL)
4700 tree built_in;
4702 if (DECL_NAME (decl) == thr_num_id)
4704 /* In #pragma omp task untied omp_get_thread_num () can change
4705 during the execution of the task region. */
4706 if (untied_task)
4707 continue;
4708 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4710 else if (DECL_NAME (decl) == num_thr_id)
4711 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4712 else
4713 continue;
4715 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4716 || gimple_call_num_args (call) != 0)
4717 continue;
4719 if (flag_exceptions && !TREE_NOTHROW (decl))
4720 continue;
4722 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4723 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4724 TREE_TYPE (TREE_TYPE (built_in))))
4725 continue;
4727 gimple_call_set_fndecl (call, built_in);
4732 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4733 regimplified. */
4735 static tree
4736 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4738 tree t = *tp;
4740 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4741 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4742 return t;
4744 if (TREE_CODE (t) == ADDR_EXPR)
4745 recompute_tree_invariant_for_addr_expr (t);
4747 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4748 return NULL_TREE;
4751 /* Prepend TO = FROM assignment before *GSI_P. */
4753 static void
4754 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4756 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4757 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4758 true, GSI_SAME_STMT);
4759 gimple stmt = gimple_build_assign (to, from);
4760 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4761 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4762 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4764 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4765 gimple_regimplify_operands (stmt, &gsi);
4769 /* Expand the OpenMP parallel or task directive starting at REGION. */
4771 static void
4772 expand_omp_taskreg (struct omp_region *region)
4774 basic_block entry_bb, exit_bb, new_bb;
4775 struct function *child_cfun;
4776 tree child_fn, block, t;
4777 gimple_stmt_iterator gsi;
4778 gimple entry_stmt, stmt;
4779 edge e;
4780 vec<tree, va_gc> *ws_args;
4782 entry_stmt = last_stmt (region->entry);
4783 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4784 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4786 entry_bb = region->entry;
4787 exit_bb = region->exit;
4789 if (is_combined_parallel (region))
4790 ws_args = region->ws_args;
4791 else
4792 ws_args = NULL;
4794 if (child_cfun->cfg)
4796 /* Due to inlining, it may happen that we have already outlined
4797 the region, in which case all we need to do is make the
4798 sub-graph unreachable and emit the parallel call. */
4799 edge entry_succ_e, exit_succ_e;
4800 gimple_stmt_iterator gsi;
4802 entry_succ_e = single_succ_edge (entry_bb);
4804 gsi = gsi_last_bb (entry_bb);
4805 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4806 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4807 gsi_remove (&gsi, true);
4809 new_bb = entry_bb;
4810 if (exit_bb)
4812 exit_succ_e = single_succ_edge (exit_bb);
4813 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4815 remove_edge_and_dominated_blocks (entry_succ_e);
4817 else
4819 unsigned srcidx, dstidx, num;
4821 /* If the parallel region needs data sent from the parent
4822 function, then the very first statement (except possible
4823 tree profile counter updates) of the parallel body
4824 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4825 &.OMP_DATA_O is passed as an argument to the child function,
4826 we need to replace it with the argument as seen by the child
4827 function.
4829 In most cases, this will end up being the identity assignment
4830 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4831 a function call that has been inlined, the original PARM_DECL
4832 .OMP_DATA_I may have been converted into a different local
4833 variable. In which case, we need to keep the assignment. */
4834 if (gimple_omp_taskreg_data_arg (entry_stmt))
4836 basic_block entry_succ_bb = single_succ (entry_bb);
4837 gimple_stmt_iterator gsi;
4838 tree arg, narg;
4839 gimple parcopy_stmt = NULL;
4841 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4843 gimple stmt;
4845 gcc_assert (!gsi_end_p (gsi));
4846 stmt = gsi_stmt (gsi);
4847 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4848 continue;
4850 if (gimple_num_ops (stmt) == 2)
4852 tree arg = gimple_assign_rhs1 (stmt);
4854 /* We're ignore the subcode because we're
4855 effectively doing a STRIP_NOPS. */
4857 if (TREE_CODE (arg) == ADDR_EXPR
4858 && TREE_OPERAND (arg, 0)
4859 == gimple_omp_taskreg_data_arg (entry_stmt))
4861 parcopy_stmt = stmt;
4862 break;
4867 gcc_assert (parcopy_stmt != NULL);
4868 arg = DECL_ARGUMENTS (child_fn);
4870 if (!gimple_in_ssa_p (cfun))
4872 if (gimple_assign_lhs (parcopy_stmt) == arg)
4873 gsi_remove (&gsi, true);
4874 else
4876 /* ?? Is setting the subcode really necessary ?? */
4877 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
4878 gimple_assign_set_rhs1 (parcopy_stmt, arg);
4881 else
4883 /* If we are in ssa form, we must load the value from the default
4884 definition of the argument. That should not be defined now,
4885 since the argument is not used uninitialized. */
4886 gcc_assert (ssa_default_def (cfun, arg) == NULL);
4887 narg = make_ssa_name (arg, gimple_build_nop ());
4888 set_ssa_default_def (cfun, arg, narg);
4889 /* ?? Is setting the subcode really necessary ?? */
4890 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
4891 gimple_assign_set_rhs1 (parcopy_stmt, narg);
4892 update_stmt (parcopy_stmt);
4896 /* Declare local variables needed in CHILD_CFUN. */
4897 block = DECL_INITIAL (child_fn);
4898 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4899 /* The gimplifier could record temporaries in parallel/task block
4900 rather than in containing function's local_decls chain,
4901 which would mean cgraph missed finalizing them. Do it now. */
4902 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4903 if (TREE_CODE (t) == VAR_DECL
4904 && TREE_STATIC (t)
4905 && !DECL_EXTERNAL (t))
4906 varpool_finalize_decl (t);
4907 DECL_SAVED_TREE (child_fn) = NULL;
4908 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4909 gimple_set_body (child_fn, NULL);
4910 TREE_USED (block) = 1;
4912 /* Reset DECL_CONTEXT on function arguments. */
4913 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
4914 DECL_CONTEXT (t) = child_fn;
4916 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
4917 so that it can be moved to the child function. */
4918 gsi = gsi_last_bb (entry_bb);
4919 stmt = gsi_stmt (gsi);
4920 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
4921 || gimple_code (stmt) == GIMPLE_OMP_TASK));
4922 gsi_remove (&gsi, true);
4923 e = split_block (entry_bb, stmt);
4924 entry_bb = e->dest;
4925 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4927 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4928 if (exit_bb)
4930 gsi = gsi_last_bb (exit_bb);
4931 gcc_assert (!gsi_end_p (gsi)
4932 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4933 stmt = gimple_build_return (NULL);
4934 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4935 gsi_remove (&gsi, true);
4938 /* Move the parallel region into CHILD_CFUN. */
4940 if (gimple_in_ssa_p (cfun))
4942 init_tree_ssa (child_cfun);
4943 init_ssa_operands (child_cfun);
4944 child_cfun->gimple_df->in_ssa_p = true;
4945 block = NULL_TREE;
4947 else
4948 block = gimple_block (entry_stmt);
4950 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
4951 if (exit_bb)
4952 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
4953 /* When the OMP expansion process cannot guarantee an up-to-date
4954 loop tree arrange for the child function to fixup loops. */
4955 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
4956 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
4958 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
4959 num = vec_safe_length (child_cfun->local_decls);
4960 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
4962 t = (*child_cfun->local_decls)[srcidx];
4963 if (DECL_CONTEXT (t) == cfun->decl)
4964 continue;
4965 if (srcidx != dstidx)
4966 (*child_cfun->local_decls)[dstidx] = t;
4967 dstidx++;
4969 if (dstidx != num)
4970 vec_safe_truncate (child_cfun->local_decls, dstidx);
4972 /* Inform the callgraph about the new function. */
4973 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
4974 cgraph_add_new_function (child_fn, true);
4976 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4977 fixed in a following pass. */
4978 push_cfun (child_cfun);
4979 if (optimize)
4980 optimize_omp_library_calls (entry_stmt);
4981 rebuild_cgraph_edges ();
4983 /* Some EH regions might become dead, see PR34608. If
4984 pass_cleanup_cfg isn't the first pass to happen with the
4985 new child, these dead EH edges might cause problems.
4986 Clean them up now. */
4987 if (flag_exceptions)
4989 basic_block bb;
4990 bool changed = false;
4992 FOR_EACH_BB_FN (bb, cfun)
4993 changed |= gimple_purge_dead_eh_edges (bb);
4994 if (changed)
4995 cleanup_tree_cfg ();
4997 if (gimple_in_ssa_p (cfun))
4998 update_ssa (TODO_update_ssa);
4999 pop_cfun ();
5002 /* Emit a library call to launch the children threads. */
5003 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5004 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
5005 else
5006 expand_task_call (new_bb, entry_stmt);
5007 if (gimple_in_ssa_p (cfun))
5008 update_ssa (TODO_update_ssa_only_virtuals);
5012 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5013 of the combined collapse > 1 loop constructs, generate code like:
5014 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5015 if (cond3 is <)
5016 adj = STEP3 - 1;
5017 else
5018 adj = STEP3 + 1;
5019 count3 = (adj + N32 - N31) / STEP3;
5020 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5021 if (cond2 is <)
5022 adj = STEP2 - 1;
5023 else
5024 adj = STEP2 + 1;
5025 count2 = (adj + N22 - N21) / STEP2;
5026 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5027 if (cond1 is <)
5028 adj = STEP1 - 1;
5029 else
5030 adj = STEP1 + 1;
5031 count1 = (adj + N12 - N11) / STEP1;
5032 count = count1 * count2 * count3;
5033 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5034 count = 0;
5035 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5036 of the combined loop constructs, just initialize COUNTS array
5037 from the _looptemp_ clauses. */
5039 /* NOTE: It *could* be better to moosh all of the BBs together,
5040 creating one larger BB with all the computation and the unexpected
5041 jump at the end. I.e.
5043 bool zero3, zero2, zero1, zero;
5045 zero3 = N32 c3 N31;
5046 count3 = (N32 - N31) /[cl] STEP3;
5047 zero2 = N22 c2 N21;
5048 count2 = (N22 - N21) /[cl] STEP2;
5049 zero1 = N12 c1 N11;
5050 count1 = (N12 - N11) /[cl] STEP1;
5051 zero = zero3 || zero2 || zero1;
5052 count = count1 * count2 * count3;
5053 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5055 After all, we expect the zero=false, and thus we expect to have to
5056 evaluate all of the comparison expressions, so short-circuiting
5057 oughtn't be a win. Since the condition isn't protecting a
5058 denominator, we're not concerned about divide-by-zero, so we can
5059 fully evaluate count even if a numerator turned out to be wrong.
5061 It seems like putting this all together would create much better
5062 scheduling opportunities, and less pressure on the chip's branch
5063 predictor. */
5065 static void
5066 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5067 basic_block &entry_bb, tree *counts,
5068 basic_block &zero_iter_bb, int &first_zero_iter,
5069 basic_block &l2_dom_bb)
5071 tree t, type = TREE_TYPE (fd->loop.v);
5072 gimple stmt;
5073 edge e, ne;
5074 int i;
5076 /* Collapsed loops need work for expansion into SSA form. */
5077 gcc_assert (!gimple_in_ssa_p (cfun));
5079 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5080 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5082 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5083 isn't supposed to be handled, as the inner loop doesn't
5084 use it. */
5085 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5086 OMP_CLAUSE__LOOPTEMP_);
5087 gcc_assert (innerc);
5088 for (i = 0; i < fd->collapse; i++)
5090 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5091 OMP_CLAUSE__LOOPTEMP_);
5092 gcc_assert (innerc);
5093 if (i)
5094 counts[i] = OMP_CLAUSE_DECL (innerc);
5095 else
5096 counts[0] = NULL_TREE;
5098 return;
5101 for (i = 0; i < fd->collapse; i++)
5103 tree itype = TREE_TYPE (fd->loops[i].v);
5105 if (SSA_VAR_P (fd->loop.n2)
5106 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5107 fold_convert (itype, fd->loops[i].n1),
5108 fold_convert (itype, fd->loops[i].n2)))
5109 == NULL_TREE || !integer_onep (t)))
5111 tree n1, n2;
5112 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5113 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5114 true, GSI_SAME_STMT);
5115 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5116 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5117 true, GSI_SAME_STMT);
5118 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5119 NULL_TREE, NULL_TREE);
5120 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5121 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5122 expand_omp_regimplify_p, NULL, NULL)
5123 || walk_tree (gimple_cond_rhs_ptr (stmt),
5124 expand_omp_regimplify_p, NULL, NULL))
5126 *gsi = gsi_for_stmt (stmt);
5127 gimple_regimplify_operands (stmt, gsi);
5129 e = split_block (entry_bb, stmt);
5130 if (zero_iter_bb == NULL)
5132 first_zero_iter = i;
5133 zero_iter_bb = create_empty_bb (entry_bb);
5134 if (current_loops)
5135 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5136 *gsi = gsi_after_labels (zero_iter_bb);
5137 stmt = gimple_build_assign (fd->loop.n2,
5138 build_zero_cst (type));
5139 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5140 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5141 entry_bb);
5143 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5144 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5145 e->flags = EDGE_TRUE_VALUE;
5146 e->probability = REG_BR_PROB_BASE - ne->probability;
5147 if (l2_dom_bb == NULL)
5148 l2_dom_bb = entry_bb;
5149 entry_bb = e->dest;
5150 *gsi = gsi_last_bb (entry_bb);
5153 if (POINTER_TYPE_P (itype))
5154 itype = signed_type_for (itype);
5155 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5156 ? -1 : 1));
5157 t = fold_build2 (PLUS_EXPR, itype,
5158 fold_convert (itype, fd->loops[i].step), t);
5159 t = fold_build2 (PLUS_EXPR, itype, t,
5160 fold_convert (itype, fd->loops[i].n2));
5161 t = fold_build2 (MINUS_EXPR, itype, t,
5162 fold_convert (itype, fd->loops[i].n1));
5163 /* ?? We could probably use CEIL_DIV_EXPR instead of
5164 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5165 generate the same code in the end because generically we
5166 don't know that the values involved must be negative for
5167 GT?? */
5168 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5169 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5170 fold_build1 (NEGATE_EXPR, itype, t),
5171 fold_build1 (NEGATE_EXPR, itype,
5172 fold_convert (itype,
5173 fd->loops[i].step)));
5174 else
5175 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5176 fold_convert (itype, fd->loops[i].step));
5177 t = fold_convert (type, t);
5178 if (TREE_CODE (t) == INTEGER_CST)
5179 counts[i] = t;
5180 else
5182 counts[i] = create_tmp_reg (type, ".count");
5183 expand_omp_build_assign (gsi, counts[i], t);
5185 if (SSA_VAR_P (fd->loop.n2))
5187 if (i == 0)
5188 t = counts[0];
5189 else
5190 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5191 expand_omp_build_assign (gsi, fd->loop.n2, t);
5197 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5198 T = V;
5199 V3 = N31 + (T % count3) * STEP3;
5200 T = T / count3;
5201 V2 = N21 + (T % count2) * STEP2;
5202 T = T / count2;
5203 V1 = N11 + T * STEP1;
5204 if this loop doesn't have an inner loop construct combined with it.
5205 If it does have an inner loop construct combined with it and the
5206 iteration count isn't known constant, store values from counts array
5207 into its _looptemp_ temporaries instead. */
5209 static void
5210 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5211 tree *counts, gimple inner_stmt, tree startvar)
5213 int i;
5214 if (gimple_omp_for_combined_p (fd->for_stmt))
5216 /* If fd->loop.n2 is constant, then no propagation of the counts
5217 is needed, they are constant. */
5218 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5219 return;
5221 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5222 ? gimple_omp_parallel_clauses (inner_stmt)
5223 : gimple_omp_for_clauses (inner_stmt);
5224 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5225 isn't supposed to be handled, as the inner loop doesn't
5226 use it. */
5227 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5228 gcc_assert (innerc);
5229 for (i = 0; i < fd->collapse; i++)
5231 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5232 OMP_CLAUSE__LOOPTEMP_);
5233 gcc_assert (innerc);
5234 if (i)
5236 tree tem = OMP_CLAUSE_DECL (innerc);
5237 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5238 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5239 false, GSI_CONTINUE_LINKING);
5240 gimple stmt = gimple_build_assign (tem, t);
5241 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5244 return;
5247 tree type = TREE_TYPE (fd->loop.v);
5248 tree tem = create_tmp_reg (type, ".tem");
5249 gimple stmt = gimple_build_assign (tem, startvar);
5250 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5252 for (i = fd->collapse - 1; i >= 0; i--)
5254 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5255 itype = vtype;
5256 if (POINTER_TYPE_P (vtype))
5257 itype = signed_type_for (vtype);
5258 if (i != 0)
5259 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5260 else
5261 t = tem;
5262 t = fold_convert (itype, t);
5263 t = fold_build2 (MULT_EXPR, itype, t,
5264 fold_convert (itype, fd->loops[i].step));
5265 if (POINTER_TYPE_P (vtype))
5266 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5267 else
5268 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5269 t = force_gimple_operand_gsi (gsi, t,
5270 DECL_P (fd->loops[i].v)
5271 && TREE_ADDRESSABLE (fd->loops[i].v),
5272 NULL_TREE, false,
5273 GSI_CONTINUE_LINKING);
5274 stmt = gimple_build_assign (fd->loops[i].v, t);
5275 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5276 if (i != 0)
5278 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5279 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5280 false, GSI_CONTINUE_LINKING);
5281 stmt = gimple_build_assign (tem, t);
5282 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5288 /* Helper function for expand_omp_for_*. Generate code like:
5289 L10:
5290 V3 += STEP3;
5291 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5292 L11:
5293 V3 = N31;
5294 V2 += STEP2;
5295 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5296 L12:
5297 V2 = N21;
5298 V1 += STEP1;
5299 goto BODY_BB; */
5301 static basic_block
5302 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5303 basic_block body_bb)
5305 basic_block last_bb, bb, collapse_bb = NULL;
5306 int i;
5307 gimple_stmt_iterator gsi;
5308 edge e;
5309 tree t;
5310 gimple stmt;
5312 last_bb = cont_bb;
5313 for (i = fd->collapse - 1; i >= 0; i--)
5315 tree vtype = TREE_TYPE (fd->loops[i].v);
5317 bb = create_empty_bb (last_bb);
5318 if (current_loops)
5319 add_bb_to_loop (bb, last_bb->loop_father);
5320 gsi = gsi_start_bb (bb);
5322 if (i < fd->collapse - 1)
5324 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5325 e->probability = REG_BR_PROB_BASE / 8;
5327 t = fd->loops[i + 1].n1;
5328 t = force_gimple_operand_gsi (&gsi, t,
5329 DECL_P (fd->loops[i + 1].v)
5330 && TREE_ADDRESSABLE (fd->loops[i
5331 + 1].v),
5332 NULL_TREE, false,
5333 GSI_CONTINUE_LINKING);
5334 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5335 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5337 else
5338 collapse_bb = bb;
5340 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5342 if (POINTER_TYPE_P (vtype))
5343 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5344 else
5345 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5346 t = force_gimple_operand_gsi (&gsi, t,
5347 DECL_P (fd->loops[i].v)
5348 && TREE_ADDRESSABLE (fd->loops[i].v),
5349 NULL_TREE, false, GSI_CONTINUE_LINKING);
5350 stmt = gimple_build_assign (fd->loops[i].v, t);
5351 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5353 if (i > 0)
5355 t = fd->loops[i].n2;
5356 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5357 false, GSI_CONTINUE_LINKING);
5358 tree v = fd->loops[i].v;
5359 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5360 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5361 false, GSI_CONTINUE_LINKING);
5362 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5363 stmt = gimple_build_cond_empty (t);
5364 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5365 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5366 e->probability = REG_BR_PROB_BASE * 7 / 8;
5368 else
5369 make_edge (bb, body_bb, EDGE_FALLTHRU);
5370 last_bb = bb;
5373 return collapse_bb;
5377 /* A subroutine of expand_omp_for. Generate code for a parallel
5378 loop with any schedule. Given parameters:
5380 for (V = N1; V cond N2; V += STEP) BODY;
5382 where COND is "<" or ">", we generate pseudocode
5384 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5385 if (more) goto L0; else goto L3;
5387 V = istart0;
5388 iend = iend0;
5390 BODY;
5391 V += STEP;
5392 if (V cond iend) goto L1; else goto L2;
5394 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5397 If this is a combined omp parallel loop, instead of the call to
5398 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5399 If this is gimple_omp_for_combined_p loop, then instead of assigning
5400 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5401 inner GIMPLE_OMP_FOR and V += STEP; and
5402 if (V cond iend) goto L1; else goto L2; are removed.
5404 For collapsed loops, given parameters:
5405 collapse(3)
5406 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5407 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5408 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5409 BODY;
5411 we generate pseudocode
5413 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5414 if (cond3 is <)
5415 adj = STEP3 - 1;
5416 else
5417 adj = STEP3 + 1;
5418 count3 = (adj + N32 - N31) / STEP3;
5419 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5420 if (cond2 is <)
5421 adj = STEP2 - 1;
5422 else
5423 adj = STEP2 + 1;
5424 count2 = (adj + N22 - N21) / STEP2;
5425 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5426 if (cond1 is <)
5427 adj = STEP1 - 1;
5428 else
5429 adj = STEP1 + 1;
5430 count1 = (adj + N12 - N11) / STEP1;
5431 count = count1 * count2 * count3;
5432 goto Z1;
5434 count = 0;
5436 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5437 if (more) goto L0; else goto L3;
5439 V = istart0;
5440 T = V;
5441 V3 = N31 + (T % count3) * STEP3;
5442 T = T / count3;
5443 V2 = N21 + (T % count2) * STEP2;
5444 T = T / count2;
5445 V1 = N11 + T * STEP1;
5446 iend = iend0;
5448 BODY;
5449 V += 1;
5450 if (V < iend) goto L10; else goto L2;
5451 L10:
5452 V3 += STEP3;
5453 if (V3 cond3 N32) goto L1; else goto L11;
5454 L11:
5455 V3 = N31;
5456 V2 += STEP2;
5457 if (V2 cond2 N22) goto L1; else goto L12;
5458 L12:
5459 V2 = N21;
5460 V1 += STEP1;
5461 goto L1;
5463 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5468 static void
5469 expand_omp_for_generic (struct omp_region *region,
5470 struct omp_for_data *fd,
5471 enum built_in_function start_fn,
5472 enum built_in_function next_fn,
5473 gimple inner_stmt)
5475 tree type, istart0, iend0, iend;
5476 tree t, vmain, vback, bias = NULL_TREE;
5477 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5478 basic_block l2_bb = NULL, l3_bb = NULL;
5479 gimple_stmt_iterator gsi;
5480 gimple stmt;
5481 bool in_combined_parallel = is_combined_parallel (region);
5482 bool broken_loop = region->cont == NULL;
5483 edge e, ne;
5484 tree *counts = NULL;
5485 int i;
5487 gcc_assert (!broken_loop || !in_combined_parallel);
5488 gcc_assert (fd->iter_type == long_integer_type_node
5489 || !in_combined_parallel);
5491 type = TREE_TYPE (fd->loop.v);
5492 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5493 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5494 TREE_ADDRESSABLE (istart0) = 1;
5495 TREE_ADDRESSABLE (iend0) = 1;
5497 /* See if we need to bias by LLONG_MIN. */
5498 if (fd->iter_type == long_long_unsigned_type_node
5499 && TREE_CODE (type) == INTEGER_TYPE
5500 && !TYPE_UNSIGNED (type))
5502 tree n1, n2;
5504 if (fd->loop.cond_code == LT_EXPR)
5506 n1 = fd->loop.n1;
5507 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5509 else
5511 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5512 n2 = fd->loop.n1;
5514 if (TREE_CODE (n1) != INTEGER_CST
5515 || TREE_CODE (n2) != INTEGER_CST
5516 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5517 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5520 entry_bb = region->entry;
5521 cont_bb = region->cont;
5522 collapse_bb = NULL;
5523 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5524 gcc_assert (broken_loop
5525 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5526 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5527 l1_bb = single_succ (l0_bb);
5528 if (!broken_loop)
5530 l2_bb = create_empty_bb (cont_bb);
5531 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5532 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5534 else
5535 l2_bb = NULL;
5536 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5537 exit_bb = region->exit;
5539 gsi = gsi_last_bb (entry_bb);
5541 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5542 if (fd->collapse > 1)
5544 int first_zero_iter = -1;
5545 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5547 counts = XALLOCAVEC (tree, fd->collapse);
5548 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5549 zero_iter_bb, first_zero_iter,
5550 l2_dom_bb);
5552 if (zero_iter_bb)
5554 /* Some counts[i] vars might be uninitialized if
5555 some loop has zero iterations. But the body shouldn't
5556 be executed in that case, so just avoid uninit warnings. */
5557 for (i = first_zero_iter; i < fd->collapse; i++)
5558 if (SSA_VAR_P (counts[i]))
5559 TREE_NO_WARNING (counts[i]) = 1;
5560 gsi_prev (&gsi);
5561 e = split_block (entry_bb, gsi_stmt (gsi));
5562 entry_bb = e->dest;
5563 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5564 gsi = gsi_last_bb (entry_bb);
5565 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5566 get_immediate_dominator (CDI_DOMINATORS,
5567 zero_iter_bb));
5570 if (in_combined_parallel)
5572 /* In a combined parallel loop, emit a call to
5573 GOMP_loop_foo_next. */
5574 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5575 build_fold_addr_expr (istart0),
5576 build_fold_addr_expr (iend0));
5578 else
5580 tree t0, t1, t2, t3, t4;
5581 /* If this is not a combined parallel loop, emit a call to
5582 GOMP_loop_foo_start in ENTRY_BB. */
5583 t4 = build_fold_addr_expr (iend0);
5584 t3 = build_fold_addr_expr (istart0);
5585 t2 = fold_convert (fd->iter_type, fd->loop.step);
5586 t1 = fd->loop.n2;
5587 t0 = fd->loop.n1;
5588 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5590 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5591 OMP_CLAUSE__LOOPTEMP_);
5592 gcc_assert (innerc);
5593 t0 = OMP_CLAUSE_DECL (innerc);
5594 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5595 OMP_CLAUSE__LOOPTEMP_);
5596 gcc_assert (innerc);
5597 t1 = OMP_CLAUSE_DECL (innerc);
5599 if (POINTER_TYPE_P (TREE_TYPE (t0))
5600 && TYPE_PRECISION (TREE_TYPE (t0))
5601 != TYPE_PRECISION (fd->iter_type))
5603 /* Avoid casting pointers to integer of a different size. */
5604 tree itype = signed_type_for (type);
5605 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5606 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5608 else
5610 t1 = fold_convert (fd->iter_type, t1);
5611 t0 = fold_convert (fd->iter_type, t0);
5613 if (bias)
5615 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5616 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5618 if (fd->iter_type == long_integer_type_node)
5620 if (fd->chunk_size)
5622 t = fold_convert (fd->iter_type, fd->chunk_size);
5623 t = build_call_expr (builtin_decl_explicit (start_fn),
5624 6, t0, t1, t2, t, t3, t4);
5626 else
5627 t = build_call_expr (builtin_decl_explicit (start_fn),
5628 5, t0, t1, t2, t3, t4);
5630 else
5632 tree t5;
5633 tree c_bool_type;
5634 tree bfn_decl;
5636 /* The GOMP_loop_ull_*start functions have additional boolean
5637 argument, true for < loops and false for > loops.
5638 In Fortran, the C bool type can be different from
5639 boolean_type_node. */
5640 bfn_decl = builtin_decl_explicit (start_fn);
5641 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5642 t5 = build_int_cst (c_bool_type,
5643 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5644 if (fd->chunk_size)
5646 tree bfn_decl = builtin_decl_explicit (start_fn);
5647 t = fold_convert (fd->iter_type, fd->chunk_size);
5648 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5650 else
5651 t = build_call_expr (builtin_decl_explicit (start_fn),
5652 6, t5, t0, t1, t2, t3, t4);
5655 if (TREE_TYPE (t) != boolean_type_node)
5656 t = fold_build2 (NE_EXPR, boolean_type_node,
5657 t, build_int_cst (TREE_TYPE (t), 0));
5658 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5659 true, GSI_SAME_STMT);
5660 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5662 /* Remove the GIMPLE_OMP_FOR statement. */
5663 gsi_remove (&gsi, true);
5665 /* Iteration setup for sequential loop goes in L0_BB. */
5666 tree startvar = fd->loop.v;
5667 tree endvar = NULL_TREE;
5669 if (gimple_omp_for_combined_p (fd->for_stmt))
5671 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5672 && gimple_omp_for_kind (inner_stmt)
5673 == GF_OMP_FOR_KIND_SIMD);
5674 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5675 OMP_CLAUSE__LOOPTEMP_);
5676 gcc_assert (innerc);
5677 startvar = OMP_CLAUSE_DECL (innerc);
5678 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5679 OMP_CLAUSE__LOOPTEMP_);
5680 gcc_assert (innerc);
5681 endvar = OMP_CLAUSE_DECL (innerc);
5684 gsi = gsi_start_bb (l0_bb);
5685 t = istart0;
5686 if (bias)
5687 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5688 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5689 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5690 t = fold_convert (TREE_TYPE (startvar), t);
5691 t = force_gimple_operand_gsi (&gsi, t,
5692 DECL_P (startvar)
5693 && TREE_ADDRESSABLE (startvar),
5694 NULL_TREE, false, GSI_CONTINUE_LINKING);
5695 stmt = gimple_build_assign (startvar, t);
5696 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5698 t = iend0;
5699 if (bias)
5700 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5701 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5702 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5703 t = fold_convert (TREE_TYPE (startvar), t);
5704 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5705 false, GSI_CONTINUE_LINKING);
5706 if (endvar)
5708 stmt = gimple_build_assign (endvar, iend);
5709 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5710 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
5711 stmt = gimple_build_assign (fd->loop.v, iend);
5712 else
5713 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend,
5714 NULL_TREE);
5715 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5717 if (fd->collapse > 1)
5718 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5720 if (!broken_loop)
5722 /* Code to control the increment and predicate for the sequential
5723 loop goes in the CONT_BB. */
5724 gsi = gsi_last_bb (cont_bb);
5725 stmt = gsi_stmt (gsi);
5726 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5727 vmain = gimple_omp_continue_control_use (stmt);
5728 vback = gimple_omp_continue_control_def (stmt);
5730 if (!gimple_omp_for_combined_p (fd->for_stmt))
5732 if (POINTER_TYPE_P (type))
5733 t = fold_build_pointer_plus (vmain, fd->loop.step);
5734 else
5735 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5736 t = force_gimple_operand_gsi (&gsi, t,
5737 DECL_P (vback)
5738 && TREE_ADDRESSABLE (vback),
5739 NULL_TREE, true, GSI_SAME_STMT);
5740 stmt = gimple_build_assign (vback, t);
5741 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5743 t = build2 (fd->loop.cond_code, boolean_type_node,
5744 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5745 iend);
5746 stmt = gimple_build_cond_empty (t);
5747 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5750 /* Remove GIMPLE_OMP_CONTINUE. */
5751 gsi_remove (&gsi, true);
5753 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5754 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5756 /* Emit code to get the next parallel iteration in L2_BB. */
5757 gsi = gsi_start_bb (l2_bb);
5759 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5760 build_fold_addr_expr (istart0),
5761 build_fold_addr_expr (iend0));
5762 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5763 false, GSI_CONTINUE_LINKING);
5764 if (TREE_TYPE (t) != boolean_type_node)
5765 t = fold_build2 (NE_EXPR, boolean_type_node,
5766 t, build_int_cst (TREE_TYPE (t), 0));
5767 stmt = gimple_build_cond_empty (t);
5768 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5771 /* Add the loop cleanup function. */
5772 gsi = gsi_last_bb (exit_bb);
5773 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5774 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5775 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5776 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5777 else
5778 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5779 stmt = gimple_build_call (t, 0);
5780 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5781 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5782 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5783 gsi_remove (&gsi, true);
5785 /* Connect the new blocks. */
5786 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5787 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5789 if (!broken_loop)
5791 gimple_seq phis;
5793 e = find_edge (cont_bb, l3_bb);
5794 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5796 phis = phi_nodes (l3_bb);
5797 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5799 gimple phi = gsi_stmt (gsi);
5800 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5801 PHI_ARG_DEF_FROM_EDGE (phi, e));
5803 remove_edge (e);
5805 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5806 if (current_loops)
5807 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5808 e = find_edge (cont_bb, l1_bb);
5809 if (gimple_omp_for_combined_p (fd->for_stmt))
5811 remove_edge (e);
5812 e = NULL;
5814 else if (fd->collapse > 1)
5816 remove_edge (e);
5817 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5819 else
5820 e->flags = EDGE_TRUE_VALUE;
5821 if (e)
5823 e->probability = REG_BR_PROB_BASE * 7 / 8;
5824 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5826 else
5828 e = find_edge (cont_bb, l2_bb);
5829 e->flags = EDGE_FALLTHRU;
5831 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5833 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5834 recompute_dominator (CDI_DOMINATORS, l2_bb));
5835 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5836 recompute_dominator (CDI_DOMINATORS, l3_bb));
5837 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5838 recompute_dominator (CDI_DOMINATORS, l0_bb));
5839 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5840 recompute_dominator (CDI_DOMINATORS, l1_bb));
5842 struct loop *outer_loop = alloc_loop ();
5843 outer_loop->header = l0_bb;
5844 outer_loop->latch = l2_bb;
5845 add_loop (outer_loop, l0_bb->loop_father);
5847 if (!gimple_omp_for_combined_p (fd->for_stmt))
5849 struct loop *loop = alloc_loop ();
5850 loop->header = l1_bb;
5851 /* The loop may have multiple latches. */
5852 add_loop (loop, outer_loop);
5858 /* A subroutine of expand_omp_for. Generate code for a parallel
5859 loop with static schedule and no specified chunk size. Given
5860 parameters:
5862 for (V = N1; V cond N2; V += STEP) BODY;
5864 where COND is "<" or ">", we generate pseudocode
5866 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5867 if (cond is <)
5868 adj = STEP - 1;
5869 else
5870 adj = STEP + 1;
5871 if ((__typeof (V)) -1 > 0 && cond is >)
5872 n = -(adj + N2 - N1) / -STEP;
5873 else
5874 n = (adj + N2 - N1) / STEP;
5875 q = n / nthreads;
5876 tt = n % nthreads;
5877 if (threadid < tt) goto L3; else goto L4;
5879 tt = 0;
5880 q = q + 1;
5882 s0 = q * threadid + tt;
5883 e0 = s0 + q;
5884 V = s0 * STEP + N1;
5885 if (s0 >= e0) goto L2; else goto L0;
5887 e = e0 * STEP + N1;
5889 BODY;
5890 V += STEP;
5891 if (V cond e) goto L1;
5895 static void
5896 expand_omp_for_static_nochunk (struct omp_region *region,
5897 struct omp_for_data *fd,
5898 gimple inner_stmt)
5900 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
5901 tree type, itype, vmain, vback;
5902 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
5903 basic_block body_bb, cont_bb, collapse_bb = NULL;
5904 basic_block fin_bb;
5905 gimple_stmt_iterator gsi;
5906 gimple stmt;
5907 edge ep;
5908 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
5909 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
5910 bool broken_loop = region->cont == NULL;
5911 tree *counts = NULL;
5912 tree n1, n2, step;
5914 itype = type = TREE_TYPE (fd->loop.v);
5915 if (POINTER_TYPE_P (type))
5916 itype = signed_type_for (type);
5918 entry_bb = region->entry;
5919 cont_bb = region->cont;
5920 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5921 fin_bb = BRANCH_EDGE (entry_bb)->dest;
5922 gcc_assert (broken_loop
5923 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
5924 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5925 body_bb = single_succ (seq_start_bb);
5926 if (!broken_loop)
5928 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
5929 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5931 exit_bb = region->exit;
5933 /* Iteration space partitioning goes in ENTRY_BB. */
5934 gsi = gsi_last_bb (entry_bb);
5935 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5937 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
5939 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
5940 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
5943 if (fd->collapse > 1)
5945 int first_zero_iter = -1;
5946 basic_block l2_dom_bb = NULL;
5948 counts = XALLOCAVEC (tree, fd->collapse);
5949 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5950 fin_bb, first_zero_iter,
5951 l2_dom_bb);
5952 t = NULL_TREE;
5954 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
5955 t = integer_one_node;
5956 else
5957 t = fold_binary (fd->loop.cond_code, boolean_type_node,
5958 fold_convert (type, fd->loop.n1),
5959 fold_convert (type, fd->loop.n2));
5960 if (fd->collapse == 1
5961 && TYPE_UNSIGNED (type)
5962 && (t == NULL_TREE || !integer_onep (t)))
5964 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5965 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5966 true, GSI_SAME_STMT);
5967 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5968 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5969 true, GSI_SAME_STMT);
5970 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
5971 NULL_TREE, NULL_TREE);
5972 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5973 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5974 expand_omp_regimplify_p, NULL, NULL)
5975 || walk_tree (gimple_cond_rhs_ptr (stmt),
5976 expand_omp_regimplify_p, NULL, NULL))
5978 gsi = gsi_for_stmt (stmt);
5979 gimple_regimplify_operands (stmt, &gsi);
5981 ep = split_block (entry_bb, stmt);
5982 ep->flags = EDGE_TRUE_VALUE;
5983 entry_bb = ep->dest;
5984 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
5985 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
5986 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
5987 if (gimple_in_ssa_p (cfun))
5989 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
5990 for (gsi = gsi_start_phis (fin_bb);
5991 !gsi_end_p (gsi); gsi_next (&gsi))
5993 gimple phi = gsi_stmt (gsi);
5994 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
5995 ep, UNKNOWN_LOCATION);
5998 gsi = gsi_last_bb (entry_bb);
6001 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6002 t = fold_convert (itype, t);
6003 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6004 true, GSI_SAME_STMT);
6006 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6007 t = fold_convert (itype, t);
6008 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6009 true, GSI_SAME_STMT);
6011 n1 = fd->loop.n1;
6012 n2 = fd->loop.n2;
6013 step = fd->loop.step;
6014 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6016 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6017 OMP_CLAUSE__LOOPTEMP_);
6018 gcc_assert (innerc);
6019 n1 = OMP_CLAUSE_DECL (innerc);
6020 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6021 OMP_CLAUSE__LOOPTEMP_);
6022 gcc_assert (innerc);
6023 n2 = OMP_CLAUSE_DECL (innerc);
6025 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6026 true, NULL_TREE, true, GSI_SAME_STMT);
6027 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6028 true, NULL_TREE, true, GSI_SAME_STMT);
6029 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6030 true, NULL_TREE, true, GSI_SAME_STMT);
6032 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6033 t = fold_build2 (PLUS_EXPR, itype, step, t);
6034 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6035 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6036 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6037 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6038 fold_build1 (NEGATE_EXPR, itype, t),
6039 fold_build1 (NEGATE_EXPR, itype, step));
6040 else
6041 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6042 t = fold_convert (itype, t);
6043 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6045 q = create_tmp_reg (itype, "q");
6046 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6047 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6048 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6050 tt = create_tmp_reg (itype, "tt");
6051 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6052 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6053 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6055 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6056 stmt = gimple_build_cond_empty (t);
6057 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6059 second_bb = split_block (entry_bb, stmt)->dest;
6060 gsi = gsi_last_bb (second_bb);
6061 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6063 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6064 GSI_SAME_STMT);
6065 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
6066 build_int_cst (itype, 1));
6067 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6069 third_bb = split_block (second_bb, stmt)->dest;
6070 gsi = gsi_last_bb (third_bb);
6071 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6073 t = build2 (MULT_EXPR, itype, q, threadid);
6074 t = build2 (PLUS_EXPR, itype, t, tt);
6075 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6077 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6078 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6080 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6081 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6083 /* Remove the GIMPLE_OMP_FOR statement. */
6084 gsi_remove (&gsi, true);
6086 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6087 gsi = gsi_start_bb (seq_start_bb);
6089 tree startvar = fd->loop.v;
6090 tree endvar = NULL_TREE;
6092 if (gimple_omp_for_combined_p (fd->for_stmt))
6094 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6095 ? gimple_omp_parallel_clauses (inner_stmt)
6096 : gimple_omp_for_clauses (inner_stmt);
6097 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6098 gcc_assert (innerc);
6099 startvar = OMP_CLAUSE_DECL (innerc);
6100 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6101 OMP_CLAUSE__LOOPTEMP_);
6102 gcc_assert (innerc);
6103 endvar = OMP_CLAUSE_DECL (innerc);
6105 t = fold_convert (itype, s0);
6106 t = fold_build2 (MULT_EXPR, itype, t, step);
6107 if (POINTER_TYPE_P (type))
6108 t = fold_build_pointer_plus (n1, t);
6109 else
6110 t = fold_build2 (PLUS_EXPR, type, t, n1);
6111 t = fold_convert (TREE_TYPE (startvar), t);
6112 t = force_gimple_operand_gsi (&gsi, t,
6113 DECL_P (startvar)
6114 && TREE_ADDRESSABLE (startvar),
6115 NULL_TREE, false, GSI_CONTINUE_LINKING);
6116 stmt = gimple_build_assign (startvar, t);
6117 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6119 t = fold_convert (itype, e0);
6120 t = fold_build2 (MULT_EXPR, itype, t, step);
6121 if (POINTER_TYPE_P (type))
6122 t = fold_build_pointer_plus (n1, t);
6123 else
6124 t = fold_build2 (PLUS_EXPR, type, t, n1);
6125 t = fold_convert (TREE_TYPE (startvar), t);
6126 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6127 false, GSI_CONTINUE_LINKING);
6128 if (endvar)
6130 stmt = gimple_build_assign (endvar, e);
6131 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6132 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6133 stmt = gimple_build_assign (fd->loop.v, e);
6134 else
6135 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6136 NULL_TREE);
6137 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6139 if (fd->collapse > 1)
6140 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6142 if (!broken_loop)
6144 /* The code controlling the sequential loop replaces the
6145 GIMPLE_OMP_CONTINUE. */
6146 gsi = gsi_last_bb (cont_bb);
6147 stmt = gsi_stmt (gsi);
6148 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6149 vmain = gimple_omp_continue_control_use (stmt);
6150 vback = gimple_omp_continue_control_def (stmt);
6152 if (!gimple_omp_for_combined_p (fd->for_stmt))
6154 if (POINTER_TYPE_P (type))
6155 t = fold_build_pointer_plus (vmain, step);
6156 else
6157 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6158 t = force_gimple_operand_gsi (&gsi, t,
6159 DECL_P (vback)
6160 && TREE_ADDRESSABLE (vback),
6161 NULL_TREE, true, GSI_SAME_STMT);
6162 stmt = gimple_build_assign (vback, t);
6163 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6165 t = build2 (fd->loop.cond_code, boolean_type_node,
6166 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6167 ? t : vback, e);
6168 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6171 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6172 gsi_remove (&gsi, true);
6174 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6175 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6178 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6179 gsi = gsi_last_bb (exit_bb);
6180 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6182 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6183 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6185 gsi_remove (&gsi, true);
6187 /* Connect all the blocks. */
6188 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6189 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6190 ep = find_edge (entry_bb, second_bb);
6191 ep->flags = EDGE_TRUE_VALUE;
6192 ep->probability = REG_BR_PROB_BASE / 4;
6193 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6194 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6196 if (!broken_loop)
6198 ep = find_edge (cont_bb, body_bb);
6199 if (gimple_omp_for_combined_p (fd->for_stmt))
6201 remove_edge (ep);
6202 ep = NULL;
6204 else if (fd->collapse > 1)
6206 remove_edge (ep);
6207 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6209 else
6210 ep->flags = EDGE_TRUE_VALUE;
6211 find_edge (cont_bb, fin_bb)->flags
6212 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6215 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6216 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6217 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6219 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6220 recompute_dominator (CDI_DOMINATORS, body_bb));
6221 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6222 recompute_dominator (CDI_DOMINATORS, fin_bb));
6224 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6226 struct loop *loop = alloc_loop ();
6227 loop->header = body_bb;
6228 if (collapse_bb == NULL)
6229 loop->latch = cont_bb;
6230 add_loop (loop, body_bb->loop_father);
6235 /* A subroutine of expand_omp_for. Generate code for a parallel
6236 loop with static schedule and a specified chunk size. Given
6237 parameters:
6239 for (V = N1; V cond N2; V += STEP) BODY;
6241 where COND is "<" or ">", we generate pseudocode
6243 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6244 if (cond is <)
6245 adj = STEP - 1;
6246 else
6247 adj = STEP + 1;
6248 if ((__typeof (V)) -1 > 0 && cond is >)
6249 n = -(adj + N2 - N1) / -STEP;
6250 else
6251 n = (adj + N2 - N1) / STEP;
6252 trip = 0;
6253 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6254 here so that V is defined
6255 if the loop is not entered
6257 s0 = (trip * nthreads + threadid) * CHUNK;
6258 e0 = min(s0 + CHUNK, n);
6259 if (s0 < n) goto L1; else goto L4;
6261 V = s0 * STEP + N1;
6262 e = e0 * STEP + N1;
6264 BODY;
6265 V += STEP;
6266 if (V cond e) goto L2; else goto L3;
6268 trip += 1;
6269 goto L0;
6273 static void
6274 expand_omp_for_static_chunk (struct omp_region *region,
6275 struct omp_for_data *fd, gimple inner_stmt)
6277 tree n, s0, e0, e, t;
6278 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6279 tree type, itype, v_main, v_back, v_extra;
6280 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6281 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6282 gimple_stmt_iterator si;
6283 gimple stmt;
6284 edge se;
6285 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6286 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6287 bool broken_loop = region->cont == NULL;
6288 tree *counts = NULL;
6289 tree n1, n2, step;
6291 itype = type = TREE_TYPE (fd->loop.v);
6292 if (POINTER_TYPE_P (type))
6293 itype = signed_type_for (type);
6295 entry_bb = region->entry;
6296 se = split_block (entry_bb, last_stmt (entry_bb));
6297 entry_bb = se->src;
6298 iter_part_bb = se->dest;
6299 cont_bb = region->cont;
6300 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6301 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6302 gcc_assert (broken_loop
6303 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6304 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6305 body_bb = single_succ (seq_start_bb);
6306 if (!broken_loop)
6308 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6309 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6310 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6312 exit_bb = region->exit;
6314 /* Trip and adjustment setup goes in ENTRY_BB. */
6315 si = gsi_last_bb (entry_bb);
6316 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
6318 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6320 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6321 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6324 if (fd->collapse > 1)
6326 int first_zero_iter = -1;
6327 basic_block l2_dom_bb = NULL;
6329 counts = XALLOCAVEC (tree, fd->collapse);
6330 expand_omp_for_init_counts (fd, &si, entry_bb, counts,
6331 fin_bb, first_zero_iter,
6332 l2_dom_bb);
6333 t = NULL_TREE;
6335 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6336 t = integer_one_node;
6337 else
6338 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6339 fold_convert (type, fd->loop.n1),
6340 fold_convert (type, fd->loop.n2));
6341 if (fd->collapse == 1
6342 && TYPE_UNSIGNED (type)
6343 && (t == NULL_TREE || !integer_onep (t)))
6345 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6346 n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
6347 true, GSI_SAME_STMT);
6348 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6349 n2 = force_gimple_operand_gsi (&si, n2, true, NULL_TREE,
6350 true, GSI_SAME_STMT);
6351 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6352 NULL_TREE, NULL_TREE);
6353 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6354 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6355 expand_omp_regimplify_p, NULL, NULL)
6356 || walk_tree (gimple_cond_rhs_ptr (stmt),
6357 expand_omp_regimplify_p, NULL, NULL))
6359 si = gsi_for_stmt (stmt);
6360 gimple_regimplify_operands (stmt, &si);
6362 se = split_block (entry_bb, stmt);
6363 se->flags = EDGE_TRUE_VALUE;
6364 entry_bb = se->dest;
6365 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6366 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6367 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6368 if (gimple_in_ssa_p (cfun))
6370 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6371 for (si = gsi_start_phis (fin_bb);
6372 !gsi_end_p (si); gsi_next (&si))
6374 gimple phi = gsi_stmt (si);
6375 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6376 se, UNKNOWN_LOCATION);
6379 si = gsi_last_bb (entry_bb);
6382 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6383 t = fold_convert (itype, t);
6384 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6385 true, GSI_SAME_STMT);
6387 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6388 t = fold_convert (itype, t);
6389 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6390 true, GSI_SAME_STMT);
6392 n1 = fd->loop.n1;
6393 n2 = fd->loop.n2;
6394 step = fd->loop.step;
6395 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6397 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6398 OMP_CLAUSE__LOOPTEMP_);
6399 gcc_assert (innerc);
6400 n1 = OMP_CLAUSE_DECL (innerc);
6401 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6402 OMP_CLAUSE__LOOPTEMP_);
6403 gcc_assert (innerc);
6404 n2 = OMP_CLAUSE_DECL (innerc);
6406 n1 = force_gimple_operand_gsi (&si, fold_convert (type, n1),
6407 true, NULL_TREE, true, GSI_SAME_STMT);
6408 n2 = force_gimple_operand_gsi (&si, fold_convert (itype, n2),
6409 true, NULL_TREE, true, GSI_SAME_STMT);
6410 step = force_gimple_operand_gsi (&si, fold_convert (itype, step),
6411 true, NULL_TREE, true, GSI_SAME_STMT);
6412 fd->chunk_size
6413 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
6414 true, NULL_TREE, true, GSI_SAME_STMT);
6416 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6417 t = fold_build2 (PLUS_EXPR, itype, step, t);
6418 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6419 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6420 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6421 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6422 fold_build1 (NEGATE_EXPR, itype, t),
6423 fold_build1 (NEGATE_EXPR, itype, step));
6424 else
6425 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6426 t = fold_convert (itype, t);
6427 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6428 true, GSI_SAME_STMT);
6430 trip_var = create_tmp_reg (itype, ".trip");
6431 if (gimple_in_ssa_p (cfun))
6433 trip_init = make_ssa_name (trip_var, NULL);
6434 trip_main = make_ssa_name (trip_var, NULL);
6435 trip_back = make_ssa_name (trip_var, NULL);
6437 else
6439 trip_init = trip_var;
6440 trip_main = trip_var;
6441 trip_back = trip_var;
6444 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6445 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6447 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6448 t = fold_build2 (MULT_EXPR, itype, t, step);
6449 if (POINTER_TYPE_P (type))
6450 t = fold_build_pointer_plus (n1, t);
6451 else
6452 t = fold_build2 (PLUS_EXPR, type, t, n1);
6453 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6454 true, GSI_SAME_STMT);
6456 /* Remove the GIMPLE_OMP_FOR. */
6457 gsi_remove (&si, true);
6459 /* Iteration space partitioning goes in ITER_PART_BB. */
6460 si = gsi_last_bb (iter_part_bb);
6462 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6463 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6464 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6465 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6466 false, GSI_CONTINUE_LINKING);
6468 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6469 t = fold_build2 (MIN_EXPR, itype, t, n);
6470 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6471 false, GSI_CONTINUE_LINKING);
6473 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6474 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6476 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6477 si = gsi_start_bb (seq_start_bb);
6479 tree startvar = fd->loop.v;
6480 tree endvar = NULL_TREE;
6482 if (gimple_omp_for_combined_p (fd->for_stmt))
6484 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6485 ? gimple_omp_parallel_clauses (inner_stmt)
6486 : gimple_omp_for_clauses (inner_stmt);
6487 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6488 gcc_assert (innerc);
6489 startvar = OMP_CLAUSE_DECL (innerc);
6490 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6491 OMP_CLAUSE__LOOPTEMP_);
6492 gcc_assert (innerc);
6493 endvar = OMP_CLAUSE_DECL (innerc);
6496 t = fold_convert (itype, s0);
6497 t = fold_build2 (MULT_EXPR, itype, t, step);
6498 if (POINTER_TYPE_P (type))
6499 t = fold_build_pointer_plus (n1, t);
6500 else
6501 t = fold_build2 (PLUS_EXPR, type, t, n1);
6502 t = fold_convert (TREE_TYPE (startvar), t);
6503 t = force_gimple_operand_gsi (&si, t,
6504 DECL_P (startvar)
6505 && TREE_ADDRESSABLE (startvar),
6506 NULL_TREE, false, GSI_CONTINUE_LINKING);
6507 stmt = gimple_build_assign (startvar, t);
6508 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6510 t = fold_convert (itype, e0);
6511 t = fold_build2 (MULT_EXPR, itype, t, step);
6512 if (POINTER_TYPE_P (type))
6513 t = fold_build_pointer_plus (n1, t);
6514 else
6515 t = fold_build2 (PLUS_EXPR, type, t, n1);
6516 t = fold_convert (TREE_TYPE (startvar), t);
6517 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6518 false, GSI_CONTINUE_LINKING);
6519 if (endvar)
6521 stmt = gimple_build_assign (endvar, e);
6522 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6523 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6524 stmt = gimple_build_assign (fd->loop.v, e);
6525 else
6526 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6527 NULL_TREE);
6528 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6530 if (fd->collapse > 1)
6531 expand_omp_for_init_vars (fd, &si, counts, inner_stmt, startvar);
6533 if (!broken_loop)
6535 /* The code controlling the sequential loop goes in CONT_BB,
6536 replacing the GIMPLE_OMP_CONTINUE. */
6537 si = gsi_last_bb (cont_bb);
6538 stmt = gsi_stmt (si);
6539 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6540 v_main = gimple_omp_continue_control_use (stmt);
6541 v_back = gimple_omp_continue_control_def (stmt);
6543 if (!gimple_omp_for_combined_p (fd->for_stmt))
6545 if (POINTER_TYPE_P (type))
6546 t = fold_build_pointer_plus (v_main, step);
6547 else
6548 t = fold_build2 (PLUS_EXPR, type, v_main, step);
6549 if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
6550 t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6551 true, GSI_SAME_STMT);
6552 stmt = gimple_build_assign (v_back, t);
6553 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6555 t = build2 (fd->loop.cond_code, boolean_type_node,
6556 DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
6557 ? t : v_back, e);
6558 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
6561 /* Remove GIMPLE_OMP_CONTINUE. */
6562 gsi_remove (&si, true);
6564 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6565 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6567 /* Trip update code goes into TRIP_UPDATE_BB. */
6568 si = gsi_start_bb (trip_update_bb);
6570 t = build_int_cst (itype, 1);
6571 t = build2 (PLUS_EXPR, itype, trip_main, t);
6572 stmt = gimple_build_assign (trip_back, t);
6573 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6576 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6577 si = gsi_last_bb (exit_bb);
6578 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
6580 t = gimple_omp_return_lhs (gsi_stmt (si));
6581 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
6583 gsi_remove (&si, true);
6585 /* Connect the new blocks. */
6586 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6587 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6589 if (!broken_loop)
6591 se = find_edge (cont_bb, body_bb);
6592 if (gimple_omp_for_combined_p (fd->for_stmt))
6594 remove_edge (se);
6595 se = NULL;
6597 else if (fd->collapse > 1)
6599 remove_edge (se);
6600 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6602 else
6603 se->flags = EDGE_TRUE_VALUE;
6604 find_edge (cont_bb, trip_update_bb)->flags
6605 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6607 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6610 if (gimple_in_ssa_p (cfun))
6612 gimple_stmt_iterator psi;
6613 gimple phi;
6614 edge re, ene;
6615 edge_var_map_vector *head;
6616 edge_var_map *vm;
6617 size_t i;
6619 gcc_assert (fd->collapse == 1 && !broken_loop);
6621 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6622 remove arguments of the phi nodes in fin_bb. We need to create
6623 appropriate phi nodes in iter_part_bb instead. */
6624 se = single_pred_edge (fin_bb);
6625 re = single_succ_edge (trip_update_bb);
6626 head = redirect_edge_var_map_vector (re);
6627 ene = single_succ_edge (entry_bb);
6629 psi = gsi_start_phis (fin_bb);
6630 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6631 gsi_next (&psi), ++i)
6633 gimple nphi;
6634 source_location locus;
6636 phi = gsi_stmt (psi);
6637 t = gimple_phi_result (phi);
6638 gcc_assert (t == redirect_edge_var_map_result (vm));
6639 nphi = create_phi_node (t, iter_part_bb);
6641 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6642 locus = gimple_phi_arg_location_from_edge (phi, se);
6644 /* A special case -- fd->loop.v is not yet computed in
6645 iter_part_bb, we need to use v_extra instead. */
6646 if (t == fd->loop.v)
6647 t = v_extra;
6648 add_phi_arg (nphi, t, ene, locus);
6649 locus = redirect_edge_var_map_location (vm);
6650 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6652 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6653 redirect_edge_var_map_clear (re);
6654 while (1)
6656 psi = gsi_start_phis (fin_bb);
6657 if (gsi_end_p (psi))
6658 break;
6659 remove_phi_node (&psi, false);
6662 /* Make phi node for trip. */
6663 phi = create_phi_node (trip_main, iter_part_bb);
6664 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6665 UNKNOWN_LOCATION);
6666 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6667 UNKNOWN_LOCATION);
6670 if (!broken_loop)
6671 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6672 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6673 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6674 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6675 recompute_dominator (CDI_DOMINATORS, fin_bb));
6676 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6677 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6678 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6679 recompute_dominator (CDI_DOMINATORS, body_bb));
6681 if (!broken_loop)
6683 struct loop *trip_loop = alloc_loop ();
6684 trip_loop->header = iter_part_bb;
6685 trip_loop->latch = trip_update_bb;
6686 add_loop (trip_loop, iter_part_bb->loop_father);
6688 if (!gimple_omp_for_combined_p (fd->for_stmt))
6690 struct loop *loop = alloc_loop ();
6691 loop->header = body_bb;
6692 if (collapse_bb == NULL)
6693 loop->latch = cont_bb;
6694 add_loop (loop, trip_loop);
6700 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6701 loop. Given parameters:
6703 for (V = N1; V cond N2; V += STEP) BODY;
6705 where COND is "<" or ">", we generate pseudocode
6707 V = N1;
6708 goto L1;
6710 BODY;
6711 V += STEP;
6713 if (V cond N2) goto L0; else goto L2;
6716 For collapsed loops, given parameters:
6717 collapse(3)
6718 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6719 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6720 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6721 BODY;
6723 we generate pseudocode
6725 if (cond3 is <)
6726 adj = STEP3 - 1;
6727 else
6728 adj = STEP3 + 1;
6729 count3 = (adj + N32 - N31) / STEP3;
6730 if (cond2 is <)
6731 adj = STEP2 - 1;
6732 else
6733 adj = STEP2 + 1;
6734 count2 = (adj + N22 - N21) / STEP2;
6735 if (cond1 is <)
6736 adj = STEP1 - 1;
6737 else
6738 adj = STEP1 + 1;
6739 count1 = (adj + N12 - N11) / STEP1;
6740 count = count1 * count2 * count3;
6741 V = 0;
6742 V1 = N11;
6743 V2 = N21;
6744 V3 = N31;
6745 goto L1;
6747 BODY;
6748 V += 1;
6749 V3 += STEP3;
6750 V2 += (V3 cond3 N32) ? 0 : STEP2;
6751 V3 = (V3 cond3 N32) ? V3 : N31;
6752 V1 += (V2 cond2 N22) ? 0 : STEP1;
6753 V2 = (V2 cond2 N22) ? V2 : N21;
6755 if (V < count) goto L0; else goto L2;
6760 static void
6761 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
6763 tree type, t;
6764 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
6765 gimple_stmt_iterator gsi;
6766 gimple stmt;
6767 bool broken_loop = region->cont == NULL;
6768 edge e, ne;
6769 tree *counts = NULL;
6770 int i;
6771 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6772 OMP_CLAUSE_SAFELEN);
6773 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6774 OMP_CLAUSE__SIMDUID_);
6775 tree n1, n2;
6777 type = TREE_TYPE (fd->loop.v);
6778 entry_bb = region->entry;
6779 cont_bb = region->cont;
6780 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6781 gcc_assert (broken_loop
6782 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6783 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6784 if (!broken_loop)
6786 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6787 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6788 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6789 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6791 else
6793 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6794 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6795 l2_bb = single_succ (l1_bb);
6797 exit_bb = region->exit;
6798 l2_dom_bb = NULL;
6800 gsi = gsi_last_bb (entry_bb);
6802 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6803 /* Not needed in SSA form right now. */
6804 gcc_assert (!gimple_in_ssa_p (cfun));
6805 if (fd->collapse > 1)
6807 int first_zero_iter = -1;
6808 basic_block zero_iter_bb = l2_bb;
6810 counts = XALLOCAVEC (tree, fd->collapse);
6811 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6812 zero_iter_bb, first_zero_iter,
6813 l2_dom_bb);
6815 if (l2_dom_bb == NULL)
6816 l2_dom_bb = l1_bb;
6818 n1 = fd->loop.n1;
6819 n2 = fd->loop.n2;
6820 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6822 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6823 OMP_CLAUSE__LOOPTEMP_);
6824 gcc_assert (innerc);
6825 n1 = OMP_CLAUSE_DECL (innerc);
6826 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6827 OMP_CLAUSE__LOOPTEMP_);
6828 gcc_assert (innerc);
6829 n2 = OMP_CLAUSE_DECL (innerc);
6830 expand_omp_build_assign (&gsi, fd->loop.v,
6831 fold_convert (type, n1));
6832 if (fd->collapse > 1)
6834 gsi_prev (&gsi);
6835 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
6836 gsi_next (&gsi);
6839 else
6841 expand_omp_build_assign (&gsi, fd->loop.v,
6842 fold_convert (type, fd->loop.n1));
6843 if (fd->collapse > 1)
6844 for (i = 0; i < fd->collapse; i++)
6846 tree itype = TREE_TYPE (fd->loops[i].v);
6847 if (POINTER_TYPE_P (itype))
6848 itype = signed_type_for (itype);
6849 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
6850 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6854 /* Remove the GIMPLE_OMP_FOR statement. */
6855 gsi_remove (&gsi, true);
6857 if (!broken_loop)
6859 /* Code to control the increment goes in the CONT_BB. */
6860 gsi = gsi_last_bb (cont_bb);
6861 stmt = gsi_stmt (gsi);
6862 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6864 if (POINTER_TYPE_P (type))
6865 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
6866 else
6867 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
6868 expand_omp_build_assign (&gsi, fd->loop.v, t);
6870 if (fd->collapse > 1)
6872 i = fd->collapse - 1;
6873 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
6875 t = fold_convert (sizetype, fd->loops[i].step);
6876 t = fold_build_pointer_plus (fd->loops[i].v, t);
6878 else
6880 t = fold_convert (TREE_TYPE (fd->loops[i].v),
6881 fd->loops[i].step);
6882 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
6883 fd->loops[i].v, t);
6885 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6887 for (i = fd->collapse - 1; i > 0; i--)
6889 tree itype = TREE_TYPE (fd->loops[i].v);
6890 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
6891 if (POINTER_TYPE_P (itype2))
6892 itype2 = signed_type_for (itype2);
6893 t = build3 (COND_EXPR, itype2,
6894 build2 (fd->loops[i].cond_code, boolean_type_node,
6895 fd->loops[i].v,
6896 fold_convert (itype, fd->loops[i].n2)),
6897 build_int_cst (itype2, 0),
6898 fold_convert (itype2, fd->loops[i - 1].step));
6899 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
6900 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
6901 else
6902 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
6903 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
6905 t = build3 (COND_EXPR, itype,
6906 build2 (fd->loops[i].cond_code, boolean_type_node,
6907 fd->loops[i].v,
6908 fold_convert (itype, fd->loops[i].n2)),
6909 fd->loops[i].v,
6910 fold_convert (itype, fd->loops[i].n1));
6911 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6915 /* Remove GIMPLE_OMP_CONTINUE. */
6916 gsi_remove (&gsi, true);
6919 /* Emit the condition in L1_BB. */
6920 gsi = gsi_start_bb (l1_bb);
6922 t = fold_convert (type, n2);
6923 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6924 false, GSI_CONTINUE_LINKING);
6925 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
6926 stmt = gimple_build_cond_empty (t);
6927 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6928 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
6929 NULL, NULL)
6930 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
6931 NULL, NULL))
6933 gsi = gsi_for_stmt (stmt);
6934 gimple_regimplify_operands (stmt, &gsi);
6937 /* Remove GIMPLE_OMP_RETURN. */
6938 gsi = gsi_last_bb (exit_bb);
6939 gsi_remove (&gsi, true);
6941 /* Connect the new blocks. */
6942 remove_edge (FALLTHRU_EDGE (entry_bb));
6944 if (!broken_loop)
6946 remove_edge (BRANCH_EDGE (entry_bb));
6947 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6949 e = BRANCH_EDGE (l1_bb);
6950 ne = FALLTHRU_EDGE (l1_bb);
6951 e->flags = EDGE_TRUE_VALUE;
6953 else
6955 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6957 ne = single_succ_edge (l1_bb);
6958 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6961 ne->flags = EDGE_FALSE_VALUE;
6962 e->probability = REG_BR_PROB_BASE * 7 / 8;
6963 ne->probability = REG_BR_PROB_BASE / 8;
6965 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6966 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6967 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6969 if (!broken_loop)
6971 struct loop *loop = alloc_loop ();
6972 loop->header = l1_bb;
6973 loop->latch = cont_bb;
6974 add_loop (loop, l1_bb->loop_father);
6975 if (safelen == NULL_TREE)
6976 loop->safelen = INT_MAX;
6977 else
6979 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
6980 if (TREE_CODE (safelen) != INTEGER_CST)
6981 loop->safelen = 0;
6982 else if (!tree_fits_uhwi_p (safelen)
6983 || tree_to_uhwi (safelen) > INT_MAX)
6984 loop->safelen = INT_MAX;
6985 else
6986 loop->safelen = tree_to_uhwi (safelen);
6987 if (loop->safelen == 1)
6988 loop->safelen = 0;
6990 if (simduid)
6992 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
6993 cfun->has_simduid_loops = true;
6995 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
6996 the loop. */
6997 if ((flag_tree_loop_vectorize
6998 || (!global_options_set.x_flag_tree_loop_vectorize
6999 && !global_options_set.x_flag_tree_vectorize))
7000 && flag_tree_loop_optimize
7001 && loop->safelen > 1)
7003 loop->force_vect = true;
7004 cfun->has_force_vect_loops = true;
7010 /* Expand the OpenMP loop defined by REGION. */
7012 static void
7013 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7015 struct omp_for_data fd;
7016 struct omp_for_data_loop *loops;
7018 loops
7019 = (struct omp_for_data_loop *)
7020 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7021 * sizeof (struct omp_for_data_loop));
7022 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
7023 region->sched_kind = fd.sched_kind;
7025 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7026 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7027 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7028 if (region->cont)
7030 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7031 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7032 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7034 else
7035 /* If there isn't a continue then this is a degerate case where
7036 the introduction of abnormal edges during lowering will prevent
7037 original loops from being detected. Fix that up. */
7038 loops_state_set (LOOPS_NEED_FIXUP);
7040 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_KIND_SIMD)
7041 expand_omp_simd (region, &fd);
7042 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7043 && !fd.have_ordered)
7045 if (fd.chunk_size == NULL)
7046 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7047 else
7048 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7050 else
7052 int fn_index, start_ix, next_ix;
7054 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7055 == GF_OMP_FOR_KIND_FOR);
7056 if (fd.chunk_size == NULL
7057 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7058 fd.chunk_size = integer_zero_node;
7059 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7060 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7061 ? 3 : fd.sched_kind;
7062 fn_index += fd.have_ordered * 4;
7063 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7064 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7065 if (fd.iter_type == long_long_unsigned_type_node)
7067 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7068 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7069 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7070 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7072 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7073 (enum built_in_function) next_ix, inner_stmt);
7076 if (gimple_in_ssa_p (cfun))
7077 update_ssa (TODO_update_ssa_only_virtuals);
7081 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7083 v = GOMP_sections_start (n);
7085 switch (v)
7087 case 0:
7088 goto L2;
7089 case 1:
7090 section 1;
7091 goto L1;
7092 case 2:
7094 case n:
7096 default:
7097 abort ();
7100 v = GOMP_sections_next ();
7101 goto L0;
7103 reduction;
7105 If this is a combined parallel sections, replace the call to
7106 GOMP_sections_start with call to GOMP_sections_next. */
7108 static void
7109 expand_omp_sections (struct omp_region *region)
7111 tree t, u, vin = NULL, vmain, vnext, l2;
7112 unsigned len;
7113 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7114 gimple_stmt_iterator si, switch_si;
7115 gimple sections_stmt, stmt, cont;
7116 edge_iterator ei;
7117 edge e;
7118 struct omp_region *inner;
7119 unsigned i, casei;
7120 bool exit_reachable = region->cont != NULL;
7122 gcc_assert (region->exit != NULL);
7123 entry_bb = region->entry;
7124 l0_bb = single_succ (entry_bb);
7125 l1_bb = region->cont;
7126 l2_bb = region->exit;
7127 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7128 l2 = gimple_block_label (l2_bb);
7129 else
7131 /* This can happen if there are reductions. */
7132 len = EDGE_COUNT (l0_bb->succs);
7133 gcc_assert (len > 0);
7134 e = EDGE_SUCC (l0_bb, len - 1);
7135 si = gsi_last_bb (e->dest);
7136 l2 = NULL_TREE;
7137 if (gsi_end_p (si)
7138 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7139 l2 = gimple_block_label (e->dest);
7140 else
7141 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7143 si = gsi_last_bb (e->dest);
7144 if (gsi_end_p (si)
7145 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7147 l2 = gimple_block_label (e->dest);
7148 break;
7152 if (exit_reachable)
7153 default_bb = create_empty_bb (l1_bb->prev_bb);
7154 else
7155 default_bb = create_empty_bb (l0_bb);
7157 /* We will build a switch() with enough cases for all the
7158 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7159 and a default case to abort if something goes wrong. */
7160 len = EDGE_COUNT (l0_bb->succs);
7162 /* Use vec::quick_push on label_vec throughout, since we know the size
7163 in advance. */
7164 auto_vec<tree> label_vec (len);
7166 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7167 GIMPLE_OMP_SECTIONS statement. */
7168 si = gsi_last_bb (entry_bb);
7169 sections_stmt = gsi_stmt (si);
7170 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7171 vin = gimple_omp_sections_control (sections_stmt);
7172 if (!is_combined_parallel (region))
7174 /* If we are not inside a combined parallel+sections region,
7175 call GOMP_sections_start. */
7176 t = build_int_cst (unsigned_type_node, len - 1);
7177 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7178 stmt = gimple_build_call (u, 1, t);
7180 else
7182 /* Otherwise, call GOMP_sections_next. */
7183 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7184 stmt = gimple_build_call (u, 0);
7186 gimple_call_set_lhs (stmt, vin);
7187 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7188 gsi_remove (&si, true);
7190 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7191 L0_BB. */
7192 switch_si = gsi_last_bb (l0_bb);
7193 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7194 if (exit_reachable)
7196 cont = last_stmt (l1_bb);
7197 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7198 vmain = gimple_omp_continue_control_use (cont);
7199 vnext = gimple_omp_continue_control_def (cont);
7201 else
7203 vmain = vin;
7204 vnext = NULL_TREE;
7207 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7208 label_vec.quick_push (t);
7209 i = 1;
7211 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7212 for (inner = region->inner, casei = 1;
7213 inner;
7214 inner = inner->next, i++, casei++)
7216 basic_block s_entry_bb, s_exit_bb;
7218 /* Skip optional reduction region. */
7219 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7221 --i;
7222 --casei;
7223 continue;
7226 s_entry_bb = inner->entry;
7227 s_exit_bb = inner->exit;
7229 t = gimple_block_label (s_entry_bb);
7230 u = build_int_cst (unsigned_type_node, casei);
7231 u = build_case_label (u, NULL, t);
7232 label_vec.quick_push (u);
7234 si = gsi_last_bb (s_entry_bb);
7235 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7236 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7237 gsi_remove (&si, true);
7238 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7240 if (s_exit_bb == NULL)
7241 continue;
7243 si = gsi_last_bb (s_exit_bb);
7244 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7245 gsi_remove (&si, true);
7247 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7250 /* Error handling code goes in DEFAULT_BB. */
7251 t = gimple_block_label (default_bb);
7252 u = build_case_label (NULL, NULL, t);
7253 make_edge (l0_bb, default_bb, 0);
7254 if (current_loops)
7255 add_bb_to_loop (default_bb, current_loops->tree_root);
7257 stmt = gimple_build_switch (vmain, u, label_vec);
7258 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7259 gsi_remove (&switch_si, true);
7261 si = gsi_start_bb (default_bb);
7262 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7263 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7265 if (exit_reachable)
7267 tree bfn_decl;
7269 /* Code to get the next section goes in L1_BB. */
7270 si = gsi_last_bb (l1_bb);
7271 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7273 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7274 stmt = gimple_build_call (bfn_decl, 0);
7275 gimple_call_set_lhs (stmt, vnext);
7276 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7277 gsi_remove (&si, true);
7279 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7282 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7283 si = gsi_last_bb (l2_bb);
7284 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7285 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7286 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7287 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7288 else
7289 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7290 stmt = gimple_build_call (t, 0);
7291 if (gimple_omp_return_lhs (gsi_stmt (si)))
7292 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7293 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7294 gsi_remove (&si, true);
7296 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7300 /* Expand code for an OpenMP single directive. We've already expanded
7301 much of the code, here we simply place the GOMP_barrier call. */
7303 static void
7304 expand_omp_single (struct omp_region *region)
7306 basic_block entry_bb, exit_bb;
7307 gimple_stmt_iterator si;
7309 entry_bb = region->entry;
7310 exit_bb = region->exit;
7312 si = gsi_last_bb (entry_bb);
7313 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7314 gsi_remove (&si, true);
7315 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7317 si = gsi_last_bb (exit_bb);
7318 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7320 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7321 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7323 gsi_remove (&si, true);
7324 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7328 /* Generic expansion for OpenMP synchronization directives: master,
7329 ordered and critical. All we need to do here is remove the entry
7330 and exit markers for REGION. */
7332 static void
7333 expand_omp_synch (struct omp_region *region)
7335 basic_block entry_bb, exit_bb;
7336 gimple_stmt_iterator si;
7338 entry_bb = region->entry;
7339 exit_bb = region->exit;
7341 si = gsi_last_bb (entry_bb);
7342 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7343 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7344 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7345 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7346 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7347 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7348 gsi_remove (&si, true);
7349 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7351 if (exit_bb)
7353 si = gsi_last_bb (exit_bb);
7354 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7355 gsi_remove (&si, true);
7356 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7360 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7361 operation as a normal volatile load. */
7363 static bool
7364 expand_omp_atomic_load (basic_block load_bb, tree addr,
7365 tree loaded_val, int index)
7367 enum built_in_function tmpbase;
7368 gimple_stmt_iterator gsi;
7369 basic_block store_bb;
7370 location_t loc;
7371 gimple stmt;
7372 tree decl, call, type, itype;
7374 gsi = gsi_last_bb (load_bb);
7375 stmt = gsi_stmt (gsi);
7376 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7377 loc = gimple_location (stmt);
7379 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7380 is smaller than word size, then expand_atomic_load assumes that the load
7381 is atomic. We could avoid the builtin entirely in this case. */
7383 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7384 decl = builtin_decl_explicit (tmpbase);
7385 if (decl == NULL_TREE)
7386 return false;
7388 type = TREE_TYPE (loaded_val);
7389 itype = TREE_TYPE (TREE_TYPE (decl));
7391 call = build_call_expr_loc (loc, decl, 2, addr,
7392 build_int_cst (NULL,
7393 gimple_omp_atomic_seq_cst_p (stmt)
7394 ? MEMMODEL_SEQ_CST
7395 : MEMMODEL_RELAXED));
7396 if (!useless_type_conversion_p (type, itype))
7397 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7398 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7400 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7401 gsi_remove (&gsi, true);
7403 store_bb = single_succ (load_bb);
7404 gsi = gsi_last_bb (store_bb);
7405 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7406 gsi_remove (&gsi, true);
7408 if (gimple_in_ssa_p (cfun))
7409 update_ssa (TODO_update_ssa_no_phi);
7411 return true;
7414 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7415 operation as a normal volatile store. */
7417 static bool
7418 expand_omp_atomic_store (basic_block load_bb, tree addr,
7419 tree loaded_val, tree stored_val, int index)
7421 enum built_in_function tmpbase;
7422 gimple_stmt_iterator gsi;
7423 basic_block store_bb = single_succ (load_bb);
7424 location_t loc;
7425 gimple stmt;
7426 tree decl, call, type, itype;
7427 enum machine_mode imode;
7428 bool exchange;
7430 gsi = gsi_last_bb (load_bb);
7431 stmt = gsi_stmt (gsi);
7432 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7434 /* If the load value is needed, then this isn't a store but an exchange. */
7435 exchange = gimple_omp_atomic_need_value_p (stmt);
7437 gsi = gsi_last_bb (store_bb);
7438 stmt = gsi_stmt (gsi);
7439 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7440 loc = gimple_location (stmt);
7442 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7443 is smaller than word size, then expand_atomic_store assumes that the store
7444 is atomic. We could avoid the builtin entirely in this case. */
7446 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7447 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7448 decl = builtin_decl_explicit (tmpbase);
7449 if (decl == NULL_TREE)
7450 return false;
7452 type = TREE_TYPE (stored_val);
7454 /* Dig out the type of the function's second argument. */
7455 itype = TREE_TYPE (decl);
7456 itype = TYPE_ARG_TYPES (itype);
7457 itype = TREE_CHAIN (itype);
7458 itype = TREE_VALUE (itype);
7459 imode = TYPE_MODE (itype);
7461 if (exchange && !can_atomic_exchange_p (imode, true))
7462 return false;
7464 if (!useless_type_conversion_p (itype, type))
7465 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7466 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7467 build_int_cst (NULL,
7468 gimple_omp_atomic_seq_cst_p (stmt)
7469 ? MEMMODEL_SEQ_CST
7470 : MEMMODEL_RELAXED));
7471 if (exchange)
7473 if (!useless_type_conversion_p (type, itype))
7474 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7475 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7478 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7479 gsi_remove (&gsi, true);
7481 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7482 gsi = gsi_last_bb (load_bb);
7483 gsi_remove (&gsi, true);
7485 if (gimple_in_ssa_p (cfun))
7486 update_ssa (TODO_update_ssa_no_phi);
7488 return true;
7491 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7492 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7493 size of the data type, and thus usable to find the index of the builtin
7494 decl. Returns false if the expression is not of the proper form. */
7496 static bool
7497 expand_omp_atomic_fetch_op (basic_block load_bb,
7498 tree addr, tree loaded_val,
7499 tree stored_val, int index)
7501 enum built_in_function oldbase, newbase, tmpbase;
7502 tree decl, itype, call;
7503 tree lhs, rhs;
7504 basic_block store_bb = single_succ (load_bb);
7505 gimple_stmt_iterator gsi;
7506 gimple stmt;
7507 location_t loc;
7508 enum tree_code code;
7509 bool need_old, need_new;
7510 enum machine_mode imode;
7511 bool seq_cst;
7513 /* We expect to find the following sequences:
7515 load_bb:
7516 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7518 store_bb:
7519 val = tmp OP something; (or: something OP tmp)
7520 GIMPLE_OMP_STORE (val)
7522 ???FIXME: Allow a more flexible sequence.
7523 Perhaps use data flow to pick the statements.
7527 gsi = gsi_after_labels (store_bb);
7528 stmt = gsi_stmt (gsi);
7529 loc = gimple_location (stmt);
7530 if (!is_gimple_assign (stmt))
7531 return false;
7532 gsi_next (&gsi);
7533 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7534 return false;
7535 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7536 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7537 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7538 gcc_checking_assert (!need_old || !need_new);
7540 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7541 return false;
7543 /* Check for one of the supported fetch-op operations. */
7544 code = gimple_assign_rhs_code (stmt);
7545 switch (code)
7547 case PLUS_EXPR:
7548 case POINTER_PLUS_EXPR:
7549 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7550 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7551 break;
7552 case MINUS_EXPR:
7553 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7554 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7555 break;
7556 case BIT_AND_EXPR:
7557 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7558 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7559 break;
7560 case BIT_IOR_EXPR:
7561 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7562 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7563 break;
7564 case BIT_XOR_EXPR:
7565 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7566 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7567 break;
7568 default:
7569 return false;
7572 /* Make sure the expression is of the proper form. */
7573 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7574 rhs = gimple_assign_rhs2 (stmt);
7575 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7576 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7577 rhs = gimple_assign_rhs1 (stmt);
7578 else
7579 return false;
7581 tmpbase = ((enum built_in_function)
7582 ((need_new ? newbase : oldbase) + index + 1));
7583 decl = builtin_decl_explicit (tmpbase);
7584 if (decl == NULL_TREE)
7585 return false;
7586 itype = TREE_TYPE (TREE_TYPE (decl));
7587 imode = TYPE_MODE (itype);
7589 /* We could test all of the various optabs involved, but the fact of the
7590 matter is that (with the exception of i486 vs i586 and xadd) all targets
7591 that support any atomic operaton optab also implements compare-and-swap.
7592 Let optabs.c take care of expanding any compare-and-swap loop. */
7593 if (!can_compare_and_swap_p (imode, true))
7594 return false;
7596 gsi = gsi_last_bb (load_bb);
7597 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7599 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7600 It only requires that the operation happen atomically. Thus we can
7601 use the RELAXED memory model. */
7602 call = build_call_expr_loc (loc, decl, 3, addr,
7603 fold_convert_loc (loc, itype, rhs),
7604 build_int_cst (NULL,
7605 seq_cst ? MEMMODEL_SEQ_CST
7606 : MEMMODEL_RELAXED));
7608 if (need_old || need_new)
7610 lhs = need_old ? loaded_val : stored_val;
7611 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7612 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7614 else
7615 call = fold_convert_loc (loc, void_type_node, call);
7616 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7617 gsi_remove (&gsi, true);
7619 gsi = gsi_last_bb (store_bb);
7620 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7621 gsi_remove (&gsi, true);
7622 gsi = gsi_last_bb (store_bb);
7623 gsi_remove (&gsi, true);
7625 if (gimple_in_ssa_p (cfun))
7626 update_ssa (TODO_update_ssa_no_phi);
7628 return true;
7631 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7633 oldval = *addr;
7634 repeat:
7635 newval = rhs; // with oldval replacing *addr in rhs
7636 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7637 if (oldval != newval)
7638 goto repeat;
7640 INDEX is log2 of the size of the data type, and thus usable to find the
7641 index of the builtin decl. */
7643 static bool
7644 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7645 tree addr, tree loaded_val, tree stored_val,
7646 int index)
7648 tree loadedi, storedi, initial, new_storedi, old_vali;
7649 tree type, itype, cmpxchg, iaddr;
7650 gimple_stmt_iterator si;
7651 basic_block loop_header = single_succ (load_bb);
7652 gimple phi, stmt;
7653 edge e;
7654 enum built_in_function fncode;
7656 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7657 order to use the RELAXED memory model effectively. */
7658 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7659 + index + 1);
7660 cmpxchg = builtin_decl_explicit (fncode);
7661 if (cmpxchg == NULL_TREE)
7662 return false;
7663 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7664 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7666 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7667 return false;
7669 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7670 si = gsi_last_bb (load_bb);
7671 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7673 /* For floating-point values, we'll need to view-convert them to integers
7674 so that we can perform the atomic compare and swap. Simplify the
7675 following code by always setting up the "i"ntegral variables. */
7676 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7678 tree iaddr_val;
7680 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7681 true), NULL);
7682 iaddr_val
7683 = force_gimple_operand_gsi (&si,
7684 fold_convert (TREE_TYPE (iaddr), addr),
7685 false, NULL_TREE, true, GSI_SAME_STMT);
7686 stmt = gimple_build_assign (iaddr, iaddr_val);
7687 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7688 loadedi = create_tmp_var (itype, NULL);
7689 if (gimple_in_ssa_p (cfun))
7690 loadedi = make_ssa_name (loadedi, NULL);
7692 else
7694 iaddr = addr;
7695 loadedi = loaded_val;
7698 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7699 tree loaddecl = builtin_decl_explicit (fncode);
7700 if (loaddecl)
7701 initial
7702 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
7703 build_call_expr (loaddecl, 2, iaddr,
7704 build_int_cst (NULL_TREE,
7705 MEMMODEL_RELAXED)));
7706 else
7707 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
7708 build_int_cst (TREE_TYPE (iaddr), 0));
7710 initial
7711 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
7712 GSI_SAME_STMT);
7714 /* Move the value to the LOADEDI temporary. */
7715 if (gimple_in_ssa_p (cfun))
7717 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
7718 phi = create_phi_node (loadedi, loop_header);
7719 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
7720 initial);
7722 else
7723 gsi_insert_before (&si,
7724 gimple_build_assign (loadedi, initial),
7725 GSI_SAME_STMT);
7726 if (loadedi != loaded_val)
7728 gimple_stmt_iterator gsi2;
7729 tree x;
7731 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
7732 gsi2 = gsi_start_bb (loop_header);
7733 if (gimple_in_ssa_p (cfun))
7735 gimple stmt;
7736 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7737 true, GSI_SAME_STMT);
7738 stmt = gimple_build_assign (loaded_val, x);
7739 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
7741 else
7743 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
7744 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7745 true, GSI_SAME_STMT);
7748 gsi_remove (&si, true);
7750 si = gsi_last_bb (store_bb);
7751 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7753 if (iaddr == addr)
7754 storedi = stored_val;
7755 else
7756 storedi =
7757 force_gimple_operand_gsi (&si,
7758 build1 (VIEW_CONVERT_EXPR, itype,
7759 stored_val), true, NULL_TREE, true,
7760 GSI_SAME_STMT);
7762 /* Build the compare&swap statement. */
7763 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
7764 new_storedi = force_gimple_operand_gsi (&si,
7765 fold_convert (TREE_TYPE (loadedi),
7766 new_storedi),
7767 true, NULL_TREE,
7768 true, GSI_SAME_STMT);
7770 if (gimple_in_ssa_p (cfun))
7771 old_vali = loadedi;
7772 else
7774 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
7775 stmt = gimple_build_assign (old_vali, loadedi);
7776 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7778 stmt = gimple_build_assign (loadedi, new_storedi);
7779 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7782 /* Note that we always perform the comparison as an integer, even for
7783 floating point. This allows the atomic operation to properly
7784 succeed even with NaNs and -0.0. */
7785 stmt = gimple_build_cond_empty
7786 (build2 (NE_EXPR, boolean_type_node,
7787 new_storedi, old_vali));
7788 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7790 /* Update cfg. */
7791 e = single_succ_edge (store_bb);
7792 e->flags &= ~EDGE_FALLTHRU;
7793 e->flags |= EDGE_FALSE_VALUE;
7795 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
7797 /* Copy the new value to loadedi (we already did that before the condition
7798 if we are not in SSA). */
7799 if (gimple_in_ssa_p (cfun))
7801 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
7802 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
7805 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
7806 gsi_remove (&si, true);
7808 struct loop *loop = alloc_loop ();
7809 loop->header = loop_header;
7810 loop->latch = store_bb;
7811 add_loop (loop, loop_header->loop_father);
7813 if (gimple_in_ssa_p (cfun))
7814 update_ssa (TODO_update_ssa_no_phi);
7816 return true;
7819 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7821 GOMP_atomic_start ();
7822 *addr = rhs;
7823 GOMP_atomic_end ();
7825 The result is not globally atomic, but works so long as all parallel
7826 references are within #pragma omp atomic directives. According to
7827 responses received from omp@openmp.org, appears to be within spec.
7828 Which makes sense, since that's how several other compilers handle
7829 this situation as well.
7830 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
7831 expanding. STORED_VAL is the operand of the matching
7832 GIMPLE_OMP_ATOMIC_STORE.
7834 We replace
7835 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
7836 loaded_val = *addr;
7838 and replace
7839 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
7840 *addr = stored_val;
7843 static bool
7844 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
7845 tree addr, tree loaded_val, tree stored_val)
7847 gimple_stmt_iterator si;
7848 gimple stmt;
7849 tree t;
7851 si = gsi_last_bb (load_bb);
7852 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7854 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
7855 t = build_call_expr (t, 0);
7856 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7858 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
7859 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7860 gsi_remove (&si, true);
7862 si = gsi_last_bb (store_bb);
7863 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7865 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
7866 stored_val);
7867 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7869 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
7870 t = build_call_expr (t, 0);
7871 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7872 gsi_remove (&si, true);
7874 if (gimple_in_ssa_p (cfun))
7875 update_ssa (TODO_update_ssa_no_phi);
7876 return true;
7879 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
7880 using expand_omp_atomic_fetch_op. If it failed, we try to
7881 call expand_omp_atomic_pipeline, and if it fails too, the
7882 ultimate fallback is wrapping the operation in a mutex
7883 (expand_omp_atomic_mutex). REGION is the atomic region built
7884 by build_omp_regions_1(). */
7886 static void
7887 expand_omp_atomic (struct omp_region *region)
7889 basic_block load_bb = region->entry, store_bb = region->exit;
7890 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
7891 tree loaded_val = gimple_omp_atomic_load_lhs (load);
7892 tree addr = gimple_omp_atomic_load_rhs (load);
7893 tree stored_val = gimple_omp_atomic_store_val (store);
7894 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7895 HOST_WIDE_INT index;
7897 /* Make sure the type is one of the supported sizes. */
7898 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
7899 index = exact_log2 (index);
7900 if (index >= 0 && index <= 4)
7902 unsigned int align = TYPE_ALIGN_UNIT (type);
7904 /* __sync builtins require strict data alignment. */
7905 if (exact_log2 (align) >= index)
7907 /* Atomic load. */
7908 if (loaded_val == stored_val
7909 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7910 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7911 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7912 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
7913 return;
7915 /* Atomic store. */
7916 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7917 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7918 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7919 && store_bb == single_succ (load_bb)
7920 && first_stmt (store_bb) == store
7921 && expand_omp_atomic_store (load_bb, addr, loaded_val,
7922 stored_val, index))
7923 return;
7925 /* When possible, use specialized atomic update functions. */
7926 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
7927 && store_bb == single_succ (load_bb)
7928 && expand_omp_atomic_fetch_op (load_bb, addr,
7929 loaded_val, stored_val, index))
7930 return;
7932 /* If we don't have specialized __sync builtins, try and implement
7933 as a compare and swap loop. */
7934 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
7935 loaded_val, stored_val, index))
7936 return;
7940 /* The ultimate fallback is wrapping the operation in a mutex. */
7941 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
7945 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
7947 static void
7948 expand_omp_target (struct omp_region *region)
7950 basic_block entry_bb, exit_bb, new_bb;
7951 struct function *child_cfun = NULL;
7952 tree child_fn = NULL_TREE, block, t;
7953 gimple_stmt_iterator gsi;
7954 gimple entry_stmt, stmt;
7955 edge e;
7957 entry_stmt = last_stmt (region->entry);
7958 new_bb = region->entry;
7959 int kind = gimple_omp_target_kind (entry_stmt);
7960 if (kind == GF_OMP_TARGET_KIND_REGION)
7962 child_fn = gimple_omp_target_child_fn (entry_stmt);
7963 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7966 entry_bb = region->entry;
7967 exit_bb = region->exit;
7969 if (kind == GF_OMP_TARGET_KIND_REGION)
7971 unsigned srcidx, dstidx, num;
7973 /* If the target region needs data sent from the parent
7974 function, then the very first statement (except possible
7975 tree profile counter updates) of the parallel body
7976 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7977 &.OMP_DATA_O is passed as an argument to the child function,
7978 we need to replace it with the argument as seen by the child
7979 function.
7981 In most cases, this will end up being the identity assignment
7982 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7983 a function call that has been inlined, the original PARM_DECL
7984 .OMP_DATA_I may have been converted into a different local
7985 variable. In which case, we need to keep the assignment. */
7986 if (gimple_omp_target_data_arg (entry_stmt))
7988 basic_block entry_succ_bb = single_succ (entry_bb);
7989 gimple_stmt_iterator gsi;
7990 tree arg;
7991 gimple tgtcopy_stmt = NULL;
7992 tree sender
7993 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
7995 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7997 gcc_assert (!gsi_end_p (gsi));
7998 stmt = gsi_stmt (gsi);
7999 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8000 continue;
8002 if (gimple_num_ops (stmt) == 2)
8004 tree arg = gimple_assign_rhs1 (stmt);
8006 /* We're ignoring the subcode because we're
8007 effectively doing a STRIP_NOPS. */
8009 if (TREE_CODE (arg) == ADDR_EXPR
8010 && TREE_OPERAND (arg, 0) == sender)
8012 tgtcopy_stmt = stmt;
8013 break;
8018 gcc_assert (tgtcopy_stmt != NULL);
8019 arg = DECL_ARGUMENTS (child_fn);
8021 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8022 gsi_remove (&gsi, true);
8025 /* Declare local variables needed in CHILD_CFUN. */
8026 block = DECL_INITIAL (child_fn);
8027 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8028 /* The gimplifier could record temporaries in target block
8029 rather than in containing function's local_decls chain,
8030 which would mean cgraph missed finalizing them. Do it now. */
8031 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8032 if (TREE_CODE (t) == VAR_DECL
8033 && TREE_STATIC (t)
8034 && !DECL_EXTERNAL (t))
8035 varpool_finalize_decl (t);
8036 DECL_SAVED_TREE (child_fn) = NULL;
8037 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8038 gimple_set_body (child_fn, NULL);
8039 TREE_USED (block) = 1;
8041 /* Reset DECL_CONTEXT on function arguments. */
8042 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8043 DECL_CONTEXT (t) = child_fn;
8045 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8046 so that it can be moved to the child function. */
8047 gsi = gsi_last_bb (entry_bb);
8048 stmt = gsi_stmt (gsi);
8049 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
8050 && gimple_omp_target_kind (stmt)
8051 == GF_OMP_TARGET_KIND_REGION);
8052 gsi_remove (&gsi, true);
8053 e = split_block (entry_bb, stmt);
8054 entry_bb = e->dest;
8055 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8057 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8058 if (exit_bb)
8060 gsi = gsi_last_bb (exit_bb);
8061 gcc_assert (!gsi_end_p (gsi)
8062 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8063 stmt = gimple_build_return (NULL);
8064 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8065 gsi_remove (&gsi, true);
8068 /* Move the target region into CHILD_CFUN. */
8070 block = gimple_block (entry_stmt);
8072 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8073 if (exit_bb)
8074 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8075 /* When the OMP expansion process cannot guarantee an up-to-date
8076 loop tree arrange for the child function to fixup loops. */
8077 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8078 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8080 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8081 num = vec_safe_length (child_cfun->local_decls);
8082 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8084 t = (*child_cfun->local_decls)[srcidx];
8085 if (DECL_CONTEXT (t) == cfun->decl)
8086 continue;
8087 if (srcidx != dstidx)
8088 (*child_cfun->local_decls)[dstidx] = t;
8089 dstidx++;
8091 if (dstidx != num)
8092 vec_safe_truncate (child_cfun->local_decls, dstidx);
8094 /* Inform the callgraph about the new function. */
8095 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8096 cgraph_add_new_function (child_fn, true);
8098 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8099 fixed in a following pass. */
8100 push_cfun (child_cfun);
8101 rebuild_cgraph_edges ();
8103 /* Some EH regions might become dead, see PR34608. If
8104 pass_cleanup_cfg isn't the first pass to happen with the
8105 new child, these dead EH edges might cause problems.
8106 Clean them up now. */
8107 if (flag_exceptions)
8109 basic_block bb;
8110 bool changed = false;
8112 FOR_EACH_BB_FN (bb, cfun)
8113 changed |= gimple_purge_dead_eh_edges (bb);
8114 if (changed)
8115 cleanup_tree_cfg ();
8117 pop_cfun ();
8120 /* Emit a library call to launch the target region, or do data
8121 transfers. */
8122 tree t1, t2, t3, t4, device, cond, c, clauses;
8123 enum built_in_function start_ix;
8124 location_t clause_loc;
8126 clauses = gimple_omp_target_clauses (entry_stmt);
8128 if (kind == GF_OMP_TARGET_KIND_REGION)
8129 start_ix = BUILT_IN_GOMP_TARGET;
8130 else if (kind == GF_OMP_TARGET_KIND_DATA)
8131 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8132 else
8133 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8135 /* By default, the value of DEVICE is -1 (let runtime library choose)
8136 and there is no conditional. */
8137 cond = NULL_TREE;
8138 device = build_int_cst (integer_type_node, -1);
8140 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8141 if (c)
8142 cond = OMP_CLAUSE_IF_EXPR (c);
8144 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8145 if (c)
8147 device = OMP_CLAUSE_DEVICE_ID (c);
8148 clause_loc = OMP_CLAUSE_LOCATION (c);
8150 else
8151 clause_loc = gimple_location (entry_stmt);
8153 /* Ensure 'device' is of the correct type. */
8154 device = fold_convert_loc (clause_loc, integer_type_node, device);
8156 /* If we found the clause 'if (cond)', build
8157 (cond ? device : -2). */
8158 if (cond)
8160 cond = gimple_boolify (cond);
8162 basic_block cond_bb, then_bb, else_bb;
8163 edge e;
8164 tree tmp_var;
8166 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8167 if (kind != GF_OMP_TARGET_KIND_REGION)
8169 gsi = gsi_last_bb (new_bb);
8170 gsi_prev (&gsi);
8171 e = split_block (new_bb, gsi_stmt (gsi));
8173 else
8174 e = split_block (new_bb, NULL);
8175 cond_bb = e->src;
8176 new_bb = e->dest;
8177 remove_edge (e);
8179 then_bb = create_empty_bb (cond_bb);
8180 else_bb = create_empty_bb (then_bb);
8181 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8182 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8184 stmt = gimple_build_cond_empty (cond);
8185 gsi = gsi_last_bb (cond_bb);
8186 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8188 gsi = gsi_start_bb (then_bb);
8189 stmt = gimple_build_assign (tmp_var, device);
8190 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8192 gsi = gsi_start_bb (else_bb);
8193 stmt = gimple_build_assign (tmp_var,
8194 build_int_cst (integer_type_node, -2));
8195 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8197 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8198 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8199 if (current_loops)
8201 add_bb_to_loop (then_bb, cond_bb->loop_father);
8202 add_bb_to_loop (else_bb, cond_bb->loop_father);
8204 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8205 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8207 device = tmp_var;
8210 gsi = gsi_last_bb (new_bb);
8211 t = gimple_omp_target_data_arg (entry_stmt);
8212 if (t == NULL)
8214 t1 = size_zero_node;
8215 t2 = build_zero_cst (ptr_type_node);
8216 t3 = t2;
8217 t4 = t2;
8219 else
8221 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8222 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8223 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8224 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8225 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8228 gimple g;
8229 /* FIXME: This will be address of
8230 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8231 symbol, as soon as the linker plugin is able to create it for us. */
8232 tree openmp_target = build_zero_cst (ptr_type_node);
8233 if (kind == GF_OMP_TARGET_KIND_REGION)
8235 tree fnaddr = build_fold_addr_expr (child_fn);
8236 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8237 device, fnaddr, openmp_target, t1, t2, t3, t4);
8239 else
8240 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8241 device, openmp_target, t1, t2, t3, t4);
8242 gimple_set_location (g, gimple_location (entry_stmt));
8243 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8244 if (kind != GF_OMP_TARGET_KIND_REGION)
8246 g = gsi_stmt (gsi);
8247 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8248 gsi_remove (&gsi, true);
8250 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8252 gsi = gsi_last_bb (region->exit);
8253 g = gsi_stmt (gsi);
8254 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8255 gsi_remove (&gsi, true);
8260 /* Expand the parallel region tree rooted at REGION. Expansion
8261 proceeds in depth-first order. Innermost regions are expanded
8262 first. This way, parallel regions that require a new function to
8263 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8264 internal dependencies in their body. */
8266 static void
8267 expand_omp (struct omp_region *region)
8269 while (region)
8271 location_t saved_location;
8272 gimple inner_stmt = NULL;
8274 /* First, determine whether this is a combined parallel+workshare
8275 region. */
8276 if (region->type == GIMPLE_OMP_PARALLEL)
8277 determine_parallel_type (region);
8279 if (region->type == GIMPLE_OMP_FOR
8280 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8281 inner_stmt = last_stmt (region->inner->entry);
8283 if (region->inner)
8284 expand_omp (region->inner);
8286 saved_location = input_location;
8287 if (gimple_has_location (last_stmt (region->entry)))
8288 input_location = gimple_location (last_stmt (region->entry));
8290 switch (region->type)
8292 case GIMPLE_OMP_PARALLEL:
8293 case GIMPLE_OMP_TASK:
8294 expand_omp_taskreg (region);
8295 break;
8297 case GIMPLE_OMP_FOR:
8298 expand_omp_for (region, inner_stmt);
8299 break;
8301 case GIMPLE_OMP_SECTIONS:
8302 expand_omp_sections (region);
8303 break;
8305 case GIMPLE_OMP_SECTION:
8306 /* Individual omp sections are handled together with their
8307 parent GIMPLE_OMP_SECTIONS region. */
8308 break;
8310 case GIMPLE_OMP_SINGLE:
8311 expand_omp_single (region);
8312 break;
8314 case GIMPLE_OMP_MASTER:
8315 case GIMPLE_OMP_TASKGROUP:
8316 case GIMPLE_OMP_ORDERED:
8317 case GIMPLE_OMP_CRITICAL:
8318 case GIMPLE_OMP_TEAMS:
8319 expand_omp_synch (region);
8320 break;
8322 case GIMPLE_OMP_ATOMIC_LOAD:
8323 expand_omp_atomic (region);
8324 break;
8326 case GIMPLE_OMP_TARGET:
8327 expand_omp_target (region);
8328 break;
8330 default:
8331 gcc_unreachable ();
8334 input_location = saved_location;
8335 region = region->next;
8340 /* Helper for build_omp_regions. Scan the dominator tree starting at
8341 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8342 true, the function ends once a single tree is built (otherwise, whole
8343 forest of OMP constructs may be built). */
8345 static void
8346 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8347 bool single_tree)
8349 gimple_stmt_iterator gsi;
8350 gimple stmt;
8351 basic_block son;
8353 gsi = gsi_last_bb (bb);
8354 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8356 struct omp_region *region;
8357 enum gimple_code code;
8359 stmt = gsi_stmt (gsi);
8360 code = gimple_code (stmt);
8361 if (code == GIMPLE_OMP_RETURN)
8363 /* STMT is the return point out of region PARENT. Mark it
8364 as the exit point and make PARENT the immediately
8365 enclosing region. */
8366 gcc_assert (parent);
8367 region = parent;
8368 region->exit = bb;
8369 parent = parent->outer;
8371 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8373 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8374 GIMPLE_OMP_RETURN, but matches with
8375 GIMPLE_OMP_ATOMIC_LOAD. */
8376 gcc_assert (parent);
8377 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8378 region = parent;
8379 region->exit = bb;
8380 parent = parent->outer;
8383 else if (code == GIMPLE_OMP_CONTINUE)
8385 gcc_assert (parent);
8386 parent->cont = bb;
8388 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8390 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8391 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8394 else if (code == GIMPLE_OMP_TARGET
8395 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8396 new_omp_region (bb, code, parent);
8397 else
8399 /* Otherwise, this directive becomes the parent for a new
8400 region. */
8401 region = new_omp_region (bb, code, parent);
8402 parent = region;
8406 if (single_tree && !parent)
8407 return;
8409 for (son = first_dom_son (CDI_DOMINATORS, bb);
8410 son;
8411 son = next_dom_son (CDI_DOMINATORS, son))
8412 build_omp_regions_1 (son, parent, single_tree);
8415 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8416 root_omp_region. */
8418 static void
8419 build_omp_regions_root (basic_block root)
8421 gcc_assert (root_omp_region == NULL);
8422 build_omp_regions_1 (root, NULL, true);
8423 gcc_assert (root_omp_region != NULL);
8426 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8428 void
8429 omp_expand_local (basic_block head)
8431 build_omp_regions_root (head);
8432 if (dump_file && (dump_flags & TDF_DETAILS))
8434 fprintf (dump_file, "\nOMP region tree\n\n");
8435 dump_omp_region (dump_file, root_omp_region, 0);
8436 fprintf (dump_file, "\n");
8439 remove_exit_barriers (root_omp_region);
8440 expand_omp (root_omp_region);
8442 free_omp_regions ();
8445 /* Scan the CFG and build a tree of OMP regions. Return the root of
8446 the OMP region tree. */
8448 static void
8449 build_omp_regions (void)
8451 gcc_assert (root_omp_region == NULL);
8452 calculate_dominance_info (CDI_DOMINATORS);
8453 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8456 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8458 static unsigned int
8459 execute_expand_omp (void)
8461 build_omp_regions ();
8463 if (!root_omp_region)
8464 return 0;
8466 if (dump_file)
8468 fprintf (dump_file, "\nOMP region tree\n\n");
8469 dump_omp_region (dump_file, root_omp_region, 0);
8470 fprintf (dump_file, "\n");
8473 remove_exit_barriers (root_omp_region);
8475 expand_omp (root_omp_region);
8477 cleanup_tree_cfg ();
8479 free_omp_regions ();
8481 return 0;
8484 /* OMP expansion -- the default pass, run before creation of SSA form. */
8486 static bool
8487 gate_expand_omp (void)
8489 return ((flag_openmp != 0 || flag_openmp_simd != 0
8490 || flag_cilkplus != 0) && !seen_error ());
8493 namespace {
8495 const pass_data pass_data_expand_omp =
8497 GIMPLE_PASS, /* type */
8498 "ompexp", /* name */
8499 OPTGROUP_NONE, /* optinfo_flags */
8500 true, /* has_gate */
8501 true, /* has_execute */
8502 TV_NONE, /* tv_id */
8503 PROP_gimple_any, /* properties_required */
8504 0, /* properties_provided */
8505 0, /* properties_destroyed */
8506 0, /* todo_flags_start */
8507 0, /* todo_flags_finish */
8510 class pass_expand_omp : public gimple_opt_pass
8512 public:
8513 pass_expand_omp (gcc::context *ctxt)
8514 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8517 /* opt_pass methods: */
8518 bool gate () { return gate_expand_omp (); }
8519 unsigned int execute () { return execute_expand_omp (); }
8521 }; // class pass_expand_omp
8523 } // anon namespace
8525 gimple_opt_pass *
8526 make_pass_expand_omp (gcc::context *ctxt)
8528 return new pass_expand_omp (ctxt);
8531 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8533 /* If ctx is a worksharing context inside of a cancellable parallel
8534 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8535 and conditional branch to parallel's cancel_label to handle
8536 cancellation in the implicit barrier. */
8538 static void
8539 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8541 gimple omp_return = gimple_seq_last_stmt (*body);
8542 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8543 if (gimple_omp_return_nowait_p (omp_return))
8544 return;
8545 if (ctx->outer
8546 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8547 && ctx->outer->cancellable)
8549 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8550 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8551 tree lhs = create_tmp_var (c_bool_type, NULL);
8552 gimple_omp_return_set_lhs (omp_return, lhs);
8553 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8554 gimple g = gimple_build_cond (NE_EXPR, lhs,
8555 fold_convert (c_bool_type,
8556 boolean_false_node),
8557 ctx->outer->cancel_label, fallthru_label);
8558 gimple_seq_add_stmt (body, g);
8559 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8563 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8564 CTX is the enclosing OMP context for the current statement. */
8566 static void
8567 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8569 tree block, control;
8570 gimple_stmt_iterator tgsi;
8571 gimple stmt, new_stmt, bind, t;
8572 gimple_seq ilist, dlist, olist, new_body;
8574 stmt = gsi_stmt (*gsi_p);
8576 push_gimplify_context ();
8578 dlist = NULL;
8579 ilist = NULL;
8580 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8581 &ilist, &dlist, ctx, NULL);
8583 new_body = gimple_omp_body (stmt);
8584 gimple_omp_set_body (stmt, NULL);
8585 tgsi = gsi_start (new_body);
8586 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8588 omp_context *sctx;
8589 gimple sec_start;
8591 sec_start = gsi_stmt (tgsi);
8592 sctx = maybe_lookup_ctx (sec_start);
8593 gcc_assert (sctx);
8595 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8596 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8597 GSI_CONTINUE_LINKING);
8598 gimple_omp_set_body (sec_start, NULL);
8600 if (gsi_one_before_end_p (tgsi))
8602 gimple_seq l = NULL;
8603 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8604 &l, ctx);
8605 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8606 gimple_omp_section_set_last (sec_start);
8609 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8610 GSI_CONTINUE_LINKING);
8613 block = make_node (BLOCK);
8614 bind = gimple_build_bind (NULL, new_body, block);
8616 olist = NULL;
8617 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8619 block = make_node (BLOCK);
8620 new_stmt = gimple_build_bind (NULL, NULL, block);
8621 gsi_replace (gsi_p, new_stmt, true);
8623 pop_gimplify_context (new_stmt);
8624 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8625 BLOCK_VARS (block) = gimple_bind_vars (bind);
8626 if (BLOCK_VARS (block))
8627 TREE_USED (block) = 1;
8629 new_body = NULL;
8630 gimple_seq_add_seq (&new_body, ilist);
8631 gimple_seq_add_stmt (&new_body, stmt);
8632 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8633 gimple_seq_add_stmt (&new_body, bind);
8635 control = create_tmp_var (unsigned_type_node, ".section");
8636 t = gimple_build_omp_continue (control, control);
8637 gimple_omp_sections_set_control (stmt, control);
8638 gimple_seq_add_stmt (&new_body, t);
8640 gimple_seq_add_seq (&new_body, olist);
8641 if (ctx->cancellable)
8642 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8643 gimple_seq_add_seq (&new_body, dlist);
8645 new_body = maybe_catch_exception (new_body);
8647 t = gimple_build_omp_return
8648 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8649 OMP_CLAUSE_NOWAIT));
8650 gimple_seq_add_stmt (&new_body, t);
8651 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8653 gimple_bind_set_body (new_stmt, new_body);
8657 /* A subroutine of lower_omp_single. Expand the simple form of
8658 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8660 if (GOMP_single_start ())
8661 BODY;
8662 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8664 FIXME. It may be better to delay expanding the logic of this until
8665 pass_expand_omp. The expanded logic may make the job more difficult
8666 to a synchronization analysis pass. */
8668 static void
8669 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8671 location_t loc = gimple_location (single_stmt);
8672 tree tlabel = create_artificial_label (loc);
8673 tree flabel = create_artificial_label (loc);
8674 gimple call, cond;
8675 tree lhs, decl;
8677 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8678 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8679 call = gimple_build_call (decl, 0);
8680 gimple_call_set_lhs (call, lhs);
8681 gimple_seq_add_stmt (pre_p, call);
8683 cond = gimple_build_cond (EQ_EXPR, lhs,
8684 fold_convert_loc (loc, TREE_TYPE (lhs),
8685 boolean_true_node),
8686 tlabel, flabel);
8687 gimple_seq_add_stmt (pre_p, cond);
8688 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8689 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8690 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8694 /* A subroutine of lower_omp_single. Expand the simple form of
8695 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8697 #pragma omp single copyprivate (a, b, c)
8699 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8702 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8704 BODY;
8705 copyout.a = a;
8706 copyout.b = b;
8707 copyout.c = c;
8708 GOMP_single_copy_end (&copyout);
8710 else
8712 a = copyout_p->a;
8713 b = copyout_p->b;
8714 c = copyout_p->c;
8716 GOMP_barrier ();
8719 FIXME. It may be better to delay expanding the logic of this until
8720 pass_expand_omp. The expanded logic may make the job more difficult
8721 to a synchronization analysis pass. */
8723 static void
8724 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
8726 tree ptr_type, t, l0, l1, l2, bfn_decl;
8727 gimple_seq copyin_seq;
8728 location_t loc = gimple_location (single_stmt);
8730 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8732 ptr_type = build_pointer_type (ctx->record_type);
8733 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8735 l0 = create_artificial_label (loc);
8736 l1 = create_artificial_label (loc);
8737 l2 = create_artificial_label (loc);
8739 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8740 t = build_call_expr_loc (loc, bfn_decl, 0);
8741 t = fold_convert_loc (loc, ptr_type, t);
8742 gimplify_assign (ctx->receiver_decl, t, pre_p);
8744 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8745 build_int_cst (ptr_type, 0));
8746 t = build3 (COND_EXPR, void_type_node, t,
8747 build_and_jump (&l0), build_and_jump (&l1));
8748 gimplify_and_add (t, pre_p);
8750 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8752 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8754 copyin_seq = NULL;
8755 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8756 &copyin_seq, ctx);
8758 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8759 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8760 t = build_call_expr_loc (loc, bfn_decl, 1, t);
8761 gimplify_and_add (t, pre_p);
8763 t = build_and_jump (&l2);
8764 gimplify_and_add (t, pre_p);
8766 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8768 gimple_seq_add_seq (pre_p, copyin_seq);
8770 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8774 /* Expand code for an OpenMP single directive. */
8776 static void
8777 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8779 tree block;
8780 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
8781 gimple_seq bind_body, bind_body_tail = NULL, dlist;
8783 push_gimplify_context ();
8785 block = make_node (BLOCK);
8786 bind = gimple_build_bind (NULL, NULL, block);
8787 gsi_replace (gsi_p, bind, true);
8788 bind_body = NULL;
8789 dlist = NULL;
8790 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8791 &bind_body, &dlist, ctx, NULL);
8792 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8794 gimple_seq_add_stmt (&bind_body, single_stmt);
8796 if (ctx->record_type)
8797 lower_omp_single_copy (single_stmt, &bind_body, ctx);
8798 else
8799 lower_omp_single_simple (single_stmt, &bind_body);
8801 gimple_omp_set_body (single_stmt, NULL);
8803 gimple_seq_add_seq (&bind_body, dlist);
8805 bind_body = maybe_catch_exception (bind_body);
8807 t = gimple_build_omp_return
8808 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
8809 OMP_CLAUSE_NOWAIT));
8810 gimple_seq_add_stmt (&bind_body_tail, t);
8811 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
8812 if (ctx->record_type)
8814 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8815 tree clobber = build_constructor (ctx->record_type, NULL);
8816 TREE_THIS_VOLATILE (clobber) = 1;
8817 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8818 clobber), GSI_SAME_STMT);
8820 gimple_seq_add_seq (&bind_body, bind_body_tail);
8821 gimple_bind_set_body (bind, bind_body);
8823 pop_gimplify_context (bind);
8825 gimple_bind_append_vars (bind, ctx->block_vars);
8826 BLOCK_VARS (block) = ctx->block_vars;
8827 if (BLOCK_VARS (block))
8828 TREE_USED (block) = 1;
8832 /* Expand code for an OpenMP master directive. */
8834 static void
8835 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8837 tree block, lab = NULL, x, bfn_decl;
8838 gimple stmt = gsi_stmt (*gsi_p), bind;
8839 location_t loc = gimple_location (stmt);
8840 gimple_seq tseq;
8842 push_gimplify_context ();
8844 block = make_node (BLOCK);
8845 bind = gimple_build_bind (NULL, NULL, block);
8846 gsi_replace (gsi_p, bind, true);
8847 gimple_bind_add_stmt (bind, stmt);
8849 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8850 x = build_call_expr_loc (loc, bfn_decl, 0);
8851 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
8852 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
8853 tseq = NULL;
8854 gimplify_and_add (x, &tseq);
8855 gimple_bind_add_seq (bind, tseq);
8857 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8858 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8859 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8860 gimple_omp_set_body (stmt, NULL);
8862 gimple_bind_add_stmt (bind, gimple_build_label (lab));
8864 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8866 pop_gimplify_context (bind);
8868 gimple_bind_append_vars (bind, ctx->block_vars);
8869 BLOCK_VARS (block) = ctx->block_vars;
8873 /* Expand code for an OpenMP taskgroup directive. */
8875 static void
8876 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8878 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8879 tree block = make_node (BLOCK);
8881 bind = gimple_build_bind (NULL, NULL, block);
8882 gsi_replace (gsi_p, bind, true);
8883 gimple_bind_add_stmt (bind, stmt);
8885 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
8887 gimple_bind_add_stmt (bind, x);
8889 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8890 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8891 gimple_omp_set_body (stmt, NULL);
8893 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8895 gimple_bind_append_vars (bind, ctx->block_vars);
8896 BLOCK_VARS (block) = ctx->block_vars;
8900 /* Expand code for an OpenMP ordered directive. */
8902 static void
8903 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8905 tree block;
8906 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8908 push_gimplify_context ();
8910 block = make_node (BLOCK);
8911 bind = gimple_build_bind (NULL, NULL, block);
8912 gsi_replace (gsi_p, bind, true);
8913 gimple_bind_add_stmt (bind, stmt);
8915 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
8917 gimple_bind_add_stmt (bind, x);
8919 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8920 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8921 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8922 gimple_omp_set_body (stmt, NULL);
8924 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
8925 gimple_bind_add_stmt (bind, x);
8927 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8929 pop_gimplify_context (bind);
8931 gimple_bind_append_vars (bind, ctx->block_vars);
8932 BLOCK_VARS (block) = gimple_bind_vars (bind);
8936 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
8937 substitution of a couple of function calls. But in the NAMED case,
8938 requires that languages coordinate a symbol name. It is therefore
8939 best put here in common code. */
8941 static GTY((param1_is (tree), param2_is (tree)))
8942 splay_tree critical_name_mutexes;
8944 static void
8945 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8947 tree block;
8948 tree name, lock, unlock;
8949 gimple stmt = gsi_stmt (*gsi_p), bind;
8950 location_t loc = gimple_location (stmt);
8951 gimple_seq tbody;
8953 name = gimple_omp_critical_name (stmt);
8954 if (name)
8956 tree decl;
8957 splay_tree_node n;
8959 if (!critical_name_mutexes)
8960 critical_name_mutexes
8961 = splay_tree_new_ggc (splay_tree_compare_pointers,
8962 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
8963 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
8965 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
8966 if (n == NULL)
8968 char *new_str;
8970 decl = create_tmp_var_raw (ptr_type_node, NULL);
8972 new_str = ACONCAT ((".gomp_critical_user_",
8973 IDENTIFIER_POINTER (name), NULL));
8974 DECL_NAME (decl) = get_identifier (new_str);
8975 TREE_PUBLIC (decl) = 1;
8976 TREE_STATIC (decl) = 1;
8977 DECL_COMMON (decl) = 1;
8978 DECL_ARTIFICIAL (decl) = 1;
8979 DECL_IGNORED_P (decl) = 1;
8980 varpool_finalize_decl (decl);
8982 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
8983 (splay_tree_value) decl);
8985 else
8986 decl = (tree) n->value;
8988 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
8989 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
8991 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
8992 unlock = build_call_expr_loc (loc, unlock, 1,
8993 build_fold_addr_expr_loc (loc, decl));
8995 else
8997 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
8998 lock = build_call_expr_loc (loc, lock, 0);
9000 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
9001 unlock = build_call_expr_loc (loc, unlock, 0);
9004 push_gimplify_context ();
9006 block = make_node (BLOCK);
9007 bind = gimple_build_bind (NULL, NULL, block);
9008 gsi_replace (gsi_p, bind, true);
9009 gimple_bind_add_stmt (bind, stmt);
9011 tbody = gimple_bind_body (bind);
9012 gimplify_and_add (lock, &tbody);
9013 gimple_bind_set_body (bind, tbody);
9015 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9016 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9017 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9018 gimple_omp_set_body (stmt, NULL);
9020 tbody = gimple_bind_body (bind);
9021 gimplify_and_add (unlock, &tbody);
9022 gimple_bind_set_body (bind, tbody);
9024 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9026 pop_gimplify_context (bind);
9027 gimple_bind_append_vars (bind, ctx->block_vars);
9028 BLOCK_VARS (block) = gimple_bind_vars (bind);
9032 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9033 for a lastprivate clause. Given a loop control predicate of (V
9034 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9035 is appended to *DLIST, iterator initialization is appended to
9036 *BODY_P. */
9038 static void
9039 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
9040 gimple_seq *dlist, struct omp_context *ctx)
9042 tree clauses, cond, vinit;
9043 enum tree_code cond_code;
9044 gimple_seq stmts;
9046 cond_code = fd->loop.cond_code;
9047 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
9049 /* When possible, use a strict equality expression. This can let VRP
9050 type optimizations deduce the value and remove a copy. */
9051 if (tree_fits_shwi_p (fd->loop.step))
9053 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
9054 if (step == 1 || step == -1)
9055 cond_code = EQ_EXPR;
9058 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
9060 clauses = gimple_omp_for_clauses (fd->for_stmt);
9061 stmts = NULL;
9062 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
9063 if (!gimple_seq_empty_p (stmts))
9065 gimple_seq_add_seq (&stmts, *dlist);
9066 *dlist = stmts;
9068 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9069 vinit = fd->loop.n1;
9070 if (cond_code == EQ_EXPR
9071 && tree_fits_shwi_p (fd->loop.n2)
9072 && ! integer_zerop (fd->loop.n2))
9073 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
9074 else
9075 vinit = unshare_expr (vinit);
9077 /* Initialize the iterator variable, so that threads that don't execute
9078 any iterations don't execute the lastprivate clauses by accident. */
9079 gimplify_assign (fd->loop.v, vinit, body_p);
9084 /* Lower code for an OpenMP loop directive. */
9086 static void
9087 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9089 tree *rhs_p, block;
9090 struct omp_for_data fd, *fdp = NULL;
9091 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
9092 gimple_seq omp_for_body, body, dlist;
9093 size_t i;
9095 push_gimplify_context ();
9097 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
9099 block = make_node (BLOCK);
9100 new_stmt = gimple_build_bind (NULL, NULL, block);
9101 /* Replace at gsi right away, so that 'stmt' is no member
9102 of a sequence anymore as we're going to add to to a different
9103 one below. */
9104 gsi_replace (gsi_p, new_stmt, true);
9106 /* Move declaration of temporaries in the loop body before we make
9107 it go away. */
9108 omp_for_body = gimple_omp_body (stmt);
9109 if (!gimple_seq_empty_p (omp_for_body)
9110 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9112 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
9113 tree vars = gimple_bind_vars (inner_bind);
9114 gimple_bind_append_vars (new_stmt, vars);
9115 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9116 keep them on the inner_bind and it's block. */
9117 gimple_bind_set_vars (inner_bind, NULL_TREE);
9118 if (gimple_bind_block (inner_bind))
9119 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9122 if (gimple_omp_for_combined_into_p (stmt))
9124 extract_omp_for_data (stmt, &fd, NULL);
9125 fdp = &fd;
9127 /* We need two temporaries with fd.loop.v type (istart/iend)
9128 and then (fd.collapse - 1) temporaries with the same
9129 type for count2 ... countN-1 vars if not constant. */
9130 size_t count = 2;
9131 tree type = fd.iter_type;
9132 if (fd.collapse > 1
9133 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9134 count += fd.collapse - 1;
9135 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9136 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9137 tree clauses = *pc;
9138 if (parallel_for)
9139 outerc
9140 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9141 OMP_CLAUSE__LOOPTEMP_);
9142 for (i = 0; i < count; i++)
9144 tree temp;
9145 if (parallel_for)
9147 gcc_assert (outerc);
9148 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9149 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9150 OMP_CLAUSE__LOOPTEMP_);
9152 else
9154 temp = create_tmp_var (type, NULL);
9155 insert_decl_map (&ctx->outer->cb, temp, temp);
9157 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9158 OMP_CLAUSE_DECL (*pc) = temp;
9159 pc = &OMP_CLAUSE_CHAIN (*pc);
9161 *pc = clauses;
9164 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9165 dlist = NULL;
9166 body = NULL;
9167 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9168 fdp);
9169 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9171 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9173 /* Lower the header expressions. At this point, we can assume that
9174 the header is of the form:
9176 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9178 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9179 using the .omp_data_s mapping, if needed. */
9180 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9182 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9183 if (!is_gimple_min_invariant (*rhs_p))
9184 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9186 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9187 if (!is_gimple_min_invariant (*rhs_p))
9188 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9190 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9191 if (!is_gimple_min_invariant (*rhs_p))
9192 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9195 /* Once lowered, extract the bounds and clauses. */
9196 extract_omp_for_data (stmt, &fd, NULL);
9198 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9200 gimple_seq_add_stmt (&body, stmt);
9201 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9203 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9204 fd.loop.v));
9206 /* After the loop, add exit clauses. */
9207 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9209 if (ctx->cancellable)
9210 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9212 gimple_seq_add_seq (&body, dlist);
9214 body = maybe_catch_exception (body);
9216 /* Region exit marker goes at the end of the loop body. */
9217 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9218 maybe_add_implicit_barrier_cancel (ctx, &body);
9219 pop_gimplify_context (new_stmt);
9221 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9222 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9223 if (BLOCK_VARS (block))
9224 TREE_USED (block) = 1;
9226 gimple_bind_set_body (new_stmt, body);
9227 gimple_omp_set_body (stmt, NULL);
9228 gimple_omp_for_set_pre_body (stmt, NULL);
9231 /* Callback for walk_stmts. Check if the current statement only contains
9232 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9234 static tree
9235 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9236 bool *handled_ops_p,
9237 struct walk_stmt_info *wi)
9239 int *info = (int *) wi->info;
9240 gimple stmt = gsi_stmt (*gsi_p);
9242 *handled_ops_p = true;
9243 switch (gimple_code (stmt))
9245 WALK_SUBSTMTS;
9247 case GIMPLE_OMP_FOR:
9248 case GIMPLE_OMP_SECTIONS:
9249 *info = *info == 0 ? 1 : -1;
9250 break;
9251 default:
9252 *info = -1;
9253 break;
9255 return NULL;
9258 struct omp_taskcopy_context
9260 /* This field must be at the beginning, as we do "inheritance": Some
9261 callback functions for tree-inline.c (e.g., omp_copy_decl)
9262 receive a copy_body_data pointer that is up-casted to an
9263 omp_context pointer. */
9264 copy_body_data cb;
9265 omp_context *ctx;
9268 static tree
9269 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9271 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9273 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9274 return create_tmp_var (TREE_TYPE (var), NULL);
9276 return var;
9279 static tree
9280 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9282 tree name, new_fields = NULL, type, f;
9284 type = lang_hooks.types.make_type (RECORD_TYPE);
9285 name = DECL_NAME (TYPE_NAME (orig_type));
9286 name = build_decl (gimple_location (tcctx->ctx->stmt),
9287 TYPE_DECL, name, type);
9288 TYPE_NAME (type) = name;
9290 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9292 tree new_f = copy_node (f);
9293 DECL_CONTEXT (new_f) = type;
9294 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9295 TREE_CHAIN (new_f) = new_fields;
9296 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9297 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9298 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9299 &tcctx->cb, NULL);
9300 new_fields = new_f;
9301 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
9303 TYPE_FIELDS (type) = nreverse (new_fields);
9304 layout_type (type);
9305 return type;
9308 /* Create task copyfn. */
9310 static void
9311 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9313 struct function *child_cfun;
9314 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9315 tree record_type, srecord_type, bind, list;
9316 bool record_needs_remap = false, srecord_needs_remap = false;
9317 splay_tree_node n;
9318 struct omp_taskcopy_context tcctx;
9319 location_t loc = gimple_location (task_stmt);
9321 child_fn = gimple_omp_task_copy_fn (task_stmt);
9322 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9323 gcc_assert (child_cfun->cfg == NULL);
9324 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9326 /* Reset DECL_CONTEXT on function arguments. */
9327 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9328 DECL_CONTEXT (t) = child_fn;
9330 /* Populate the function. */
9331 push_gimplify_context ();
9332 push_cfun (child_cfun);
9334 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9335 TREE_SIDE_EFFECTS (bind) = 1;
9336 list = NULL;
9337 DECL_SAVED_TREE (child_fn) = bind;
9338 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9340 /* Remap src and dst argument types if needed. */
9341 record_type = ctx->record_type;
9342 srecord_type = ctx->srecord_type;
9343 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9344 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9346 record_needs_remap = true;
9347 break;
9349 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9350 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9352 srecord_needs_remap = true;
9353 break;
9356 if (record_needs_remap || srecord_needs_remap)
9358 memset (&tcctx, '\0', sizeof (tcctx));
9359 tcctx.cb.src_fn = ctx->cb.src_fn;
9360 tcctx.cb.dst_fn = child_fn;
9361 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
9362 gcc_checking_assert (tcctx.cb.src_node);
9363 tcctx.cb.dst_node = tcctx.cb.src_node;
9364 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9365 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9366 tcctx.cb.eh_lp_nr = 0;
9367 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9368 tcctx.cb.decl_map = pointer_map_create ();
9369 tcctx.ctx = ctx;
9371 if (record_needs_remap)
9372 record_type = task_copyfn_remap_type (&tcctx, record_type);
9373 if (srecord_needs_remap)
9374 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9376 else
9377 tcctx.cb.decl_map = NULL;
9379 arg = DECL_ARGUMENTS (child_fn);
9380 TREE_TYPE (arg) = build_pointer_type (record_type);
9381 sarg = DECL_CHAIN (arg);
9382 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9384 /* First pass: initialize temporaries used in record_type and srecord_type
9385 sizes and field offsets. */
9386 if (tcctx.cb.decl_map)
9387 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9388 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9390 tree *p;
9392 decl = OMP_CLAUSE_DECL (c);
9393 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
9394 if (p == NULL)
9395 continue;
9396 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9397 sf = (tree) n->value;
9398 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9399 src = build_simple_mem_ref_loc (loc, sarg);
9400 src = omp_build_component_ref (src, sf);
9401 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9402 append_to_statement_list (t, &list);
9405 /* Second pass: copy shared var pointers and copy construct non-VLA
9406 firstprivate vars. */
9407 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9408 switch (OMP_CLAUSE_CODE (c))
9410 case OMP_CLAUSE_SHARED:
9411 decl = OMP_CLAUSE_DECL (c);
9412 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9413 if (n == NULL)
9414 break;
9415 f = (tree) n->value;
9416 if (tcctx.cb.decl_map)
9417 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9418 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9419 sf = (tree) n->value;
9420 if (tcctx.cb.decl_map)
9421 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9422 src = build_simple_mem_ref_loc (loc, sarg);
9423 src = omp_build_component_ref (src, sf);
9424 dst = build_simple_mem_ref_loc (loc, arg);
9425 dst = omp_build_component_ref (dst, f);
9426 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9427 append_to_statement_list (t, &list);
9428 break;
9429 case OMP_CLAUSE_FIRSTPRIVATE:
9430 decl = OMP_CLAUSE_DECL (c);
9431 if (is_variable_sized (decl))
9432 break;
9433 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9434 if (n == NULL)
9435 break;
9436 f = (tree) n->value;
9437 if (tcctx.cb.decl_map)
9438 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9439 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9440 if (n != NULL)
9442 sf = (tree) n->value;
9443 if (tcctx.cb.decl_map)
9444 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9445 src = build_simple_mem_ref_loc (loc, sarg);
9446 src = omp_build_component_ref (src, sf);
9447 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9448 src = build_simple_mem_ref_loc (loc, src);
9450 else
9451 src = decl;
9452 dst = build_simple_mem_ref_loc (loc, arg);
9453 dst = omp_build_component_ref (dst, f);
9454 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9455 append_to_statement_list (t, &list);
9456 break;
9457 case OMP_CLAUSE_PRIVATE:
9458 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9459 break;
9460 decl = OMP_CLAUSE_DECL (c);
9461 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9462 f = (tree) n->value;
9463 if (tcctx.cb.decl_map)
9464 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9465 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9466 if (n != NULL)
9468 sf = (tree) n->value;
9469 if (tcctx.cb.decl_map)
9470 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9471 src = build_simple_mem_ref_loc (loc, sarg);
9472 src = omp_build_component_ref (src, sf);
9473 if (use_pointer_for_field (decl, NULL))
9474 src = build_simple_mem_ref_loc (loc, src);
9476 else
9477 src = decl;
9478 dst = build_simple_mem_ref_loc (loc, arg);
9479 dst = omp_build_component_ref (dst, f);
9480 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9481 append_to_statement_list (t, &list);
9482 break;
9483 default:
9484 break;
9487 /* Last pass: handle VLA firstprivates. */
9488 if (tcctx.cb.decl_map)
9489 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9490 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9492 tree ind, ptr, df;
9494 decl = OMP_CLAUSE_DECL (c);
9495 if (!is_variable_sized (decl))
9496 continue;
9497 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9498 if (n == NULL)
9499 continue;
9500 f = (tree) n->value;
9501 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9502 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9503 ind = DECL_VALUE_EXPR (decl);
9504 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9505 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9506 n = splay_tree_lookup (ctx->sfield_map,
9507 (splay_tree_key) TREE_OPERAND (ind, 0));
9508 sf = (tree) n->value;
9509 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9510 src = build_simple_mem_ref_loc (loc, sarg);
9511 src = omp_build_component_ref (src, sf);
9512 src = build_simple_mem_ref_loc (loc, src);
9513 dst = build_simple_mem_ref_loc (loc, arg);
9514 dst = omp_build_component_ref (dst, f);
9515 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9516 append_to_statement_list (t, &list);
9517 n = splay_tree_lookup (ctx->field_map,
9518 (splay_tree_key) TREE_OPERAND (ind, 0));
9519 df = (tree) n->value;
9520 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
9521 ptr = build_simple_mem_ref_loc (loc, arg);
9522 ptr = omp_build_component_ref (ptr, df);
9523 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9524 build_fold_addr_expr_loc (loc, dst));
9525 append_to_statement_list (t, &list);
9528 t = build1 (RETURN_EXPR, void_type_node, NULL);
9529 append_to_statement_list (t, &list);
9531 if (tcctx.cb.decl_map)
9532 pointer_map_destroy (tcctx.cb.decl_map);
9533 pop_gimplify_context (NULL);
9534 BIND_EXPR_BODY (bind) = list;
9535 pop_cfun ();
9538 static void
9539 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9541 tree c, clauses;
9542 gimple g;
9543 size_t n_in = 0, n_out = 0, idx = 2, i;
9545 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9546 OMP_CLAUSE_DEPEND);
9547 gcc_assert (clauses);
9548 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9549 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9550 switch (OMP_CLAUSE_DEPEND_KIND (c))
9552 case OMP_CLAUSE_DEPEND_IN:
9553 n_in++;
9554 break;
9555 case OMP_CLAUSE_DEPEND_OUT:
9556 case OMP_CLAUSE_DEPEND_INOUT:
9557 n_out++;
9558 break;
9559 default:
9560 gcc_unreachable ();
9562 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9563 tree array = create_tmp_var (type, NULL);
9564 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9565 NULL_TREE);
9566 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9567 gimple_seq_add_stmt (iseq, g);
9568 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9569 NULL_TREE);
9570 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9571 gimple_seq_add_stmt (iseq, g);
9572 for (i = 0; i < 2; i++)
9574 if ((i ? n_in : n_out) == 0)
9575 continue;
9576 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9577 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9578 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9580 tree t = OMP_CLAUSE_DECL (c);
9581 t = fold_convert (ptr_type_node, t);
9582 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9583 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9584 NULL_TREE, NULL_TREE);
9585 g = gimple_build_assign (r, t);
9586 gimple_seq_add_stmt (iseq, g);
9589 tree *p = gimple_omp_task_clauses_ptr (stmt);
9590 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9591 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9592 OMP_CLAUSE_CHAIN (c) = *p;
9593 *p = c;
9594 tree clobber = build_constructor (type, NULL);
9595 TREE_THIS_VOLATILE (clobber) = 1;
9596 g = gimple_build_assign (array, clobber);
9597 gimple_seq_add_stmt (oseq, g);
9600 /* Lower the OpenMP parallel or task directive in the current statement
9601 in GSI_P. CTX holds context information for the directive. */
9603 static void
9604 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9606 tree clauses;
9607 tree child_fn, t;
9608 gimple stmt = gsi_stmt (*gsi_p);
9609 gimple par_bind, bind, dep_bind = NULL;
9610 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9611 location_t loc = gimple_location (stmt);
9613 clauses = gimple_omp_taskreg_clauses (stmt);
9614 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9615 par_body = gimple_bind_body (par_bind);
9616 child_fn = ctx->cb.dst_fn;
9617 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9618 && !gimple_omp_parallel_combined_p (stmt))
9620 struct walk_stmt_info wi;
9621 int ws_num = 0;
9623 memset (&wi, 0, sizeof (wi));
9624 wi.info = &ws_num;
9625 wi.val_only = true;
9626 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9627 if (ws_num == 1)
9628 gimple_omp_parallel_set_combined_p (stmt, true);
9630 gimple_seq dep_ilist = NULL;
9631 gimple_seq dep_olist = NULL;
9632 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9633 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9635 push_gimplify_context ();
9636 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9637 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9640 if (ctx->srecord_type)
9641 create_task_copyfn (stmt, ctx);
9643 push_gimplify_context ();
9645 par_olist = NULL;
9646 par_ilist = NULL;
9647 par_rlist = NULL;
9648 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9649 lower_omp (&par_body, ctx);
9650 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9651 lower_reduction_clauses (clauses, &par_rlist, ctx);
9653 /* Declare all the variables created by mapping and the variables
9654 declared in the scope of the parallel body. */
9655 record_vars_into (ctx->block_vars, child_fn);
9656 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9658 if (ctx->record_type)
9660 ctx->sender_decl
9661 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9662 : ctx->record_type, ".omp_data_o");
9663 DECL_NAMELESS (ctx->sender_decl) = 1;
9664 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9665 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9668 olist = NULL;
9669 ilist = NULL;
9670 lower_send_clauses (clauses, &ilist, &olist, ctx);
9671 lower_send_shared_vars (&ilist, &olist, ctx);
9673 if (ctx->record_type)
9675 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9676 TREE_THIS_VOLATILE (clobber) = 1;
9677 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9678 clobber));
9681 /* Once all the expansions are done, sequence all the different
9682 fragments inside gimple_omp_body. */
9684 new_body = NULL;
9686 if (ctx->record_type)
9688 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9689 /* fixup_child_record_type might have changed receiver_decl's type. */
9690 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9691 gimple_seq_add_stmt (&new_body,
9692 gimple_build_assign (ctx->receiver_decl, t));
9695 gimple_seq_add_seq (&new_body, par_ilist);
9696 gimple_seq_add_seq (&new_body, par_body);
9697 gimple_seq_add_seq (&new_body, par_rlist);
9698 if (ctx->cancellable)
9699 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9700 gimple_seq_add_seq (&new_body, par_olist);
9701 new_body = maybe_catch_exception (new_body);
9702 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9703 gimple_omp_set_body (stmt, new_body);
9705 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9706 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
9707 gimple_bind_add_seq (bind, ilist);
9708 gimple_bind_add_stmt (bind, stmt);
9709 gimple_bind_add_seq (bind, olist);
9711 pop_gimplify_context (NULL);
9713 if (dep_bind)
9715 gimple_bind_add_seq (dep_bind, dep_ilist);
9716 gimple_bind_add_stmt (dep_bind, bind);
9717 gimple_bind_add_seq (dep_bind, dep_olist);
9718 pop_gimplify_context (dep_bind);
9722 /* Lower the OpenMP target directive in the current statement
9723 in GSI_P. CTX holds context information for the directive. */
9725 static void
9726 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9728 tree clauses;
9729 tree child_fn, t, c;
9730 gimple stmt = gsi_stmt (*gsi_p);
9731 gimple tgt_bind = NULL, bind;
9732 gimple_seq tgt_body = NULL, olist, ilist, new_body;
9733 location_t loc = gimple_location (stmt);
9734 int kind = gimple_omp_target_kind (stmt);
9735 unsigned int map_cnt = 0;
9737 clauses = gimple_omp_target_clauses (stmt);
9738 if (kind == GF_OMP_TARGET_KIND_REGION)
9740 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9741 tgt_body = gimple_bind_body (tgt_bind);
9743 else if (kind == GF_OMP_TARGET_KIND_DATA)
9744 tgt_body = gimple_omp_body (stmt);
9745 child_fn = ctx->cb.dst_fn;
9747 push_gimplify_context ();
9749 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9750 switch (OMP_CLAUSE_CODE (c))
9752 tree var, x;
9754 default:
9755 break;
9756 case OMP_CLAUSE_MAP:
9757 case OMP_CLAUSE_TO:
9758 case OMP_CLAUSE_FROM:
9759 var = OMP_CLAUSE_DECL (c);
9760 if (!DECL_P (var))
9762 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
9763 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9764 map_cnt++;
9765 continue;
9768 if (DECL_SIZE (var)
9769 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
9771 tree var2 = DECL_VALUE_EXPR (var);
9772 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
9773 var2 = TREE_OPERAND (var2, 0);
9774 gcc_assert (DECL_P (var2));
9775 var = var2;
9778 if (!maybe_lookup_field (var, ctx))
9779 continue;
9781 if (kind == GF_OMP_TARGET_KIND_REGION)
9783 x = build_receiver_ref (var, true, ctx);
9784 tree new_var = lookup_decl (var, ctx);
9785 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9786 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9787 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9788 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
9789 x = build_simple_mem_ref (x);
9790 SET_DECL_VALUE_EXPR (new_var, x);
9791 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
9793 map_cnt++;
9796 if (kind == GF_OMP_TARGET_KIND_REGION)
9798 target_nesting_level++;
9799 lower_omp (&tgt_body, ctx);
9800 target_nesting_level--;
9802 else if (kind == GF_OMP_TARGET_KIND_DATA)
9803 lower_omp (&tgt_body, ctx);
9805 if (kind == GF_OMP_TARGET_KIND_REGION)
9807 /* Declare all the variables created by mapping and the variables
9808 declared in the scope of the target body. */
9809 record_vars_into (ctx->block_vars, child_fn);
9810 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
9813 olist = NULL;
9814 ilist = NULL;
9815 if (ctx->record_type)
9817 ctx->sender_decl
9818 = create_tmp_var (ctx->record_type, ".omp_data_arr");
9819 DECL_NAMELESS (ctx->sender_decl) = 1;
9820 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9821 t = make_tree_vec (3);
9822 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
9823 TREE_VEC_ELT (t, 1)
9824 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
9825 ".omp_data_sizes");
9826 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
9827 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
9828 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
9829 TREE_VEC_ELT (t, 2)
9830 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
9831 map_cnt),
9832 ".omp_data_kinds");
9833 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
9834 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
9835 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
9836 gimple_omp_target_set_data_arg (stmt, t);
9838 vec<constructor_elt, va_gc> *vsize;
9839 vec<constructor_elt, va_gc> *vkind;
9840 vec_alloc (vsize, map_cnt);
9841 vec_alloc (vkind, map_cnt);
9842 unsigned int map_idx = 0;
9844 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9845 switch (OMP_CLAUSE_CODE (c))
9847 tree ovar, nc;
9849 default:
9850 break;
9851 case OMP_CLAUSE_MAP:
9852 case OMP_CLAUSE_TO:
9853 case OMP_CLAUSE_FROM:
9854 nc = c;
9855 ovar = OMP_CLAUSE_DECL (c);
9856 if (!DECL_P (ovar))
9858 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9859 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9861 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
9862 == get_base_address (ovar));
9863 nc = OMP_CLAUSE_CHAIN (c);
9864 ovar = OMP_CLAUSE_DECL (nc);
9866 else
9868 tree x = build_sender_ref (ovar, ctx);
9869 tree v
9870 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
9871 gimplify_assign (x, v, &ilist);
9872 nc = NULL_TREE;
9875 else
9877 if (DECL_SIZE (ovar)
9878 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
9880 tree ovar2 = DECL_VALUE_EXPR (ovar);
9881 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
9882 ovar2 = TREE_OPERAND (ovar2, 0);
9883 gcc_assert (DECL_P (ovar2));
9884 ovar = ovar2;
9886 if (!maybe_lookup_field (ovar, ctx))
9887 continue;
9890 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
9891 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
9892 talign = DECL_ALIGN_UNIT (ovar);
9893 if (nc)
9895 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
9896 tree x = build_sender_ref (ovar, ctx);
9897 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9898 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9899 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9900 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
9902 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9903 tree avar
9904 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
9905 mark_addressable (avar);
9906 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
9907 talign = DECL_ALIGN_UNIT (avar);
9908 avar = build_fold_addr_expr (avar);
9909 gimplify_assign (x, avar, &ilist);
9911 else if (is_gimple_reg (var))
9913 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9914 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
9915 mark_addressable (avar);
9916 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
9917 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
9918 gimplify_assign (avar, var, &ilist);
9919 avar = build_fold_addr_expr (avar);
9920 gimplify_assign (x, avar, &ilist);
9921 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
9922 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
9923 && !TYPE_READONLY (TREE_TYPE (var)))
9925 x = build_sender_ref (ovar, ctx);
9926 x = build_simple_mem_ref (x);
9927 gimplify_assign (var, x, &olist);
9930 else
9932 var = build_fold_addr_expr (var);
9933 gimplify_assign (x, var, &ilist);
9936 tree s = OMP_CLAUSE_SIZE (c);
9937 if (s == NULL_TREE)
9938 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
9939 s = fold_convert (size_type_node, s);
9940 tree purpose = size_int (map_idx++);
9941 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
9942 if (TREE_CODE (s) != INTEGER_CST)
9943 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
9945 unsigned char tkind = 0;
9946 switch (OMP_CLAUSE_CODE (c))
9948 case OMP_CLAUSE_MAP:
9949 tkind = OMP_CLAUSE_MAP_KIND (c);
9950 break;
9951 case OMP_CLAUSE_TO:
9952 tkind = OMP_CLAUSE_MAP_TO;
9953 break;
9954 case OMP_CLAUSE_FROM:
9955 tkind = OMP_CLAUSE_MAP_FROM;
9956 break;
9957 default:
9958 gcc_unreachable ();
9960 talign = ceil_log2 (talign);
9961 tkind |= talign << 3;
9962 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
9963 build_int_cst (unsigned_char_type_node,
9964 tkind));
9965 if (nc && nc != c)
9966 c = nc;
9969 gcc_assert (map_idx == map_cnt);
9971 DECL_INITIAL (TREE_VEC_ELT (t, 1))
9972 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
9973 DECL_INITIAL (TREE_VEC_ELT (t, 2))
9974 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
9975 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
9977 gimple_seq initlist = NULL;
9978 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
9979 TREE_VEC_ELT (t, 1)),
9980 &initlist, true, NULL_TREE);
9981 gimple_seq_add_seq (&ilist, initlist);
9983 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
9984 NULL);
9985 TREE_THIS_VOLATILE (clobber) = 1;
9986 gimple_seq_add_stmt (&olist,
9987 gimple_build_assign (TREE_VEC_ELT (t, 1),
9988 clobber));
9991 tree clobber = build_constructor (ctx->record_type, NULL);
9992 TREE_THIS_VOLATILE (clobber) = 1;
9993 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9994 clobber));
9997 /* Once all the expansions are done, sequence all the different
9998 fragments inside gimple_omp_body. */
10000 new_body = NULL;
10002 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
10004 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10005 /* fixup_child_record_type might have changed receiver_decl's type. */
10006 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10007 gimple_seq_add_stmt (&new_body,
10008 gimple_build_assign (ctx->receiver_decl, t));
10011 if (kind == GF_OMP_TARGET_KIND_REGION)
10013 gimple_seq_add_seq (&new_body, tgt_body);
10014 new_body = maybe_catch_exception (new_body);
10016 else if (kind == GF_OMP_TARGET_KIND_DATA)
10017 new_body = tgt_body;
10018 if (kind != GF_OMP_TARGET_KIND_UPDATE)
10020 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10021 gimple_omp_set_body (stmt, new_body);
10024 bind = gimple_build_bind (NULL, NULL,
10025 tgt_bind ? gimple_bind_block (tgt_bind)
10026 : NULL_TREE);
10027 gsi_replace (gsi_p, bind, true);
10028 gimple_bind_add_seq (bind, ilist);
10029 gimple_bind_add_stmt (bind, stmt);
10030 gimple_bind_add_seq (bind, olist);
10032 pop_gimplify_context (NULL);
10035 /* Expand code for an OpenMP teams directive. */
10037 static void
10038 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10040 gimple teams_stmt = gsi_stmt (*gsi_p);
10041 push_gimplify_context ();
10043 tree block = make_node (BLOCK);
10044 gimple bind = gimple_build_bind (NULL, NULL, block);
10045 gsi_replace (gsi_p, bind, true);
10046 gimple_seq bind_body = NULL;
10047 gimple_seq dlist = NULL;
10048 gimple_seq olist = NULL;
10050 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10051 OMP_CLAUSE_NUM_TEAMS);
10052 if (num_teams == NULL_TREE)
10053 num_teams = build_int_cst (unsigned_type_node, 0);
10054 else
10056 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
10057 num_teams = fold_convert (unsigned_type_node, num_teams);
10058 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
10060 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10061 OMP_CLAUSE_THREAD_LIMIT);
10062 if (thread_limit == NULL_TREE)
10063 thread_limit = build_int_cst (unsigned_type_node, 0);
10064 else
10066 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10067 thread_limit = fold_convert (unsigned_type_node, thread_limit);
10068 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
10069 fb_rvalue);
10072 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
10073 &bind_body, &dlist, ctx, NULL);
10074 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
10075 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
10076 gimple_seq_add_stmt (&bind_body, teams_stmt);
10078 location_t loc = gimple_location (teams_stmt);
10079 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
10080 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10081 gimple_set_location (call, loc);
10082 gimple_seq_add_stmt (&bind_body, call);
10084 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10085 gimple_omp_set_body (teams_stmt, NULL);
10086 gimple_seq_add_seq (&bind_body, olist);
10087 gimple_seq_add_seq (&bind_body, dlist);
10088 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10089 gimple_bind_set_body (bind, bind_body);
10091 pop_gimplify_context (bind);
10093 gimple_bind_append_vars (bind, ctx->block_vars);
10094 BLOCK_VARS (block) = ctx->block_vars;
10095 if (BLOCK_VARS (block))
10096 TREE_USED (block) = 1;
10100 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10101 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10102 of OpenMP context, but with task_shared_vars set. */
10104 static tree
10105 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10106 void *data)
10108 tree t = *tp;
10110 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10111 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
10112 return t;
10114 if (task_shared_vars
10115 && DECL_P (t)
10116 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10117 return t;
10119 /* If a global variable has been privatized, TREE_CONSTANT on
10120 ADDR_EXPR might be wrong. */
10121 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10122 recompute_tree_invariant_for_addr_expr (t);
10124 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10125 return NULL_TREE;
10128 static void
10129 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10131 gimple stmt = gsi_stmt (*gsi_p);
10132 struct walk_stmt_info wi;
10134 if (gimple_has_location (stmt))
10135 input_location = gimple_location (stmt);
10137 if (task_shared_vars)
10138 memset (&wi, '\0', sizeof (wi));
10140 /* If we have issued syntax errors, avoid doing any heavy lifting.
10141 Just replace the OpenMP directives with a NOP to avoid
10142 confusing RTL expansion. */
10143 if (seen_error () && is_gimple_omp (stmt))
10145 gsi_replace (gsi_p, gimple_build_nop (), true);
10146 return;
10149 switch (gimple_code (stmt))
10151 case GIMPLE_COND:
10152 if ((ctx || task_shared_vars)
10153 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
10154 ctx ? NULL : &wi, NULL)
10155 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
10156 ctx ? NULL : &wi, NULL)))
10157 gimple_regimplify_operands (stmt, gsi_p);
10158 break;
10159 case GIMPLE_CATCH:
10160 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
10161 break;
10162 case GIMPLE_EH_FILTER:
10163 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10164 break;
10165 case GIMPLE_TRY:
10166 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10167 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10168 break;
10169 case GIMPLE_TRANSACTION:
10170 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
10171 break;
10172 case GIMPLE_BIND:
10173 lower_omp (gimple_bind_body_ptr (stmt), ctx);
10174 break;
10175 case GIMPLE_OMP_PARALLEL:
10176 case GIMPLE_OMP_TASK:
10177 ctx = maybe_lookup_ctx (stmt);
10178 gcc_assert (ctx);
10179 if (ctx->cancellable)
10180 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10181 lower_omp_taskreg (gsi_p, ctx);
10182 break;
10183 case GIMPLE_OMP_FOR:
10184 ctx = maybe_lookup_ctx (stmt);
10185 gcc_assert (ctx);
10186 if (ctx->cancellable)
10187 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10188 lower_omp_for (gsi_p, ctx);
10189 break;
10190 case GIMPLE_OMP_SECTIONS:
10191 ctx = maybe_lookup_ctx (stmt);
10192 gcc_assert (ctx);
10193 if (ctx->cancellable)
10194 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10195 lower_omp_sections (gsi_p, ctx);
10196 break;
10197 case GIMPLE_OMP_SINGLE:
10198 ctx = maybe_lookup_ctx (stmt);
10199 gcc_assert (ctx);
10200 lower_omp_single (gsi_p, ctx);
10201 break;
10202 case GIMPLE_OMP_MASTER:
10203 ctx = maybe_lookup_ctx (stmt);
10204 gcc_assert (ctx);
10205 lower_omp_master (gsi_p, ctx);
10206 break;
10207 case GIMPLE_OMP_TASKGROUP:
10208 ctx = maybe_lookup_ctx (stmt);
10209 gcc_assert (ctx);
10210 lower_omp_taskgroup (gsi_p, ctx);
10211 break;
10212 case GIMPLE_OMP_ORDERED:
10213 ctx = maybe_lookup_ctx (stmt);
10214 gcc_assert (ctx);
10215 lower_omp_ordered (gsi_p, ctx);
10216 break;
10217 case GIMPLE_OMP_CRITICAL:
10218 ctx = maybe_lookup_ctx (stmt);
10219 gcc_assert (ctx);
10220 lower_omp_critical (gsi_p, ctx);
10221 break;
10222 case GIMPLE_OMP_ATOMIC_LOAD:
10223 if ((ctx || task_shared_vars)
10224 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
10225 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10226 gimple_regimplify_operands (stmt, gsi_p);
10227 break;
10228 case GIMPLE_OMP_TARGET:
10229 ctx = maybe_lookup_ctx (stmt);
10230 gcc_assert (ctx);
10231 lower_omp_target (gsi_p, ctx);
10232 break;
10233 case GIMPLE_OMP_TEAMS:
10234 ctx = maybe_lookup_ctx (stmt);
10235 gcc_assert (ctx);
10236 lower_omp_teams (gsi_p, ctx);
10237 break;
10238 case GIMPLE_CALL:
10239 tree fndecl;
10240 fndecl = gimple_call_fndecl (stmt);
10241 if (fndecl
10242 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10243 switch (DECL_FUNCTION_CODE (fndecl))
10245 case BUILT_IN_GOMP_BARRIER:
10246 if (ctx == NULL)
10247 break;
10248 /* FALLTHRU */
10249 case BUILT_IN_GOMP_CANCEL:
10250 case BUILT_IN_GOMP_CANCELLATION_POINT:
10251 omp_context *cctx;
10252 cctx = ctx;
10253 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10254 cctx = cctx->outer;
10255 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10256 if (!cctx->cancellable)
10258 if (DECL_FUNCTION_CODE (fndecl)
10259 == BUILT_IN_GOMP_CANCELLATION_POINT)
10261 stmt = gimple_build_nop ();
10262 gsi_replace (gsi_p, stmt, false);
10264 break;
10266 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10268 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10269 gimple_call_set_fndecl (stmt, fndecl);
10270 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10272 tree lhs;
10273 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
10274 gimple_call_set_lhs (stmt, lhs);
10275 tree fallthru_label;
10276 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10277 gimple g;
10278 g = gimple_build_label (fallthru_label);
10279 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10280 g = gimple_build_cond (NE_EXPR, lhs,
10281 fold_convert (TREE_TYPE (lhs),
10282 boolean_false_node),
10283 cctx->cancel_label, fallthru_label);
10284 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10285 break;
10286 default:
10287 break;
10289 /* FALLTHRU */
10290 default:
10291 if ((ctx || task_shared_vars)
10292 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10293 ctx ? NULL : &wi))
10295 /* Just remove clobbers, this should happen only if we have
10296 "privatized" local addressable variables in SIMD regions,
10297 the clobber isn't needed in that case and gimplifying address
10298 of the ARRAY_REF into a pointer and creating MEM_REF based
10299 clobber would create worse code than we get with the clobber
10300 dropped. */
10301 if (gimple_clobber_p (stmt))
10303 gsi_replace (gsi_p, gimple_build_nop (), true);
10304 break;
10306 gimple_regimplify_operands (stmt, gsi_p);
10308 break;
10312 static void
10313 lower_omp (gimple_seq *body, omp_context *ctx)
10315 location_t saved_location = input_location;
10316 gimple_stmt_iterator gsi;
10317 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10318 lower_omp_1 (&gsi, ctx);
10319 /* During gimplification, we have not always invoked fold_stmt
10320 (gimplify.c:maybe_fold_stmt); call it now. */
10321 if (target_nesting_level)
10322 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10323 fold_stmt (&gsi);
10324 input_location = saved_location;
10327 /* Main entry point. */
10329 static unsigned int
10330 execute_lower_omp (void)
10332 gimple_seq body;
10333 int i;
10334 omp_context *ctx;
10336 /* This pass always runs, to provide PROP_gimple_lomp.
10337 But there is nothing to do unless -fopenmp is given. */
10338 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10339 return 0;
10341 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10342 delete_omp_context);
10344 body = gimple_body (current_function_decl);
10345 scan_omp (&body, NULL);
10346 gcc_assert (taskreg_nesting_level == 0);
10347 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
10348 finish_taskreg_scan (ctx);
10349 taskreg_contexts.release ();
10351 if (all_contexts->root)
10353 if (task_shared_vars)
10354 push_gimplify_context ();
10355 lower_omp (&body, NULL);
10356 if (task_shared_vars)
10357 pop_gimplify_context (NULL);
10360 if (all_contexts)
10362 splay_tree_delete (all_contexts);
10363 all_contexts = NULL;
10365 BITMAP_FREE (task_shared_vars);
10366 return 0;
10369 namespace {
10371 const pass_data pass_data_lower_omp =
10373 GIMPLE_PASS, /* type */
10374 "omplower", /* name */
10375 OPTGROUP_NONE, /* optinfo_flags */
10376 false, /* has_gate */
10377 true, /* has_execute */
10378 TV_NONE, /* tv_id */
10379 PROP_gimple_any, /* properties_required */
10380 PROP_gimple_lomp, /* properties_provided */
10381 0, /* properties_destroyed */
10382 0, /* todo_flags_start */
10383 0, /* todo_flags_finish */
10386 class pass_lower_omp : public gimple_opt_pass
10388 public:
10389 pass_lower_omp (gcc::context *ctxt)
10390 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10393 /* opt_pass methods: */
10394 unsigned int execute () { return execute_lower_omp (); }
10396 }; // class pass_lower_omp
10398 } // anon namespace
10400 gimple_opt_pass *
10401 make_pass_lower_omp (gcc::context *ctxt)
10403 return new pass_lower_omp (ctxt);
10406 /* The following is a utility to diagnose OpenMP structured block violations.
10407 It is not part of the "omplower" pass, as that's invoked too late. It
10408 should be invoked by the respective front ends after gimplification. */
10410 static splay_tree all_labels;
10412 /* Check for mismatched contexts and generate an error if needed. Return
10413 true if an error is detected. */
10415 static bool
10416 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10417 gimple branch_ctx, gimple label_ctx)
10419 if (label_ctx == branch_ctx)
10420 return false;
10424 Previously we kept track of the label's entire context in diagnose_sb_[12]
10425 so we could traverse it and issue a correct "exit" or "enter" error
10426 message upon a structured block violation.
10428 We built the context by building a list with tree_cons'ing, but there is
10429 no easy counterpart in gimple tuples. It seems like far too much work
10430 for issuing exit/enter error messages. If someone really misses the
10431 distinct error message... patches welcome.
10434 #if 0
10435 /* Try to avoid confusing the user by producing and error message
10436 with correct "exit" or "enter" verbiage. We prefer "exit"
10437 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10438 if (branch_ctx == NULL)
10439 exit_p = false;
10440 else
10442 while (label_ctx)
10444 if (TREE_VALUE (label_ctx) == branch_ctx)
10446 exit_p = false;
10447 break;
10449 label_ctx = TREE_CHAIN (label_ctx);
10453 if (exit_p)
10454 error ("invalid exit from OpenMP structured block");
10455 else
10456 error ("invalid entry to OpenMP structured block");
10457 #endif
10459 bool cilkplus_block = false;
10460 if (flag_cilkplus)
10462 if ((branch_ctx
10463 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10464 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10465 || (label_ctx
10466 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10467 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10468 cilkplus_block = true;
10471 /* If it's obvious we have an invalid entry, be specific about the error. */
10472 if (branch_ctx == NULL)
10474 if (cilkplus_block)
10475 error ("invalid entry to Cilk Plus structured block");
10476 else
10477 error ("invalid entry to OpenMP structured block");
10479 else
10481 /* Otherwise, be vague and lazy, but efficient. */
10482 if (cilkplus_block)
10483 error ("invalid branch to/from a Cilk Plus structured block");
10484 else
10485 error ("invalid branch to/from an OpenMP structured block");
10488 gsi_replace (gsi_p, gimple_build_nop (), false);
10489 return true;
10492 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10493 where each label is found. */
10495 static tree
10496 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10497 struct walk_stmt_info *wi)
10499 gimple context = (gimple) wi->info;
10500 gimple inner_context;
10501 gimple stmt = gsi_stmt (*gsi_p);
10503 *handled_ops_p = true;
10505 switch (gimple_code (stmt))
10507 WALK_SUBSTMTS;
10509 case GIMPLE_OMP_PARALLEL:
10510 case GIMPLE_OMP_TASK:
10511 case GIMPLE_OMP_SECTIONS:
10512 case GIMPLE_OMP_SINGLE:
10513 case GIMPLE_OMP_SECTION:
10514 case GIMPLE_OMP_MASTER:
10515 case GIMPLE_OMP_ORDERED:
10516 case GIMPLE_OMP_CRITICAL:
10517 case GIMPLE_OMP_TARGET:
10518 case GIMPLE_OMP_TEAMS:
10519 case GIMPLE_OMP_TASKGROUP:
10520 /* The minimal context here is just the current OMP construct. */
10521 inner_context = stmt;
10522 wi->info = inner_context;
10523 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10524 wi->info = context;
10525 break;
10527 case GIMPLE_OMP_FOR:
10528 inner_context = stmt;
10529 wi->info = inner_context;
10530 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10531 walk them. */
10532 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10533 diagnose_sb_1, NULL, wi);
10534 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10535 wi->info = context;
10536 break;
10538 case GIMPLE_LABEL:
10539 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10540 (splay_tree_value) context);
10541 break;
10543 default:
10544 break;
10547 return NULL_TREE;
10550 /* Pass 2: Check each branch and see if its context differs from that of
10551 the destination label's context. */
10553 static tree
10554 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10555 struct walk_stmt_info *wi)
10557 gimple context = (gimple) wi->info;
10558 splay_tree_node n;
10559 gimple stmt = gsi_stmt (*gsi_p);
10561 *handled_ops_p = true;
10563 switch (gimple_code (stmt))
10565 WALK_SUBSTMTS;
10567 case GIMPLE_OMP_PARALLEL:
10568 case GIMPLE_OMP_TASK:
10569 case GIMPLE_OMP_SECTIONS:
10570 case GIMPLE_OMP_SINGLE:
10571 case GIMPLE_OMP_SECTION:
10572 case GIMPLE_OMP_MASTER:
10573 case GIMPLE_OMP_ORDERED:
10574 case GIMPLE_OMP_CRITICAL:
10575 case GIMPLE_OMP_TARGET:
10576 case GIMPLE_OMP_TEAMS:
10577 case GIMPLE_OMP_TASKGROUP:
10578 wi->info = stmt;
10579 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10580 wi->info = context;
10581 break;
10583 case GIMPLE_OMP_FOR:
10584 wi->info = stmt;
10585 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10586 walk them. */
10587 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10588 diagnose_sb_2, NULL, wi);
10589 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10590 wi->info = context;
10591 break;
10593 case GIMPLE_COND:
10595 tree lab = gimple_cond_true_label (stmt);
10596 if (lab)
10598 n = splay_tree_lookup (all_labels,
10599 (splay_tree_key) lab);
10600 diagnose_sb_0 (gsi_p, context,
10601 n ? (gimple) n->value : NULL);
10603 lab = gimple_cond_false_label (stmt);
10604 if (lab)
10606 n = splay_tree_lookup (all_labels,
10607 (splay_tree_key) lab);
10608 diagnose_sb_0 (gsi_p, context,
10609 n ? (gimple) n->value : NULL);
10612 break;
10614 case GIMPLE_GOTO:
10616 tree lab = gimple_goto_dest (stmt);
10617 if (TREE_CODE (lab) != LABEL_DECL)
10618 break;
10620 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10621 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10623 break;
10625 case GIMPLE_SWITCH:
10627 unsigned int i;
10628 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10630 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10631 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10632 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10633 break;
10636 break;
10638 case GIMPLE_RETURN:
10639 diagnose_sb_0 (gsi_p, context, NULL);
10640 break;
10642 default:
10643 break;
10646 return NULL_TREE;
10649 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10650 codes. */
10651 bool
10652 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
10653 int *region_idx)
10655 gimple last = last_stmt (bb);
10656 enum gimple_code code = gimple_code (last);
10657 struct omp_region *cur_region = *region;
10658 bool fallthru = false;
10660 switch (code)
10662 case GIMPLE_OMP_PARALLEL:
10663 case GIMPLE_OMP_TASK:
10664 case GIMPLE_OMP_FOR:
10665 case GIMPLE_OMP_SINGLE:
10666 case GIMPLE_OMP_TEAMS:
10667 case GIMPLE_OMP_MASTER:
10668 case GIMPLE_OMP_TASKGROUP:
10669 case GIMPLE_OMP_ORDERED:
10670 case GIMPLE_OMP_CRITICAL:
10671 case GIMPLE_OMP_SECTION:
10672 cur_region = new_omp_region (bb, code, cur_region);
10673 fallthru = true;
10674 break;
10676 case GIMPLE_OMP_TARGET:
10677 cur_region = new_omp_region (bb, code, cur_region);
10678 fallthru = true;
10679 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10680 cur_region = cur_region->outer;
10681 break;
10683 case GIMPLE_OMP_SECTIONS:
10684 cur_region = new_omp_region (bb, code, cur_region);
10685 fallthru = true;
10686 break;
10688 case GIMPLE_OMP_SECTIONS_SWITCH:
10689 fallthru = false;
10690 break;
10692 case GIMPLE_OMP_ATOMIC_LOAD:
10693 case GIMPLE_OMP_ATOMIC_STORE:
10694 fallthru = true;
10695 break;
10697 case GIMPLE_OMP_RETURN:
10698 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10699 somewhere other than the next block. This will be
10700 created later. */
10701 cur_region->exit = bb;
10702 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
10703 cur_region = cur_region->outer;
10704 break;
10706 case GIMPLE_OMP_CONTINUE:
10707 cur_region->cont = bb;
10708 switch (cur_region->type)
10710 case GIMPLE_OMP_FOR:
10711 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
10712 succs edges as abnormal to prevent splitting
10713 them. */
10714 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
10715 /* Make the loopback edge. */
10716 make_edge (bb, single_succ (cur_region->entry),
10717 EDGE_ABNORMAL);
10719 /* Create an edge from GIMPLE_OMP_FOR to exit, which
10720 corresponds to the case that the body of the loop
10721 is not executed at all. */
10722 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
10723 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
10724 fallthru = false;
10725 break;
10727 case GIMPLE_OMP_SECTIONS:
10728 /* Wire up the edges into and out of the nested sections. */
10730 basic_block switch_bb = single_succ (cur_region->entry);
10732 struct omp_region *i;
10733 for (i = cur_region->inner; i ; i = i->next)
10735 gcc_assert (i->type == GIMPLE_OMP_SECTION);
10736 make_edge (switch_bb, i->entry, 0);
10737 make_edge (i->exit, bb, EDGE_FALLTHRU);
10740 /* Make the loopback edge to the block with
10741 GIMPLE_OMP_SECTIONS_SWITCH. */
10742 make_edge (bb, switch_bb, 0);
10744 /* Make the edge from the switch to exit. */
10745 make_edge (switch_bb, bb->next_bb, 0);
10746 fallthru = false;
10748 break;
10750 default:
10751 gcc_unreachable ();
10753 break;
10755 default:
10756 gcc_unreachable ();
10759 if (*region != cur_region)
10761 *region = cur_region;
10762 if (cur_region)
10763 *region_idx = cur_region->entry->index;
10764 else
10765 *region_idx = 0;
10768 return fallthru;
10771 static unsigned int
10772 diagnose_omp_structured_block_errors (void)
10774 struct walk_stmt_info wi;
10775 gimple_seq body = gimple_body (current_function_decl);
10777 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
10779 memset (&wi, 0, sizeof (wi));
10780 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
10782 memset (&wi, 0, sizeof (wi));
10783 wi.want_locations = true;
10784 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
10786 gimple_set_body (current_function_decl, body);
10788 splay_tree_delete (all_labels);
10789 all_labels = NULL;
10791 return 0;
10794 static bool
10795 gate_diagnose_omp_blocks (void)
10797 return flag_openmp || flag_cilkplus;
10800 namespace {
10802 const pass_data pass_data_diagnose_omp_blocks =
10804 GIMPLE_PASS, /* type */
10805 "*diagnose_omp_blocks", /* name */
10806 OPTGROUP_NONE, /* optinfo_flags */
10807 true, /* has_gate */
10808 true, /* has_execute */
10809 TV_NONE, /* tv_id */
10810 PROP_gimple_any, /* properties_required */
10811 0, /* properties_provided */
10812 0, /* properties_destroyed */
10813 0, /* todo_flags_start */
10814 0, /* todo_flags_finish */
10817 class pass_diagnose_omp_blocks : public gimple_opt_pass
10819 public:
10820 pass_diagnose_omp_blocks (gcc::context *ctxt)
10821 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
10824 /* opt_pass methods: */
10825 bool gate () { return gate_diagnose_omp_blocks (); }
10826 unsigned int execute () {
10827 return diagnose_omp_structured_block_errors ();
10830 }; // class pass_diagnose_omp_blocks
10832 } // anon namespace
10834 gimple_opt_pass *
10835 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
10837 return new pass_diagnose_omp_blocks (ctxt);
10840 /* SIMD clone supporting code. */
10842 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
10843 of arguments to reserve space for. */
10845 static struct cgraph_simd_clone *
10846 simd_clone_struct_alloc (int nargs)
10848 struct cgraph_simd_clone *clone_info;
10849 size_t len = (sizeof (struct cgraph_simd_clone)
10850 + nargs * sizeof (struct cgraph_simd_clone_arg));
10851 clone_info = (struct cgraph_simd_clone *)
10852 ggc_internal_cleared_alloc (len);
10853 return clone_info;
10856 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
10858 static inline void
10859 simd_clone_struct_copy (struct cgraph_simd_clone *to,
10860 struct cgraph_simd_clone *from)
10862 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
10863 + ((from->nargs - from->inbranch)
10864 * sizeof (struct cgraph_simd_clone_arg))));
10867 /* Return vector of parameter types of function FNDECL. This uses
10868 TYPE_ARG_TYPES if available, otherwise falls back to types of
10869 DECL_ARGUMENTS types. */
10871 vec<tree>
10872 simd_clone_vector_of_formal_parm_types (tree fndecl)
10874 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
10875 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
10876 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
10877 unsigned int i;
10878 tree arg;
10879 FOR_EACH_VEC_ELT (args, i, arg)
10880 args[i] = TREE_TYPE (args[i]);
10881 return args;
10884 /* Given a simd function in NODE, extract the simd specific
10885 information from the OMP clauses passed in CLAUSES, and return
10886 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
10887 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
10888 otherwise set to FALSE. */
10890 static struct cgraph_simd_clone *
10891 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
10892 bool *inbranch_specified)
10894 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
10895 tree t;
10896 int n;
10897 *inbranch_specified = false;
10899 n = args.length ();
10900 if (n > 0 && args.last () == void_type_node)
10901 n--;
10903 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
10904 be cloned have a distinctive artificial label in addition to "omp
10905 declare simd". */
10906 bool cilk_clone
10907 = (flag_cilkplus
10908 && lookup_attribute ("cilk simd function",
10909 DECL_ATTRIBUTES (node->decl)));
10911 /* Allocate one more than needed just in case this is an in-branch
10912 clone which will require a mask argument. */
10913 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
10914 clone_info->nargs = n;
10915 clone_info->cilk_elemental = cilk_clone;
10917 if (!clauses)
10919 args.release ();
10920 return clone_info;
10922 clauses = TREE_VALUE (clauses);
10923 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
10924 return clone_info;
10926 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
10928 switch (OMP_CLAUSE_CODE (t))
10930 case OMP_CLAUSE_INBRANCH:
10931 clone_info->inbranch = 1;
10932 *inbranch_specified = true;
10933 break;
10934 case OMP_CLAUSE_NOTINBRANCH:
10935 clone_info->inbranch = 0;
10936 *inbranch_specified = true;
10937 break;
10938 case OMP_CLAUSE_SIMDLEN:
10939 clone_info->simdlen
10940 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
10941 break;
10942 case OMP_CLAUSE_LINEAR:
10944 tree decl = OMP_CLAUSE_DECL (t);
10945 tree step = OMP_CLAUSE_LINEAR_STEP (t);
10946 int argno = TREE_INT_CST_LOW (decl);
10947 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
10949 clone_info->args[argno].arg_type
10950 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
10951 clone_info->args[argno].linear_step = tree_to_shwi (step);
10952 gcc_assert (clone_info->args[argno].linear_step >= 0
10953 && clone_info->args[argno].linear_step < n);
10955 else
10957 if (POINTER_TYPE_P (args[argno]))
10958 step = fold_convert (ssizetype, step);
10959 if (!tree_fits_shwi_p (step))
10961 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10962 "ignoring large linear step");
10963 args.release ();
10964 return NULL;
10966 else if (integer_zerop (step))
10968 warning_at (OMP_CLAUSE_LOCATION (t), 0,
10969 "ignoring zero linear step");
10970 args.release ();
10971 return NULL;
10973 else
10975 clone_info->args[argno].arg_type
10976 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
10977 clone_info->args[argno].linear_step = tree_to_shwi (step);
10980 break;
10982 case OMP_CLAUSE_UNIFORM:
10984 tree decl = OMP_CLAUSE_DECL (t);
10985 int argno = tree_to_uhwi (decl);
10986 clone_info->args[argno].arg_type
10987 = SIMD_CLONE_ARG_TYPE_UNIFORM;
10988 break;
10990 case OMP_CLAUSE_ALIGNED:
10992 tree decl = OMP_CLAUSE_DECL (t);
10993 int argno = tree_to_uhwi (decl);
10994 clone_info->args[argno].alignment
10995 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
10996 break;
10998 default:
10999 break;
11002 args.release ();
11003 return clone_info;
11006 /* Given a SIMD clone in NODE, calculate the characteristic data
11007 type and return the coresponding type. The characteristic data
11008 type is computed as described in the Intel Vector ABI. */
11010 static tree
11011 simd_clone_compute_base_data_type (struct cgraph_node *node,
11012 struct cgraph_simd_clone *clone_info)
11014 tree type = integer_type_node;
11015 tree fndecl = node->decl;
11017 /* a) For non-void function, the characteristic data type is the
11018 return type. */
11019 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
11020 type = TREE_TYPE (TREE_TYPE (fndecl));
11022 /* b) If the function has any non-uniform, non-linear parameters,
11023 then the characteristic data type is the type of the first
11024 such parameter. */
11025 else
11027 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
11028 for (unsigned int i = 0; i < clone_info->nargs; ++i)
11029 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
11031 type = map[i];
11032 break;
11034 map.release ();
11037 /* c) If the characteristic data type determined by a) or b) above
11038 is struct, union, or class type which is pass-by-value (except
11039 for the type that maps to the built-in complex data type), the
11040 characteristic data type is int. */
11041 if (RECORD_OR_UNION_TYPE_P (type)
11042 && !aggregate_value_p (type, NULL)
11043 && TREE_CODE (type) != COMPLEX_TYPE)
11044 return integer_type_node;
11046 /* d) If none of the above three classes is applicable, the
11047 characteristic data type is int. */
11049 return type;
11051 /* e) For Intel Xeon Phi native and offload compilation, if the
11052 resulting characteristic data type is 8-bit or 16-bit integer
11053 data type, the characteristic data type is int. */
11054 /* Well, we don't handle Xeon Phi yet. */
11057 static tree
11058 simd_clone_mangle (struct cgraph_node *node,
11059 struct cgraph_simd_clone *clone_info)
11061 char vecsize_mangle = clone_info->vecsize_mangle;
11062 char mask = clone_info->inbranch ? 'M' : 'N';
11063 unsigned int simdlen = clone_info->simdlen;
11064 unsigned int n;
11065 pretty_printer pp;
11067 gcc_assert (vecsize_mangle && simdlen);
11069 pp_string (&pp, "_ZGV");
11070 pp_character (&pp, vecsize_mangle);
11071 pp_character (&pp, mask);
11072 pp_decimal_int (&pp, simdlen);
11074 for (n = 0; n < clone_info->nargs; ++n)
11076 struct cgraph_simd_clone_arg arg = clone_info->args[n];
11078 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
11079 pp_character (&pp, 'u');
11080 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11082 gcc_assert (arg.linear_step != 0);
11083 pp_character (&pp, 'l');
11084 if (arg.linear_step > 1)
11085 pp_unsigned_wide_integer (&pp, arg.linear_step);
11086 else if (arg.linear_step < 0)
11088 pp_character (&pp, 'n');
11089 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
11090 arg.linear_step));
11093 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11095 pp_character (&pp, 's');
11096 pp_unsigned_wide_integer (&pp, arg.linear_step);
11098 else
11099 pp_character (&pp, 'v');
11100 if (arg.alignment)
11102 pp_character (&pp, 'a');
11103 pp_decimal_int (&pp, arg.alignment);
11107 pp_underscore (&pp);
11108 pp_string (&pp,
11109 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11110 const char *str = pp_formatted_text (&pp);
11112 /* If there already is a SIMD clone with the same mangled name, don't
11113 add another one. This can happen e.g. for
11114 #pragma omp declare simd
11115 #pragma omp declare simd simdlen(8)
11116 int foo (int, int);
11117 if the simdlen is assumed to be 8 for the first one, etc. */
11118 for (struct cgraph_node *clone = node->simd_clones; clone;
11119 clone = clone->simdclone->next_clone)
11120 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11121 str) == 0)
11122 return NULL_TREE;
11124 return get_identifier (str);
11127 /* Create a simd clone of OLD_NODE and return it. */
11129 static struct cgraph_node *
11130 simd_clone_create (struct cgraph_node *old_node)
11132 struct cgraph_node *new_node;
11133 if (old_node->definition)
11135 if (!cgraph_function_with_gimple_body_p (old_node))
11136 return NULL;
11137 cgraph_get_body (old_node);
11138 new_node = cgraph_function_versioning (old_node, vNULL, NULL, NULL,
11139 false, NULL, NULL, "simdclone");
11141 else
11143 tree old_decl = old_node->decl;
11144 tree new_decl = copy_node (old_node->decl);
11145 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11146 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11147 SET_DECL_RTL (new_decl, NULL);
11148 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11149 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11150 new_node
11151 = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL);
11152 cgraph_call_function_insertion_hooks (new_node);
11154 if (new_node == NULL)
11155 return new_node;
11157 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11159 /* The function cgraph_function_versioning () will force the new
11160 symbol local. Undo this, and inherit external visability from
11161 the old node. */
11162 new_node->local.local = old_node->local.local;
11163 new_node->externally_visible = old_node->externally_visible;
11165 return new_node;
11168 /* Adjust the return type of the given function to its appropriate
11169 vector counterpart. Returns a simd array to be used throughout the
11170 function as a return value. */
11172 static tree
11173 simd_clone_adjust_return_type (struct cgraph_node *node)
11175 tree fndecl = node->decl;
11176 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11177 unsigned int veclen;
11178 tree t;
11180 /* Adjust the function return type. */
11181 if (orig_rettype == void_type_node)
11182 return NULL_TREE;
11183 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11184 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11185 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11186 veclen = node->simdclone->vecsize_int;
11187 else
11188 veclen = node->simdclone->vecsize_float;
11189 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11190 if (veclen > node->simdclone->simdlen)
11191 veclen = node->simdclone->simdlen;
11192 if (veclen == node->simdclone->simdlen)
11193 TREE_TYPE (TREE_TYPE (fndecl))
11194 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11195 node->simdclone->simdlen);
11196 else
11198 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11199 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11200 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11202 if (!node->definition)
11203 return NULL_TREE;
11205 t = DECL_RESULT (fndecl);
11206 /* Adjust the DECL_RESULT. */
11207 gcc_assert (TREE_TYPE (t) != void_type_node);
11208 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11209 relayout_decl (t);
11211 tree atype = build_array_type_nelts (orig_rettype,
11212 node->simdclone->simdlen);
11213 if (veclen != node->simdclone->simdlen)
11214 return build1 (VIEW_CONVERT_EXPR, atype, t);
11216 /* Set up a SIMD array to use as the return value. */
11217 tree retval = create_tmp_var_raw (atype, "retval");
11218 gimple_add_tmp_var (retval);
11219 return retval;
11222 /* Each vector argument has a corresponding array to be used locally
11223 as part of the eventual loop. Create such temporary array and
11224 return it.
11226 PREFIX is the prefix to be used for the temporary.
11228 TYPE is the inner element type.
11230 SIMDLEN is the number of elements. */
11232 static tree
11233 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11235 tree atype = build_array_type_nelts (type, simdlen);
11236 tree avar = create_tmp_var_raw (atype, prefix);
11237 gimple_add_tmp_var (avar);
11238 return avar;
11241 /* Modify the function argument types to their corresponding vector
11242 counterparts if appropriate. Also, create one array for each simd
11243 argument to be used locally when using the function arguments as
11244 part of the loop.
11246 NODE is the function whose arguments are to be adjusted.
11248 Returns an adjustment vector that will be filled describing how the
11249 argument types will be adjusted. */
11251 static ipa_parm_adjustment_vec
11252 simd_clone_adjust_argument_types (struct cgraph_node *node)
11254 vec<tree> args;
11255 ipa_parm_adjustment_vec adjustments;
11257 if (node->definition)
11258 args = ipa_get_vector_of_formal_parms (node->decl);
11259 else
11260 args = simd_clone_vector_of_formal_parm_types (node->decl);
11261 adjustments.create (args.length ());
11262 unsigned i, j, veclen;
11263 struct ipa_parm_adjustment adj;
11264 for (i = 0; i < node->simdclone->nargs; ++i)
11266 memset (&adj, 0, sizeof (adj));
11267 tree parm = args[i];
11268 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11269 adj.base_index = i;
11270 adj.base = parm;
11272 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11273 node->simdclone->args[i].orig_type = parm_type;
11275 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11277 /* No adjustment necessary for scalar arguments. */
11278 adj.op = IPA_PARM_OP_COPY;
11280 else
11282 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11283 veclen = node->simdclone->vecsize_int;
11284 else
11285 veclen = node->simdclone->vecsize_float;
11286 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11287 if (veclen > node->simdclone->simdlen)
11288 veclen = node->simdclone->simdlen;
11289 adj.arg_prefix = "simd";
11290 adj.type = build_vector_type (parm_type, veclen);
11291 node->simdclone->args[i].vector_type = adj.type;
11292 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11294 adjustments.safe_push (adj);
11295 if (j == veclen)
11297 memset (&adj, 0, sizeof (adj));
11298 adj.op = IPA_PARM_OP_NEW;
11299 adj.arg_prefix = "simd";
11300 adj.base_index = i;
11301 adj.type = node->simdclone->args[i].vector_type;
11305 if (node->definition)
11306 node->simdclone->args[i].simd_array
11307 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11308 parm_type, node->simdclone->simdlen);
11310 adjustments.safe_push (adj);
11313 if (node->simdclone->inbranch)
11315 tree base_type
11316 = simd_clone_compute_base_data_type (node->simdclone->origin,
11317 node->simdclone);
11319 memset (&adj, 0, sizeof (adj));
11320 adj.op = IPA_PARM_OP_NEW;
11321 adj.arg_prefix = "mask";
11323 adj.base_index = i;
11324 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11325 veclen = node->simdclone->vecsize_int;
11326 else
11327 veclen = node->simdclone->vecsize_float;
11328 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11329 if (veclen > node->simdclone->simdlen)
11330 veclen = node->simdclone->simdlen;
11331 adj.type = build_vector_type (base_type, veclen);
11332 adjustments.safe_push (adj);
11334 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11335 adjustments.safe_push (adj);
11337 /* We have previously allocated one extra entry for the mask. Use
11338 it and fill it. */
11339 struct cgraph_simd_clone *sc = node->simdclone;
11340 sc->nargs++;
11341 if (node->definition)
11343 sc->args[i].orig_arg
11344 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11345 sc->args[i].simd_array
11346 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11348 sc->args[i].orig_type = base_type;
11349 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11352 if (node->definition)
11353 ipa_modify_formal_parameters (node->decl, adjustments);
11354 else
11356 tree new_arg_types = NULL_TREE, new_reversed;
11357 bool last_parm_void = false;
11358 if (args.length () > 0 && args.last () == void_type_node)
11359 last_parm_void = true;
11361 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11362 j = adjustments.length ();
11363 for (i = 0; i < j; i++)
11365 struct ipa_parm_adjustment *adj = &adjustments[i];
11366 tree ptype;
11367 if (adj->op == IPA_PARM_OP_COPY)
11368 ptype = args[adj->base_index];
11369 else
11370 ptype = adj->type;
11371 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11373 new_reversed = nreverse (new_arg_types);
11374 if (last_parm_void)
11376 if (new_reversed)
11377 TREE_CHAIN (new_arg_types) = void_list_node;
11378 else
11379 new_reversed = void_list_node;
11382 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11383 TYPE_ARG_TYPES (new_type) = new_reversed;
11384 TREE_TYPE (node->decl) = new_type;
11386 adjustments.release ();
11388 args.release ();
11389 return adjustments;
11392 /* Initialize and copy the function arguments in NODE to their
11393 corresponding local simd arrays. Returns a fresh gimple_seq with
11394 the instruction sequence generated. */
11396 static gimple_seq
11397 simd_clone_init_simd_arrays (struct cgraph_node *node,
11398 ipa_parm_adjustment_vec adjustments)
11400 gimple_seq seq = NULL;
11401 unsigned i = 0, j = 0, k;
11403 for (tree arg = DECL_ARGUMENTS (node->decl);
11404 arg;
11405 arg = DECL_CHAIN (arg), i++, j++)
11407 if (adjustments[j].op == IPA_PARM_OP_COPY)
11408 continue;
11410 node->simdclone->args[i].vector_arg = arg;
11412 tree array = node->simdclone->args[i].simd_array;
11413 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11415 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11416 tree ptr = build_fold_addr_expr (array);
11417 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11418 build_int_cst (ptype, 0));
11419 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11420 gimplify_and_add (t, &seq);
11422 else
11424 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11425 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11426 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11428 tree ptr = build_fold_addr_expr (array);
11429 int elemsize;
11430 if (k)
11432 arg = DECL_CHAIN (arg);
11433 j++;
11435 elemsize
11436 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11437 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11438 build_int_cst (ptype, k * elemsize));
11439 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11440 gimplify_and_add (t, &seq);
11444 return seq;
11447 /* Callback info for ipa_simd_modify_stmt_ops below. */
11449 struct modify_stmt_info {
11450 ipa_parm_adjustment_vec adjustments;
11451 gimple stmt;
11452 /* True if the parent statement was modified by
11453 ipa_simd_modify_stmt_ops. */
11454 bool modified;
11457 /* Callback for walk_gimple_op.
11459 Adjust operands from a given statement as specified in the
11460 adjustments vector in the callback data. */
11462 static tree
11463 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11465 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11466 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11467 tree *orig_tp = tp;
11468 if (TREE_CODE (*tp) == ADDR_EXPR)
11469 tp = &TREE_OPERAND (*tp, 0);
11470 struct ipa_parm_adjustment *cand = NULL;
11471 if (TREE_CODE (*tp) == PARM_DECL)
11472 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11473 else
11475 if (TYPE_P (*tp))
11476 *walk_subtrees = 0;
11479 tree repl = NULL_TREE;
11480 if (cand)
11481 repl = unshare_expr (cand->new_decl);
11482 else
11484 if (tp != orig_tp)
11486 *walk_subtrees = 0;
11487 bool modified = info->modified;
11488 info->modified = false;
11489 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11490 if (!info->modified)
11492 info->modified = modified;
11493 return NULL_TREE;
11495 info->modified = modified;
11496 repl = *tp;
11498 else
11499 return NULL_TREE;
11502 if (tp != orig_tp)
11504 repl = build_fold_addr_expr (repl);
11505 gimple stmt;
11506 if (is_gimple_debug (info->stmt))
11508 tree vexpr = make_node (DEBUG_EXPR_DECL);
11509 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
11510 DECL_ARTIFICIAL (vexpr) = 1;
11511 TREE_TYPE (vexpr) = TREE_TYPE (repl);
11512 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
11513 repl = vexpr;
11515 else
11517 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl),
11518 NULL), repl);
11519 repl = gimple_assign_lhs (stmt);
11521 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11522 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11523 *orig_tp = repl;
11525 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11527 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11528 *tp = vce;
11530 else
11531 *tp = repl;
11533 info->modified = true;
11534 return NULL_TREE;
11537 /* Traverse the function body and perform all modifications as
11538 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11539 modified such that the replacement/reduction value will now be an
11540 offset into the corresponding simd_array.
11542 This function will replace all function argument uses with their
11543 corresponding simd array elements, and ajust the return values
11544 accordingly. */
11546 static void
11547 ipa_simd_modify_function_body (struct cgraph_node *node,
11548 ipa_parm_adjustment_vec adjustments,
11549 tree retval_array, tree iter)
11551 basic_block bb;
11552 unsigned int i, j, l;
11554 /* Re-use the adjustments array, but this time use it to replace
11555 every function argument use to an offset into the corresponding
11556 simd_array. */
11557 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11559 if (!node->simdclone->args[i].vector_arg)
11560 continue;
11562 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11563 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11564 adjustments[j].new_decl
11565 = build4 (ARRAY_REF,
11566 basetype,
11567 node->simdclone->args[i].simd_array,
11568 iter,
11569 NULL_TREE, NULL_TREE);
11570 if (adjustments[j].op == IPA_PARM_OP_NONE
11571 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11572 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11575 l = adjustments.length ();
11576 for (i = 1; i < num_ssa_names; i++)
11578 tree name = ssa_name (i);
11579 if (name
11580 && SSA_NAME_VAR (name)
11581 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11583 for (j = 0; j < l; j++)
11584 if (SSA_NAME_VAR (name) == adjustments[j].base
11585 && adjustments[j].new_decl)
11587 tree base_var;
11588 if (adjustments[j].new_ssa_base == NULL_TREE)
11590 base_var
11591 = copy_var_decl (adjustments[j].base,
11592 DECL_NAME (adjustments[j].base),
11593 TREE_TYPE (adjustments[j].base));
11594 adjustments[j].new_ssa_base = base_var;
11596 else
11597 base_var = adjustments[j].new_ssa_base;
11598 if (SSA_NAME_IS_DEFAULT_DEF (name))
11600 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11601 gimple_stmt_iterator gsi = gsi_after_labels (bb);
11602 tree new_decl = unshare_expr (adjustments[j].new_decl);
11603 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
11604 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11605 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
11606 gimple stmt = gimple_build_assign (name, new_decl);
11607 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11609 else
11610 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11615 struct modify_stmt_info info;
11616 info.adjustments = adjustments;
11618 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
11620 gimple_stmt_iterator gsi;
11622 gsi = gsi_start_bb (bb);
11623 while (!gsi_end_p (gsi))
11625 gimple stmt = gsi_stmt (gsi);
11626 info.stmt = stmt;
11627 struct walk_stmt_info wi;
11629 memset (&wi, 0, sizeof (wi));
11630 info.modified = false;
11631 wi.info = &info;
11632 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
11634 if (gimple_code (stmt) == GIMPLE_RETURN)
11636 tree retval = gimple_return_retval (stmt);
11637 if (!retval)
11639 gsi_remove (&gsi, true);
11640 continue;
11643 /* Replace `return foo' with `retval_array[iter] = foo'. */
11644 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
11645 retval_array, iter, NULL, NULL);
11646 stmt = gimple_build_assign (ref, retval);
11647 gsi_replace (&gsi, stmt, true);
11648 info.modified = true;
11651 if (info.modified)
11653 update_stmt (stmt);
11654 if (maybe_clean_eh_stmt (stmt))
11655 gimple_purge_dead_eh_edges (gimple_bb (stmt));
11657 gsi_next (&gsi);
11662 /* Adjust the argument types in NODE to their appropriate vector
11663 counterparts. */
11665 static void
11666 simd_clone_adjust (struct cgraph_node *node)
11668 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
11670 targetm.simd_clone.adjust (node);
11672 tree retval = simd_clone_adjust_return_type (node);
11673 ipa_parm_adjustment_vec adjustments
11674 = simd_clone_adjust_argument_types (node);
11676 push_gimplify_context ();
11678 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
11680 /* Adjust all uses of vector arguments accordingly. Adjust all
11681 return values accordingly. */
11682 tree iter = create_tmp_var (unsigned_type_node, "iter");
11683 tree iter1 = make_ssa_name (iter, NULL);
11684 tree iter2 = make_ssa_name (iter, NULL);
11685 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
11687 /* Initialize the iteration variable. */
11688 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11689 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
11690 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
11691 /* Insert the SIMD array and iv initialization at function
11692 entry. */
11693 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
11695 pop_gimplify_context (NULL);
11697 /* Create a new BB right before the original exit BB, to hold the
11698 iteration increment and the condition/branch. */
11699 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
11700 basic_block incr_bb = create_empty_bb (orig_exit);
11701 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11702 flag. Set it now to be a FALLTHRU_EDGE. */
11703 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
11704 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
11705 for (unsigned i = 0;
11706 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
11708 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
11709 redirect_edge_succ (e, incr_bb);
11711 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
11712 e->probability = REG_BR_PROB_BASE;
11713 gsi = gsi_last_bb (incr_bb);
11714 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
11715 build_int_cst (unsigned_type_node,
11716 1));
11717 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11719 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
11720 struct loop *loop = alloc_loop ();
11721 cfun->has_force_vect_loops = true;
11722 loop->safelen = node->simdclone->simdlen;
11723 loop->force_vect = true;
11724 loop->header = body_bb;
11725 add_bb_to_loop (incr_bb, loop);
11727 /* Branch around the body if the mask applies. */
11728 if (node->simdclone->inbranch)
11730 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
11731 tree mask_array
11732 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
11733 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
11734 tree aref = build4 (ARRAY_REF,
11735 TREE_TYPE (TREE_TYPE (mask_array)),
11736 mask_array, iter1,
11737 NULL, NULL);
11738 g = gimple_build_assign (mask, aref);
11739 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11740 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
11741 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
11743 aref = build1 (VIEW_CONVERT_EXPR,
11744 build_nonstandard_integer_type (bitsize, 0), mask);
11745 mask = make_ssa_name (TREE_TYPE (aref), NULL);
11746 g = gimple_build_assign (mask, aref);
11747 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11750 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
11751 NULL, NULL);
11752 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11753 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
11754 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
11757 /* Generate the condition. */
11758 g = gimple_build_cond (LT_EXPR,
11759 iter2,
11760 build_int_cst (unsigned_type_node,
11761 node->simdclone->simdlen),
11762 NULL, NULL);
11763 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11764 e = split_block (incr_bb, gsi_stmt (gsi));
11765 basic_block latch_bb = e->dest;
11766 basic_block new_exit_bb = e->dest;
11767 new_exit_bb = split_block (latch_bb, NULL)->dest;
11768 loop->latch = latch_bb;
11770 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
11772 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
11773 /* The successor of incr_bb is already pointing to latch_bb; just
11774 change the flags.
11775 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
11776 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
11778 gimple phi = create_phi_node (iter1, body_bb);
11779 edge preheader_edge = find_edge (entry_bb, body_bb);
11780 edge latch_edge = single_succ_edge (latch_bb);
11781 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
11782 UNKNOWN_LOCATION);
11783 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11785 /* Generate the new return. */
11786 gsi = gsi_last_bb (new_exit_bb);
11787 if (retval
11788 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
11789 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
11790 retval = TREE_OPERAND (retval, 0);
11791 else if (retval)
11793 retval = build1 (VIEW_CONVERT_EXPR,
11794 TREE_TYPE (TREE_TYPE (node->decl)),
11795 retval);
11796 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
11797 false, GSI_CONTINUE_LINKING);
11799 g = gimple_build_return (retval);
11800 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
11802 /* Handle aligned clauses by replacing default defs of the aligned
11803 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
11804 lhs. Handle linear by adding PHIs. */
11805 for (unsigned i = 0; i < node->simdclone->nargs; i++)
11806 if (node->simdclone->args[i].alignment
11807 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
11808 && (node->simdclone->args[i].alignment
11809 & (node->simdclone->args[i].alignment - 1)) == 0
11810 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
11811 == POINTER_TYPE)
11813 unsigned int alignment = node->simdclone->args[i].alignment;
11814 tree orig_arg = node->simdclone->args[i].orig_arg;
11815 tree def = ssa_default_def (cfun, orig_arg);
11816 if (def && !has_zero_uses (def))
11818 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
11819 gimple_seq seq = NULL;
11820 bool need_cvt = false;
11821 gimple call
11822 = gimple_build_call (fn, 2, def, size_int (alignment));
11823 g = call;
11824 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
11825 ptr_type_node))
11826 need_cvt = true;
11827 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
11828 gimple_call_set_lhs (g, t);
11829 gimple_seq_add_stmt_without_update (&seq, g);
11830 if (need_cvt)
11832 t = make_ssa_name (orig_arg, NULL);
11833 g = gimple_build_assign_with_ops (NOP_EXPR, t,
11834 gimple_call_lhs (g),
11835 NULL_TREE);
11836 gimple_seq_add_stmt_without_update (&seq, g);
11838 gsi_insert_seq_on_edge_immediate
11839 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
11841 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11842 int freq = compute_call_stmt_bb_frequency (current_function_decl,
11843 entry_bb);
11844 cgraph_create_edge (node, cgraph_get_create_node (fn),
11845 call, entry_bb->count, freq);
11847 imm_use_iterator iter;
11848 use_operand_p use_p;
11849 gimple use_stmt;
11850 tree repl = gimple_get_lhs (g);
11851 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11852 if (is_gimple_debug (use_stmt) || use_stmt == call)
11853 continue;
11854 else
11855 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11856 SET_USE (use_p, repl);
11859 else if (node->simdclone->args[i].arg_type
11860 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11862 tree orig_arg = node->simdclone->args[i].orig_arg;
11863 tree def = ssa_default_def (cfun, orig_arg);
11864 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11865 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
11866 if (def && !has_zero_uses (def))
11868 iter1 = make_ssa_name (orig_arg, NULL);
11869 iter2 = make_ssa_name (orig_arg, NULL);
11870 phi = create_phi_node (iter1, body_bb);
11871 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
11872 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
11873 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11874 ? PLUS_EXPR : POINTER_PLUS_EXPR;
11875 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
11876 ? TREE_TYPE (orig_arg) : sizetype;
11877 tree addcst
11878 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
11879 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
11880 gsi = gsi_last_bb (incr_bb);
11881 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
11883 imm_use_iterator iter;
11884 use_operand_p use_p;
11885 gimple use_stmt;
11886 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
11887 if (use_stmt == phi)
11888 continue;
11889 else
11890 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
11891 SET_USE (use_p, iter1);
11895 calculate_dominance_info (CDI_DOMINATORS);
11896 add_loop (loop, loop->header->loop_father);
11897 update_ssa (TODO_update_ssa);
11899 pop_cfun ();
11902 /* If the function in NODE is tagged as an elemental SIMD function,
11903 create the appropriate SIMD clones. */
11905 static void
11906 expand_simd_clones (struct cgraph_node *node)
11908 tree attr = lookup_attribute ("omp declare simd",
11909 DECL_ATTRIBUTES (node->decl));
11910 if (attr == NULL_TREE
11911 || node->global.inlined_to
11912 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
11913 return;
11915 /* Ignore
11916 #pragma omp declare simd
11917 extern int foo ();
11918 in C, there we don't know the argument types at all. */
11919 if (!node->definition
11920 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
11921 return;
11925 /* Start with parsing the "omp declare simd" attribute(s). */
11926 bool inbranch_clause_specified;
11927 struct cgraph_simd_clone *clone_info
11928 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
11929 &inbranch_clause_specified);
11930 if (clone_info == NULL)
11931 continue;
11933 int orig_simdlen = clone_info->simdlen;
11934 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
11935 /* The target can return 0 (no simd clones should be created),
11936 1 (just one ISA of simd clones should be created) or higher
11937 count of ISA variants. In that case, clone_info is initialized
11938 for the first ISA variant. */
11939 int count
11940 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
11941 base_type, 0);
11942 if (count == 0)
11943 continue;
11945 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
11946 also create one inbranch and one !inbranch clone of it. */
11947 for (int i = 0; i < count * 2; i++)
11949 struct cgraph_simd_clone *clone = clone_info;
11950 if (inbranch_clause_specified && (i & 1) != 0)
11951 continue;
11953 if (i != 0)
11955 clone = simd_clone_struct_alloc (clone_info->nargs
11956 + ((i & 1) != 0));
11957 simd_clone_struct_copy (clone, clone_info);
11958 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
11959 and simd_clone_adjust_argument_types did to the first
11960 clone's info. */
11961 clone->nargs -= clone_info->inbranch;
11962 clone->simdlen = orig_simdlen;
11963 /* And call the target hook again to get the right ISA. */
11964 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
11965 base_type,
11966 i / 2);
11967 if ((i & 1) != 0)
11968 clone->inbranch = 1;
11971 /* simd_clone_mangle might fail if such a clone has been created
11972 already. */
11973 tree id = simd_clone_mangle (node, clone);
11974 if (id == NULL_TREE)
11975 continue;
11977 /* Only when we are sure we want to create the clone actually
11978 clone the function (or definitions) or create another
11979 extern FUNCTION_DECL (for prototypes without definitions). */
11980 struct cgraph_node *n = simd_clone_create (node);
11981 if (n == NULL)
11982 continue;
11984 n->simdclone = clone;
11985 clone->origin = node;
11986 clone->next_clone = NULL;
11987 if (node->simd_clones == NULL)
11989 clone->prev_clone = n;
11990 node->simd_clones = n;
11992 else
11994 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
11995 clone->prev_clone->simdclone->next_clone = n;
11996 node->simd_clones->simdclone->prev_clone = n;
11998 change_decl_assembler_name (n->decl, id);
11999 /* And finally adjust the return type, parameters and for
12000 definitions also function body. */
12001 if (node->definition)
12002 simd_clone_adjust (n);
12003 else
12005 simd_clone_adjust_return_type (n);
12006 simd_clone_adjust_argument_types (n);
12010 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
12013 /* Entry point for IPA simd clone creation pass. */
12015 static unsigned int
12016 ipa_omp_simd_clone (void)
12018 struct cgraph_node *node;
12019 FOR_EACH_FUNCTION (node)
12020 expand_simd_clones (node);
12021 return 0;
12024 namespace {
12026 const pass_data pass_data_omp_simd_clone =
12028 SIMPLE_IPA_PASS, /* type */
12029 "simdclone", /* name */
12030 OPTGROUP_NONE, /* optinfo_flags */
12031 true, /* has_gate */
12032 true, /* has_execute */
12033 TV_NONE, /* tv_id */
12034 ( PROP_ssa | PROP_cfg ), /* properties_required */
12035 0, /* properties_provided */
12036 0, /* properties_destroyed */
12037 0, /* todo_flags_start */
12038 0, /* todo_flags_finish */
12041 class pass_omp_simd_clone : public simple_ipa_opt_pass
12043 public:
12044 pass_omp_simd_clone(gcc::context *ctxt)
12045 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
12048 /* opt_pass methods: */
12049 bool gate () { return ((flag_openmp || flag_openmp_simd
12050 || flag_cilkplus || (in_lto_p && !flag_wpa))
12051 && (targetm.simd_clone.compute_vecsize_and_simdlen
12052 != NULL)); }
12053 unsigned int execute () { return ipa_omp_simd_clone (); }
12056 } // anon namespace
12058 simple_ipa_opt_pass *
12059 make_pass_omp_simd_clone (gcc::context *ctxt)
12061 return new pass_omp_simd_clone (ctxt);
12064 #include "gt-omp-low.h"