compiler: Recognize 64-bit symbol tables in archives.
[official-gcc.git] / gcc / omp-low.c
blob06db877291f81ca25fd1e1728513363fe31ce4ee
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 "basic-block.h"
33 #include "tree-ssa-alias.h"
34 #include "internal-fn.h"
35 #include "gimple-fold.h"
36 #include "gimple-expr.h"
37 #include "is-a.h"
38 #include "gimple.h"
39 #include "gimplify.h"
40 #include "gimple-iterator.h"
41 #include "gimplify-me.h"
42 #include "gimple-walk.h"
43 #include "tree-iterator.h"
44 #include "tree-inline.h"
45 #include "langhooks.h"
46 #include "diagnostic-core.h"
47 #include "gimple-ssa.h"
48 #include "cgraph.h"
49 #include "tree-cfg.h"
50 #include "tree-phinodes.h"
51 #include "ssa-iterators.h"
52 #include "tree-ssanames.h"
53 #include "tree-into-ssa.h"
54 #include "expr.h"
55 #include "tree-dfa.h"
56 #include "tree-ssa.h"
57 #include "flags.h"
58 #include "function.h"
59 #include "expr.h"
60 #include "tree-pass.h"
61 #include "except.h"
62 #include "splay-tree.h"
63 #include "optabs.h"
64 #include "cfgloop.h"
65 #include "target.h"
66 #include "omp-low.h"
67 #include "gimple-low.h"
68 #include "tree-cfgcleanup.h"
69 #include "pretty-print.h"
70 #include "ipa-prop.h"
71 #include "tree-nested.h"
72 #include "tree-eh.h"
73 #include "cilk.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_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 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
319 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
320 collapse_iter = NULL;
321 collapse_count = NULL;
323 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
324 switch (OMP_CLAUSE_CODE (t))
326 case OMP_CLAUSE_NOWAIT:
327 fd->have_nowait = true;
328 break;
329 case OMP_CLAUSE_ORDERED:
330 fd->have_ordered = true;
331 break;
332 case OMP_CLAUSE_SCHEDULE:
333 gcc_assert (!distribute);
334 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
335 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
336 break;
337 case OMP_CLAUSE_DIST_SCHEDULE:
338 gcc_assert (distribute);
339 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
340 break;
341 case OMP_CLAUSE_COLLAPSE:
342 if (fd->collapse > 1)
344 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
345 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
347 break;
348 default:
349 break;
352 /* FIXME: for now map schedule(auto) to schedule(static).
353 There should be analysis to determine whether all iterations
354 are approximately the same amount of work (then schedule(static)
355 is best) or if it varies (then schedule(dynamic,N) is better). */
356 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
358 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
359 gcc_assert (fd->chunk_size == NULL);
361 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
362 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
363 gcc_assert (fd->chunk_size == NULL);
364 else if (fd->chunk_size == NULL)
366 /* We only need to compute a default chunk size for ordered
367 static loops and dynamic loops. */
368 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
369 || fd->have_ordered)
370 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
371 ? integer_zero_node : integer_one_node;
374 for (i = 0; i < fd->collapse; i++)
376 if (fd->collapse == 1)
377 loop = &fd->loop;
378 else if (loops != NULL)
379 loop = loops + i;
380 else
381 loop = &dummy_loop;
383 loop->v = gimple_omp_for_index (for_stmt, i);
384 gcc_assert (SSA_VAR_P (loop->v));
385 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
386 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
387 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
388 loop->n1 = gimple_omp_for_initial (for_stmt, i);
390 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
391 loop->n2 = gimple_omp_for_final (for_stmt, i);
392 switch (loop->cond_code)
394 case LT_EXPR:
395 case GT_EXPR:
396 break;
397 case NE_EXPR:
398 gcc_assert (gimple_omp_for_kind (for_stmt)
399 == GF_OMP_FOR_KIND_CILKSIMD
400 || (gimple_omp_for_kind (for_stmt)
401 == GF_OMP_FOR_KIND_CILKFOR));
402 break;
403 case LE_EXPR:
404 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
405 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
406 else
407 loop->n2 = fold_build2_loc (loc,
408 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
409 build_int_cst (TREE_TYPE (loop->n2), 1));
410 loop->cond_code = LT_EXPR;
411 break;
412 case GE_EXPR:
413 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
414 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
415 else
416 loop->n2 = fold_build2_loc (loc,
417 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
418 build_int_cst (TREE_TYPE (loop->n2), 1));
419 loop->cond_code = GT_EXPR;
420 break;
421 default:
422 gcc_unreachable ();
425 t = gimple_omp_for_incr (for_stmt, i);
426 gcc_assert (TREE_OPERAND (t, 0) == var);
427 switch (TREE_CODE (t))
429 case PLUS_EXPR:
430 loop->step = TREE_OPERAND (t, 1);
431 break;
432 case POINTER_PLUS_EXPR:
433 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
434 break;
435 case MINUS_EXPR:
436 loop->step = TREE_OPERAND (t, 1);
437 loop->step = fold_build1_loc (loc,
438 NEGATE_EXPR, TREE_TYPE (loop->step),
439 loop->step);
440 break;
441 default:
442 gcc_unreachable ();
445 if (simd
446 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
447 && !fd->have_ordered))
449 if (fd->collapse == 1)
450 iter_type = TREE_TYPE (loop->v);
451 else if (i == 0
452 || TYPE_PRECISION (iter_type)
453 < TYPE_PRECISION (TREE_TYPE (loop->v)))
454 iter_type
455 = build_nonstandard_integer_type
456 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
458 else if (iter_type != long_long_unsigned_type_node)
460 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
461 iter_type = long_long_unsigned_type_node;
462 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
463 && TYPE_PRECISION (TREE_TYPE (loop->v))
464 >= TYPE_PRECISION (iter_type))
466 tree n;
468 if (loop->cond_code == LT_EXPR)
469 n = fold_build2_loc (loc,
470 PLUS_EXPR, TREE_TYPE (loop->v),
471 loop->n2, loop->step);
472 else
473 n = loop->n1;
474 if (TREE_CODE (n) != INTEGER_CST
475 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
476 iter_type = long_long_unsigned_type_node;
478 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
479 > TYPE_PRECISION (iter_type))
481 tree n1, n2;
483 if (loop->cond_code == LT_EXPR)
485 n1 = loop->n1;
486 n2 = fold_build2_loc (loc,
487 PLUS_EXPR, TREE_TYPE (loop->v),
488 loop->n2, loop->step);
490 else
492 n1 = fold_build2_loc (loc,
493 MINUS_EXPR, TREE_TYPE (loop->v),
494 loop->n2, loop->step);
495 n2 = loop->n1;
497 if (TREE_CODE (n1) != INTEGER_CST
498 || TREE_CODE (n2) != INTEGER_CST
499 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
500 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
501 iter_type = long_long_unsigned_type_node;
505 if (collapse_count && *collapse_count == NULL)
507 t = fold_binary (loop->cond_code, boolean_type_node,
508 fold_convert (TREE_TYPE (loop->v), loop->n1),
509 fold_convert (TREE_TYPE (loop->v), loop->n2));
510 if (t && integer_zerop (t))
511 count = build_zero_cst (long_long_unsigned_type_node);
512 else if ((i == 0 || count != NULL_TREE)
513 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
514 && TREE_CONSTANT (loop->n1)
515 && TREE_CONSTANT (loop->n2)
516 && TREE_CODE (loop->step) == INTEGER_CST)
518 tree itype = TREE_TYPE (loop->v);
520 if (POINTER_TYPE_P (itype))
521 itype = signed_type_for (itype);
522 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
523 t = fold_build2_loc (loc,
524 PLUS_EXPR, itype,
525 fold_convert_loc (loc, itype, loop->step), t);
526 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
527 fold_convert_loc (loc, itype, loop->n2));
528 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
529 fold_convert_loc (loc, itype, loop->n1));
530 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
531 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
532 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
533 fold_build1_loc (loc, NEGATE_EXPR, itype,
534 fold_convert_loc (loc, itype,
535 loop->step)));
536 else
537 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
538 fold_convert_loc (loc, itype, loop->step));
539 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
540 if (count != NULL_TREE)
541 count = fold_build2_loc (loc,
542 MULT_EXPR, long_long_unsigned_type_node,
543 count, t);
544 else
545 count = t;
546 if (TREE_CODE (count) != INTEGER_CST)
547 count = NULL_TREE;
549 else if (count && !integer_zerop (count))
550 count = NULL_TREE;
554 if (count
555 && !simd
556 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
557 || fd->have_ordered))
559 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
560 iter_type = long_long_unsigned_type_node;
561 else
562 iter_type = long_integer_type_node;
564 else if (collapse_iter && *collapse_iter != NULL)
565 iter_type = TREE_TYPE (*collapse_iter);
566 fd->iter_type = iter_type;
567 if (collapse_iter && *collapse_iter == NULL)
568 *collapse_iter = create_tmp_var (iter_type, ".iter");
569 if (collapse_count && *collapse_count == NULL)
571 if (count)
572 *collapse_count = fold_convert_loc (loc, iter_type, count);
573 else
574 *collapse_count = create_tmp_var (iter_type, ".count");
577 if (fd->collapse > 1)
579 fd->loop.v = *collapse_iter;
580 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
581 fd->loop.n2 = *collapse_count;
582 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
583 fd->loop.cond_code = LT_EXPR;
588 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
589 is the immediate dominator of PAR_ENTRY_BB, return true if there
590 are no data dependencies that would prevent expanding the parallel
591 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
593 When expanding a combined parallel+workshare region, the call to
594 the child function may need additional arguments in the case of
595 GIMPLE_OMP_FOR regions. In some cases, these arguments are
596 computed out of variables passed in from the parent to the child
597 via 'struct .omp_data_s'. For instance:
599 #pragma omp parallel for schedule (guided, i * 4)
600 for (j ...)
602 Is lowered into:
604 # BLOCK 2 (PAR_ENTRY_BB)
605 .omp_data_o.i = i;
606 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
608 # BLOCK 3 (WS_ENTRY_BB)
609 .omp_data_i = &.omp_data_o;
610 D.1667 = .omp_data_i->i;
611 D.1598 = D.1667 * 4;
612 #pragma omp for schedule (guided, D.1598)
614 When we outline the parallel region, the call to the child function
615 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
616 that value is computed *after* the call site. So, in principle we
617 cannot do the transformation.
619 To see whether the code in WS_ENTRY_BB blocks the combined
620 parallel+workshare call, we collect all the variables used in the
621 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
622 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
623 call.
625 FIXME. If we had the SSA form built at this point, we could merely
626 hoist the code in block 3 into block 2 and be done with it. But at
627 this point we don't have dataflow information and though we could
628 hack something up here, it is really not worth the aggravation. */
630 static bool
631 workshare_safe_to_combine_p (basic_block ws_entry_bb)
633 struct omp_for_data fd;
634 gimple ws_stmt = last_stmt (ws_entry_bb);
636 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
637 return true;
639 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
641 extract_omp_for_data (ws_stmt, &fd, NULL);
643 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
644 return false;
645 if (fd.iter_type != long_integer_type_node)
646 return false;
648 /* FIXME. We give up too easily here. If any of these arguments
649 are not constants, they will likely involve variables that have
650 been mapped into fields of .omp_data_s for sharing with the child
651 function. With appropriate data flow, it would be possible to
652 see through this. */
653 if (!is_gimple_min_invariant (fd.loop.n1)
654 || !is_gimple_min_invariant (fd.loop.n2)
655 || !is_gimple_min_invariant (fd.loop.step)
656 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
657 return false;
659 return true;
663 /* Collect additional arguments needed to emit a combined
664 parallel+workshare call. WS_STMT is the workshare directive being
665 expanded. */
667 static vec<tree, va_gc> *
668 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
670 tree t;
671 location_t loc = gimple_location (ws_stmt);
672 vec<tree, va_gc> *ws_args;
674 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
676 struct omp_for_data fd;
677 tree n1, n2;
679 extract_omp_for_data (ws_stmt, &fd, NULL);
680 n1 = fd.loop.n1;
681 n2 = fd.loop.n2;
683 if (gimple_omp_for_combined_into_p (ws_stmt))
685 tree innerc
686 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
687 OMP_CLAUSE__LOOPTEMP_);
688 gcc_assert (innerc);
689 n1 = OMP_CLAUSE_DECL (innerc);
690 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
691 OMP_CLAUSE__LOOPTEMP_);
692 gcc_assert (innerc);
693 n2 = OMP_CLAUSE_DECL (innerc);
696 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
698 t = fold_convert_loc (loc, long_integer_type_node, n1);
699 ws_args->quick_push (t);
701 t = fold_convert_loc (loc, long_integer_type_node, n2);
702 ws_args->quick_push (t);
704 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
705 ws_args->quick_push (t);
707 if (fd.chunk_size)
709 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
710 ws_args->quick_push (t);
713 return ws_args;
715 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
717 /* Number of sections is equal to the number of edges from the
718 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
719 the exit of the sections region. */
720 basic_block bb = single_succ (gimple_bb (ws_stmt));
721 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
722 vec_alloc (ws_args, 1);
723 ws_args->quick_push (t);
724 return ws_args;
727 gcc_unreachable ();
731 /* Discover whether REGION is a combined parallel+workshare region. */
733 static void
734 determine_parallel_type (struct omp_region *region)
736 basic_block par_entry_bb, par_exit_bb;
737 basic_block ws_entry_bb, ws_exit_bb;
739 if (region == NULL || region->inner == NULL
740 || region->exit == NULL || region->inner->exit == NULL
741 || region->inner->cont == NULL)
742 return;
744 /* We only support parallel+for and parallel+sections. */
745 if (region->type != GIMPLE_OMP_PARALLEL
746 || (region->inner->type != GIMPLE_OMP_FOR
747 && region->inner->type != GIMPLE_OMP_SECTIONS))
748 return;
750 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
751 WS_EXIT_BB -> PAR_EXIT_BB. */
752 par_entry_bb = region->entry;
753 par_exit_bb = region->exit;
754 ws_entry_bb = region->inner->entry;
755 ws_exit_bb = region->inner->exit;
757 if (single_succ (par_entry_bb) == ws_entry_bb
758 && single_succ (ws_exit_bb) == par_exit_bb
759 && workshare_safe_to_combine_p (ws_entry_bb)
760 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
761 || (last_and_only_stmt (ws_entry_bb)
762 && last_and_only_stmt (par_exit_bb))))
764 gimple par_stmt = last_stmt (par_entry_bb);
765 gimple ws_stmt = last_stmt (ws_entry_bb);
767 if (region->inner->type == GIMPLE_OMP_FOR)
769 /* If this is a combined parallel loop, we need to determine
770 whether or not to use the combined library calls. There
771 are two cases where we do not apply the transformation:
772 static loops and any kind of ordered loop. In the first
773 case, we already open code the loop so there is no need
774 to do anything else. In the latter case, the combined
775 parallel loop call would still need extra synchronization
776 to implement ordered semantics, so there would not be any
777 gain in using the combined call. */
778 tree clauses = gimple_omp_for_clauses (ws_stmt);
779 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
780 if (c == NULL
781 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
782 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
784 region->is_combined_parallel = false;
785 region->inner->is_combined_parallel = false;
786 return;
790 region->is_combined_parallel = true;
791 region->inner->is_combined_parallel = true;
792 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
797 /* Return true if EXPR is variable sized. */
799 static inline bool
800 is_variable_sized (const_tree expr)
802 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
805 /* Return true if DECL is a reference type. */
807 static inline bool
808 is_reference (tree decl)
810 return lang_hooks.decls.omp_privatize_by_reference (decl);
813 /* Lookup variables in the decl or field splay trees. The "maybe" form
814 allows for the variable form to not have been entered, otherwise we
815 assert that the variable must have been entered. */
817 static inline tree
818 lookup_decl (tree var, omp_context *ctx)
820 tree *n = ctx->cb.decl_map->get (var);
821 return *n;
824 static inline tree
825 maybe_lookup_decl (const_tree var, omp_context *ctx)
827 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
828 return n ? *n : NULL_TREE;
831 static inline tree
832 lookup_field (tree var, omp_context *ctx)
834 splay_tree_node n;
835 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
836 return (tree) n->value;
839 static inline tree
840 lookup_sfield (tree var, omp_context *ctx)
842 splay_tree_node n;
843 n = splay_tree_lookup (ctx->sfield_map
844 ? ctx->sfield_map : ctx->field_map,
845 (splay_tree_key) var);
846 return (tree) n->value;
849 static inline tree
850 maybe_lookup_field (tree var, omp_context *ctx)
852 splay_tree_node n;
853 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
854 return n ? (tree) n->value : NULL_TREE;
857 /* Return true if DECL should be copied by pointer. SHARED_CTX is
858 the parallel context if DECL is to be shared. */
860 static bool
861 use_pointer_for_field (tree decl, omp_context *shared_ctx)
863 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
864 return true;
866 /* We can only use copy-in/copy-out semantics for shared variables
867 when we know the value is not accessible from an outer scope. */
868 if (shared_ctx)
870 /* ??? Trivially accessible from anywhere. But why would we even
871 be passing an address in this case? Should we simply assert
872 this to be false, or should we have a cleanup pass that removes
873 these from the list of mappings? */
874 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
875 return true;
877 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
878 without analyzing the expression whether or not its location
879 is accessible to anyone else. In the case of nested parallel
880 regions it certainly may be. */
881 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
882 return true;
884 /* Do not use copy-in/copy-out for variables that have their
885 address taken. */
886 if (TREE_ADDRESSABLE (decl))
887 return true;
889 /* lower_send_shared_vars only uses copy-in, but not copy-out
890 for these. */
891 if (TREE_READONLY (decl)
892 || ((TREE_CODE (decl) == RESULT_DECL
893 || TREE_CODE (decl) == PARM_DECL)
894 && DECL_BY_REFERENCE (decl)))
895 return false;
897 /* Disallow copy-in/out in nested parallel if
898 decl is shared in outer parallel, otherwise
899 each thread could store the shared variable
900 in its own copy-in location, making the
901 variable no longer really shared. */
902 if (shared_ctx->is_nested)
904 omp_context *up;
906 for (up = shared_ctx->outer; up; up = up->outer)
907 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
908 break;
910 if (up)
912 tree c;
914 for (c = gimple_omp_taskreg_clauses (up->stmt);
915 c; c = OMP_CLAUSE_CHAIN (c))
916 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
917 && OMP_CLAUSE_DECL (c) == decl)
918 break;
920 if (c)
921 goto maybe_mark_addressable_and_ret;
925 /* For tasks avoid using copy-in/out. As tasks can be
926 deferred or executed in different thread, when GOMP_task
927 returns, the task hasn't necessarily terminated. */
928 if (is_task_ctx (shared_ctx))
930 tree outer;
931 maybe_mark_addressable_and_ret:
932 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
933 if (is_gimple_reg (outer))
935 /* Taking address of OUTER in lower_send_shared_vars
936 might need regimplification of everything that uses the
937 variable. */
938 if (!task_shared_vars)
939 task_shared_vars = BITMAP_ALLOC (NULL);
940 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
941 TREE_ADDRESSABLE (outer) = 1;
943 return true;
947 return false;
950 /* Construct a new automatic decl similar to VAR. */
952 static tree
953 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
955 tree copy = copy_var_decl (var, name, type);
957 DECL_CONTEXT (copy) = current_function_decl;
958 DECL_CHAIN (copy) = ctx->block_vars;
959 ctx->block_vars = copy;
961 return copy;
964 static tree
965 omp_copy_decl_1 (tree var, omp_context *ctx)
967 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
970 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
971 as appropriate. */
972 static tree
973 omp_build_component_ref (tree obj, tree field)
975 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
976 if (TREE_THIS_VOLATILE (field))
977 TREE_THIS_VOLATILE (ret) |= 1;
978 if (TREE_READONLY (field))
979 TREE_READONLY (ret) |= 1;
980 return ret;
983 /* Build tree nodes to access the field for VAR on the receiver side. */
985 static tree
986 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
988 tree x, field = lookup_field (var, ctx);
990 /* If the receiver record type was remapped in the child function,
991 remap the field into the new record type. */
992 x = maybe_lookup_field (field, ctx);
993 if (x != NULL)
994 field = x;
996 x = build_simple_mem_ref (ctx->receiver_decl);
997 x = omp_build_component_ref (x, field);
998 if (by_ref)
999 x = build_simple_mem_ref (x);
1001 return x;
1004 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1005 of a parallel, this is a component reference; for workshare constructs
1006 this is some variable. */
1008 static tree
1009 build_outer_var_ref (tree var, omp_context *ctx)
1011 tree x;
1013 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1014 x = var;
1015 else if (is_variable_sized (var))
1017 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1018 x = build_outer_var_ref (x, ctx);
1019 x = build_simple_mem_ref (x);
1021 else if (is_taskreg_ctx (ctx))
1023 bool by_ref = use_pointer_for_field (var, NULL);
1024 x = build_receiver_ref (var, by_ref, ctx);
1026 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1027 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1029 /* #pragma omp simd isn't a worksharing construct, and can reference even
1030 private vars in its linear etc. clauses. */
1031 x = NULL_TREE;
1032 if (ctx->outer && is_taskreg_ctx (ctx))
1033 x = lookup_decl (var, ctx->outer);
1034 else if (ctx->outer)
1035 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1036 if (x == NULL_TREE)
1037 x = var;
1039 else if (ctx->outer)
1040 x = lookup_decl (var, ctx->outer);
1041 else if (is_reference (var))
1042 /* This can happen with orphaned constructs. If var is reference, it is
1043 possible it is shared and as such valid. */
1044 x = var;
1045 else
1046 gcc_unreachable ();
1048 if (is_reference (var))
1049 x = build_simple_mem_ref (x);
1051 return x;
1054 /* Build tree nodes to access the field for VAR on the sender side. */
1056 static tree
1057 build_sender_ref (tree var, omp_context *ctx)
1059 tree field = lookup_sfield (var, ctx);
1060 return omp_build_component_ref (ctx->sender_decl, field);
1063 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1065 static void
1066 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1068 tree field, type, sfield = NULL_TREE;
1070 gcc_assert ((mask & 1) == 0
1071 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1072 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1073 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1075 type = TREE_TYPE (var);
1076 if (mask & 4)
1078 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1079 type = build_pointer_type (build_pointer_type (type));
1081 else if (by_ref)
1082 type = build_pointer_type (type);
1083 else if ((mask & 3) == 1 && is_reference (var))
1084 type = TREE_TYPE (type);
1086 field = build_decl (DECL_SOURCE_LOCATION (var),
1087 FIELD_DECL, DECL_NAME (var), type);
1089 /* Remember what variable this field was created for. This does have a
1090 side effect of making dwarf2out ignore this member, so for helpful
1091 debugging we clear it later in delete_omp_context. */
1092 DECL_ABSTRACT_ORIGIN (field) = var;
1093 if (type == TREE_TYPE (var))
1095 DECL_ALIGN (field) = DECL_ALIGN (var);
1096 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1097 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1099 else
1100 DECL_ALIGN (field) = TYPE_ALIGN (type);
1102 if ((mask & 3) == 3)
1104 insert_field_into_struct (ctx->record_type, field);
1105 if (ctx->srecord_type)
1107 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1108 FIELD_DECL, DECL_NAME (var), type);
1109 DECL_ABSTRACT_ORIGIN (sfield) = var;
1110 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1111 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1112 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1113 insert_field_into_struct (ctx->srecord_type, sfield);
1116 else
1118 if (ctx->srecord_type == NULL_TREE)
1120 tree t;
1122 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1123 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1124 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1126 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1127 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1128 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1129 insert_field_into_struct (ctx->srecord_type, sfield);
1130 splay_tree_insert (ctx->sfield_map,
1131 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1132 (splay_tree_value) sfield);
1135 sfield = field;
1136 insert_field_into_struct ((mask & 1) ? ctx->record_type
1137 : ctx->srecord_type, field);
1140 if (mask & 1)
1141 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1142 (splay_tree_value) field);
1143 if ((mask & 2) && ctx->sfield_map)
1144 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1145 (splay_tree_value) sfield);
1148 static tree
1149 install_var_local (tree var, omp_context *ctx)
1151 tree new_var = omp_copy_decl_1 (var, ctx);
1152 insert_decl_map (&ctx->cb, var, new_var);
1153 return new_var;
1156 /* Adjust the replacement for DECL in CTX for the new context. This means
1157 copying the DECL_VALUE_EXPR, and fixing up the type. */
1159 static void
1160 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1162 tree new_decl, size;
1164 new_decl = lookup_decl (decl, ctx);
1166 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1168 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1169 && DECL_HAS_VALUE_EXPR_P (decl))
1171 tree ve = DECL_VALUE_EXPR (decl);
1172 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1173 SET_DECL_VALUE_EXPR (new_decl, ve);
1174 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1177 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1179 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1180 if (size == error_mark_node)
1181 size = TYPE_SIZE (TREE_TYPE (new_decl));
1182 DECL_SIZE (new_decl) = size;
1184 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1185 if (size == error_mark_node)
1186 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1187 DECL_SIZE_UNIT (new_decl) = size;
1191 /* The callback for remap_decl. Search all containing contexts for a
1192 mapping of the variable; this avoids having to duplicate the splay
1193 tree ahead of time. We know a mapping doesn't already exist in the
1194 given context. Create new mappings to implement default semantics. */
1196 static tree
1197 omp_copy_decl (tree var, copy_body_data *cb)
1199 omp_context *ctx = (omp_context *) cb;
1200 tree new_var;
1202 if (TREE_CODE (var) == LABEL_DECL)
1204 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1205 DECL_CONTEXT (new_var) = current_function_decl;
1206 insert_decl_map (&ctx->cb, var, new_var);
1207 return new_var;
1210 while (!is_taskreg_ctx (ctx))
1212 ctx = ctx->outer;
1213 if (ctx == NULL)
1214 return var;
1215 new_var = maybe_lookup_decl (var, ctx);
1216 if (new_var)
1217 return new_var;
1220 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1221 return var;
1223 return error_mark_node;
1227 /* Debugging dumps for parallel regions. */
1228 void dump_omp_region (FILE *, struct omp_region *, int);
1229 void debug_omp_region (struct omp_region *);
1230 void debug_all_omp_regions (void);
1232 /* Dump the parallel region tree rooted at REGION. */
1234 void
1235 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1237 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1238 gimple_code_name[region->type]);
1240 if (region->inner)
1241 dump_omp_region (file, region->inner, indent + 4);
1243 if (region->cont)
1245 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1246 region->cont->index);
1249 if (region->exit)
1250 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1251 region->exit->index);
1252 else
1253 fprintf (file, "%*s[no exit marker]\n", indent, "");
1255 if (region->next)
1256 dump_omp_region (file, region->next, indent);
1259 DEBUG_FUNCTION void
1260 debug_omp_region (struct omp_region *region)
1262 dump_omp_region (stderr, region, 0);
1265 DEBUG_FUNCTION void
1266 debug_all_omp_regions (void)
1268 dump_omp_region (stderr, root_omp_region, 0);
1272 /* Create a new parallel region starting at STMT inside region PARENT. */
1274 static struct omp_region *
1275 new_omp_region (basic_block bb, enum gimple_code type,
1276 struct omp_region *parent)
1278 struct omp_region *region = XCNEW (struct omp_region);
1280 region->outer = parent;
1281 region->entry = bb;
1282 region->type = type;
1284 if (parent)
1286 /* This is a nested region. Add it to the list of inner
1287 regions in PARENT. */
1288 region->next = parent->inner;
1289 parent->inner = region;
1291 else
1293 /* This is a toplevel region. Add it to the list of toplevel
1294 regions in ROOT_OMP_REGION. */
1295 region->next = root_omp_region;
1296 root_omp_region = region;
1299 return region;
1302 /* Release the memory associated with the region tree rooted at REGION. */
1304 static void
1305 free_omp_region_1 (struct omp_region *region)
1307 struct omp_region *i, *n;
1309 for (i = region->inner; i ; i = n)
1311 n = i->next;
1312 free_omp_region_1 (i);
1315 free (region);
1318 /* Release the memory for the entire omp region tree. */
1320 void
1321 free_omp_regions (void)
1323 struct omp_region *r, *n;
1324 for (r = root_omp_region; r ; r = n)
1326 n = r->next;
1327 free_omp_region_1 (r);
1329 root_omp_region = NULL;
1333 /* Create a new context, with OUTER_CTX being the surrounding context. */
1335 static omp_context *
1336 new_omp_context (gimple stmt, omp_context *outer_ctx)
1338 omp_context *ctx = XCNEW (omp_context);
1340 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1341 (splay_tree_value) ctx);
1342 ctx->stmt = stmt;
1344 if (outer_ctx)
1346 ctx->outer = outer_ctx;
1347 ctx->cb = outer_ctx->cb;
1348 ctx->cb.block = NULL;
1349 ctx->depth = outer_ctx->depth + 1;
1351 else
1353 ctx->cb.src_fn = current_function_decl;
1354 ctx->cb.dst_fn = current_function_decl;
1355 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1356 gcc_checking_assert (ctx->cb.src_node);
1357 ctx->cb.dst_node = ctx->cb.src_node;
1358 ctx->cb.src_cfun = cfun;
1359 ctx->cb.copy_decl = omp_copy_decl;
1360 ctx->cb.eh_lp_nr = 0;
1361 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1362 ctx->depth = 1;
1365 ctx->cb.decl_map = new hash_map<tree, tree>;
1367 return ctx;
1370 static gimple_seq maybe_catch_exception (gimple_seq);
1372 /* Finalize task copyfn. */
1374 static void
1375 finalize_task_copyfn (gimple task_stmt)
1377 struct function *child_cfun;
1378 tree child_fn;
1379 gimple_seq seq = NULL, new_seq;
1380 gimple bind;
1382 child_fn = gimple_omp_task_copy_fn (task_stmt);
1383 if (child_fn == NULL_TREE)
1384 return;
1386 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1387 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1389 push_cfun (child_cfun);
1390 bind = gimplify_body (child_fn, false);
1391 gimple_seq_add_stmt (&seq, bind);
1392 new_seq = maybe_catch_exception (seq);
1393 if (new_seq != seq)
1395 bind = gimple_build_bind (NULL, new_seq, NULL);
1396 seq = NULL;
1397 gimple_seq_add_stmt (&seq, bind);
1399 gimple_set_body (child_fn, seq);
1400 pop_cfun ();
1402 /* Inform the callgraph about the new function. */
1403 cgraph_node::add_new_function (child_fn, false);
1406 /* Destroy a omp_context data structures. Called through the splay tree
1407 value delete callback. */
1409 static void
1410 delete_omp_context (splay_tree_value value)
1412 omp_context *ctx = (omp_context *) value;
1414 delete ctx->cb.decl_map;
1416 if (ctx->field_map)
1417 splay_tree_delete (ctx->field_map);
1418 if (ctx->sfield_map)
1419 splay_tree_delete (ctx->sfield_map);
1421 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1422 it produces corrupt debug information. */
1423 if (ctx->record_type)
1425 tree t;
1426 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1427 DECL_ABSTRACT_ORIGIN (t) = NULL;
1429 if (ctx->srecord_type)
1431 tree t;
1432 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1433 DECL_ABSTRACT_ORIGIN (t) = NULL;
1436 if (is_task_ctx (ctx))
1437 finalize_task_copyfn (ctx->stmt);
1439 XDELETE (ctx);
1442 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1443 context. */
1445 static void
1446 fixup_child_record_type (omp_context *ctx)
1448 tree f, type = ctx->record_type;
1450 /* ??? It isn't sufficient to just call remap_type here, because
1451 variably_modified_type_p doesn't work the way we expect for
1452 record types. Testing each field for whether it needs remapping
1453 and creating a new record by hand works, however. */
1454 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1455 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1456 break;
1457 if (f)
1459 tree name, new_fields = NULL;
1461 type = lang_hooks.types.make_type (RECORD_TYPE);
1462 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1463 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1464 TYPE_DECL, name, type);
1465 TYPE_NAME (type) = name;
1467 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1469 tree new_f = copy_node (f);
1470 DECL_CONTEXT (new_f) = type;
1471 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1472 DECL_CHAIN (new_f) = new_fields;
1473 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1474 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1475 &ctx->cb, NULL);
1476 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1477 &ctx->cb, NULL);
1478 new_fields = new_f;
1480 /* Arrange to be able to look up the receiver field
1481 given the sender field. */
1482 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1483 (splay_tree_value) new_f);
1485 TYPE_FIELDS (type) = nreverse (new_fields);
1486 layout_type (type);
1489 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1492 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1493 specified by CLAUSES. */
1495 static void
1496 scan_sharing_clauses (tree clauses, omp_context *ctx)
1498 tree c, decl;
1499 bool scan_array_reductions = false;
1501 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1503 bool by_ref;
1505 switch (OMP_CLAUSE_CODE (c))
1507 case OMP_CLAUSE_PRIVATE:
1508 decl = OMP_CLAUSE_DECL (c);
1509 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1510 goto do_private;
1511 else if (!is_variable_sized (decl))
1512 install_var_local (decl, ctx);
1513 break;
1515 case OMP_CLAUSE_SHARED:
1516 decl = OMP_CLAUSE_DECL (c);
1517 /* Ignore shared directives in teams construct. */
1518 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1520 /* Global variables don't need to be copied,
1521 the receiver side will use them directly. */
1522 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1523 if (is_global_var (odecl))
1524 break;
1525 insert_decl_map (&ctx->cb, decl, odecl);
1526 break;
1528 gcc_assert (is_taskreg_ctx (ctx));
1529 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1530 || !is_variable_sized (decl));
1531 /* Global variables don't need to be copied,
1532 the receiver side will use them directly. */
1533 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1534 break;
1535 by_ref = use_pointer_for_field (decl, ctx);
1536 if (! TREE_READONLY (decl)
1537 || TREE_ADDRESSABLE (decl)
1538 || by_ref
1539 || is_reference (decl))
1541 install_var_field (decl, by_ref, 3, ctx);
1542 install_var_local (decl, ctx);
1543 break;
1545 /* We don't need to copy const scalar vars back. */
1546 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1547 goto do_private;
1549 case OMP_CLAUSE_LASTPRIVATE:
1550 /* Let the corresponding firstprivate clause create
1551 the variable. */
1552 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1553 break;
1554 /* FALLTHRU */
1556 case OMP_CLAUSE_FIRSTPRIVATE:
1557 case OMP_CLAUSE_REDUCTION:
1558 case OMP_CLAUSE_LINEAR:
1559 decl = OMP_CLAUSE_DECL (c);
1560 do_private:
1561 if (is_variable_sized (decl))
1563 if (is_task_ctx (ctx))
1564 install_var_field (decl, false, 1, ctx);
1565 break;
1567 else if (is_taskreg_ctx (ctx))
1569 bool global
1570 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1571 by_ref = use_pointer_for_field (decl, NULL);
1573 if (is_task_ctx (ctx)
1574 && (global || by_ref || is_reference (decl)))
1576 install_var_field (decl, false, 1, ctx);
1577 if (!global)
1578 install_var_field (decl, by_ref, 2, ctx);
1580 else if (!global)
1581 install_var_field (decl, by_ref, 3, ctx);
1583 install_var_local (decl, ctx);
1584 break;
1586 case OMP_CLAUSE__LOOPTEMP_:
1587 gcc_assert (is_parallel_ctx (ctx));
1588 decl = OMP_CLAUSE_DECL (c);
1589 install_var_field (decl, false, 3, ctx);
1590 install_var_local (decl, ctx);
1591 break;
1593 case OMP_CLAUSE_COPYPRIVATE:
1594 case OMP_CLAUSE_COPYIN:
1595 decl = OMP_CLAUSE_DECL (c);
1596 by_ref = use_pointer_for_field (decl, NULL);
1597 install_var_field (decl, by_ref, 3, ctx);
1598 break;
1600 case OMP_CLAUSE_DEFAULT:
1601 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1602 break;
1604 case OMP_CLAUSE_FINAL:
1605 case OMP_CLAUSE_IF:
1606 case OMP_CLAUSE_NUM_THREADS:
1607 case OMP_CLAUSE_NUM_TEAMS:
1608 case OMP_CLAUSE_THREAD_LIMIT:
1609 case OMP_CLAUSE_DEVICE:
1610 case OMP_CLAUSE_SCHEDULE:
1611 case OMP_CLAUSE_DIST_SCHEDULE:
1612 case OMP_CLAUSE_DEPEND:
1613 case OMP_CLAUSE__CILK_FOR_COUNT_:
1614 if (ctx->outer)
1615 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1616 break;
1618 case OMP_CLAUSE_TO:
1619 case OMP_CLAUSE_FROM:
1620 case OMP_CLAUSE_MAP:
1621 if (ctx->outer)
1622 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1623 decl = OMP_CLAUSE_DECL (c);
1624 /* Global variables with "omp declare target" attribute
1625 don't need to be copied, the receiver side will use them
1626 directly. */
1627 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1628 && DECL_P (decl)
1629 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1630 && lookup_attribute ("omp declare target",
1631 DECL_ATTRIBUTES (decl)))
1632 break;
1633 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1634 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1636 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1637 #pragma omp target data, there is nothing to map for
1638 those. */
1639 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1640 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1641 break;
1643 if (DECL_P (decl))
1645 if (DECL_SIZE (decl)
1646 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1648 tree decl2 = DECL_VALUE_EXPR (decl);
1649 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1650 decl2 = TREE_OPERAND (decl2, 0);
1651 gcc_assert (DECL_P (decl2));
1652 install_var_field (decl2, true, 3, ctx);
1653 install_var_local (decl2, ctx);
1654 install_var_local (decl, ctx);
1656 else
1658 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1659 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1660 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1661 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1662 install_var_field (decl, true, 7, ctx);
1663 else
1664 install_var_field (decl, true, 3, ctx);
1665 if (gimple_omp_target_kind (ctx->stmt)
1666 == GF_OMP_TARGET_KIND_REGION)
1667 install_var_local (decl, ctx);
1670 else
1672 tree base = get_base_address (decl);
1673 tree nc = OMP_CLAUSE_CHAIN (c);
1674 if (DECL_P (base)
1675 && nc != NULL_TREE
1676 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1677 && OMP_CLAUSE_DECL (nc) == base
1678 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1679 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1681 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1682 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1684 else
1686 if (ctx->outer)
1688 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1689 decl = OMP_CLAUSE_DECL (c);
1691 gcc_assert (!splay_tree_lookup (ctx->field_map,
1692 (splay_tree_key) decl));
1693 tree field
1694 = build_decl (OMP_CLAUSE_LOCATION (c),
1695 FIELD_DECL, NULL_TREE, ptr_type_node);
1696 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1697 insert_field_into_struct (ctx->record_type, field);
1698 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1699 (splay_tree_value) field);
1702 break;
1704 case OMP_CLAUSE_NOWAIT:
1705 case OMP_CLAUSE_ORDERED:
1706 case OMP_CLAUSE_COLLAPSE:
1707 case OMP_CLAUSE_UNTIED:
1708 case OMP_CLAUSE_MERGEABLE:
1709 case OMP_CLAUSE_PROC_BIND:
1710 case OMP_CLAUSE_SAFELEN:
1711 break;
1713 case OMP_CLAUSE_ALIGNED:
1714 decl = OMP_CLAUSE_DECL (c);
1715 if (is_global_var (decl)
1716 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1717 install_var_local (decl, ctx);
1718 break;
1720 default:
1721 gcc_unreachable ();
1725 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1727 switch (OMP_CLAUSE_CODE (c))
1729 case OMP_CLAUSE_LASTPRIVATE:
1730 /* Let the corresponding firstprivate clause create
1731 the variable. */
1732 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1733 scan_array_reductions = true;
1734 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1735 break;
1736 /* FALLTHRU */
1738 case OMP_CLAUSE_PRIVATE:
1739 case OMP_CLAUSE_FIRSTPRIVATE:
1740 case OMP_CLAUSE_REDUCTION:
1741 case OMP_CLAUSE_LINEAR:
1742 decl = OMP_CLAUSE_DECL (c);
1743 if (is_variable_sized (decl))
1744 install_var_local (decl, ctx);
1745 fixup_remapped_decl (decl, ctx,
1746 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1747 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1748 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1749 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1750 scan_array_reductions = true;
1751 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1752 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1753 scan_array_reductions = true;
1754 break;
1756 case OMP_CLAUSE_SHARED:
1757 /* Ignore shared directives in teams construct. */
1758 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1759 break;
1760 decl = OMP_CLAUSE_DECL (c);
1761 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1762 fixup_remapped_decl (decl, ctx, false);
1763 break;
1765 case OMP_CLAUSE_MAP:
1766 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1767 break;
1768 decl = OMP_CLAUSE_DECL (c);
1769 if (DECL_P (decl)
1770 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1771 && lookup_attribute ("omp declare target",
1772 DECL_ATTRIBUTES (decl)))
1773 break;
1774 if (DECL_P (decl))
1776 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1777 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1778 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1780 tree new_decl = lookup_decl (decl, ctx);
1781 TREE_TYPE (new_decl)
1782 = remap_type (TREE_TYPE (decl), &ctx->cb);
1784 else if (DECL_SIZE (decl)
1785 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1787 tree decl2 = DECL_VALUE_EXPR (decl);
1788 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1789 decl2 = TREE_OPERAND (decl2, 0);
1790 gcc_assert (DECL_P (decl2));
1791 fixup_remapped_decl (decl2, ctx, false);
1792 fixup_remapped_decl (decl, ctx, true);
1794 else
1795 fixup_remapped_decl (decl, ctx, false);
1797 break;
1799 case OMP_CLAUSE_COPYPRIVATE:
1800 case OMP_CLAUSE_COPYIN:
1801 case OMP_CLAUSE_DEFAULT:
1802 case OMP_CLAUSE_IF:
1803 case OMP_CLAUSE_NUM_THREADS:
1804 case OMP_CLAUSE_NUM_TEAMS:
1805 case OMP_CLAUSE_THREAD_LIMIT:
1806 case OMP_CLAUSE_DEVICE:
1807 case OMP_CLAUSE_SCHEDULE:
1808 case OMP_CLAUSE_DIST_SCHEDULE:
1809 case OMP_CLAUSE_NOWAIT:
1810 case OMP_CLAUSE_ORDERED:
1811 case OMP_CLAUSE_COLLAPSE:
1812 case OMP_CLAUSE_UNTIED:
1813 case OMP_CLAUSE_FINAL:
1814 case OMP_CLAUSE_MERGEABLE:
1815 case OMP_CLAUSE_PROC_BIND:
1816 case OMP_CLAUSE_SAFELEN:
1817 case OMP_CLAUSE_ALIGNED:
1818 case OMP_CLAUSE_DEPEND:
1819 case OMP_CLAUSE__LOOPTEMP_:
1820 case OMP_CLAUSE_TO:
1821 case OMP_CLAUSE_FROM:
1822 case OMP_CLAUSE__CILK_FOR_COUNT_:
1823 break;
1825 default:
1826 gcc_unreachable ();
1830 if (scan_array_reductions)
1831 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1832 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1833 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1835 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1836 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1838 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1839 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1840 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1841 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1842 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1843 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1846 /* Create a new name for omp child function. Returns an identifier. If
1847 IS_CILK_FOR is true then the suffix for the child function is
1848 "_cilk_for_fn." */
1850 static tree
1851 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1853 if (is_cilk_for)
1854 return clone_function_name (current_function_decl, "_cilk_for_fn");
1855 return clone_function_name (current_function_decl,
1856 task_copy ? "_omp_cpyfn" : "_omp_fn");
1859 /* Returns the type of the induction variable for the child function for
1860 _Cilk_for and the types for _high and _low variables based on TYPE. */
1862 static tree
1863 cilk_for_check_loop_diff_type (tree type)
1865 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
1867 if (TYPE_UNSIGNED (type))
1868 return uint32_type_node;
1869 else
1870 return integer_type_node;
1872 else
1874 if (TYPE_UNSIGNED (type))
1875 return uint64_type_node;
1876 else
1877 return long_long_integer_type_node;
1881 /* Build a decl for the omp child function. It'll not contain a body
1882 yet, just the bare decl. */
1884 static void
1885 create_omp_child_function (omp_context *ctx, bool task_copy)
1887 tree decl, type, name, t;
1889 tree cilk_for_count
1890 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
1891 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1892 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
1893 tree cilk_var_type = NULL_TREE;
1895 name = create_omp_child_function_name (task_copy,
1896 cilk_for_count != NULL_TREE);
1897 if (task_copy)
1898 type = build_function_type_list (void_type_node, ptr_type_node,
1899 ptr_type_node, NULL_TREE);
1900 else if (cilk_for_count)
1902 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
1903 cilk_var_type = cilk_for_check_loop_diff_type (type);
1904 type = build_function_type_list (void_type_node, ptr_type_node,
1905 cilk_var_type, cilk_var_type, NULL_TREE);
1907 else
1908 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1910 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1912 if (!task_copy)
1913 ctx->cb.dst_fn = decl;
1914 else
1915 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1917 TREE_STATIC (decl) = 1;
1918 TREE_USED (decl) = 1;
1919 DECL_ARTIFICIAL (decl) = 1;
1920 DECL_IGNORED_P (decl) = 0;
1921 TREE_PUBLIC (decl) = 0;
1922 DECL_UNINLINABLE (decl) = 1;
1923 DECL_EXTERNAL (decl) = 0;
1924 DECL_CONTEXT (decl) = NULL_TREE;
1925 DECL_INITIAL (decl) = make_node (BLOCK);
1926 bool target_p = false;
1927 if (lookup_attribute ("omp declare target",
1928 DECL_ATTRIBUTES (current_function_decl)))
1929 target_p = true;
1930 else
1932 omp_context *octx;
1933 for (octx = ctx; octx; octx = octx->outer)
1934 if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
1935 && gimple_omp_target_kind (octx->stmt)
1936 == GF_OMP_TARGET_KIND_REGION)
1938 target_p = true;
1939 break;
1942 if (target_p)
1943 DECL_ATTRIBUTES (decl)
1944 = tree_cons (get_identifier ("omp declare target"),
1945 NULL_TREE, DECL_ATTRIBUTES (decl));
1947 t = build_decl (DECL_SOURCE_LOCATION (decl),
1948 RESULT_DECL, NULL_TREE, void_type_node);
1949 DECL_ARTIFICIAL (t) = 1;
1950 DECL_IGNORED_P (t) = 1;
1951 DECL_CONTEXT (t) = decl;
1952 DECL_RESULT (decl) = t;
1954 /* _Cilk_for's child function requires two extra parameters called
1955 __low and __high that are set the by Cilk runtime when it calls this
1956 function. */
1957 if (cilk_for_count)
1959 t = build_decl (DECL_SOURCE_LOCATION (decl),
1960 PARM_DECL, get_identifier ("__high"), cilk_var_type);
1961 DECL_ARTIFICIAL (t) = 1;
1962 DECL_NAMELESS (t) = 1;
1963 DECL_ARG_TYPE (t) = ptr_type_node;
1964 DECL_CONTEXT (t) = current_function_decl;
1965 TREE_USED (t) = 1;
1966 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1967 DECL_ARGUMENTS (decl) = t;
1969 t = build_decl (DECL_SOURCE_LOCATION (decl),
1970 PARM_DECL, get_identifier ("__low"), cilk_var_type);
1971 DECL_ARTIFICIAL (t) = 1;
1972 DECL_NAMELESS (t) = 1;
1973 DECL_ARG_TYPE (t) = ptr_type_node;
1974 DECL_CONTEXT (t) = current_function_decl;
1975 TREE_USED (t) = 1;
1976 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1977 DECL_ARGUMENTS (decl) = t;
1980 tree data_name = get_identifier (".omp_data_i");
1981 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
1982 ptr_type_node);
1983 DECL_ARTIFICIAL (t) = 1;
1984 DECL_NAMELESS (t) = 1;
1985 DECL_ARG_TYPE (t) = ptr_type_node;
1986 DECL_CONTEXT (t) = current_function_decl;
1987 TREE_USED (t) = 1;
1988 if (cilk_for_count)
1989 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1990 DECL_ARGUMENTS (decl) = t;
1991 if (!task_copy)
1992 ctx->receiver_decl = t;
1993 else
1995 t = build_decl (DECL_SOURCE_LOCATION (decl),
1996 PARM_DECL, get_identifier (".omp_data_o"),
1997 ptr_type_node);
1998 DECL_ARTIFICIAL (t) = 1;
1999 DECL_NAMELESS (t) = 1;
2000 DECL_ARG_TYPE (t) = ptr_type_node;
2001 DECL_CONTEXT (t) = current_function_decl;
2002 TREE_USED (t) = 1;
2003 TREE_ADDRESSABLE (t) = 1;
2004 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2005 DECL_ARGUMENTS (decl) = t;
2008 /* Allocate memory for the function structure. The call to
2009 allocate_struct_function clobbers CFUN, so we need to restore
2010 it afterward. */
2011 push_struct_function (decl);
2012 cfun->function_end_locus = gimple_location (ctx->stmt);
2013 pop_cfun ();
2016 /* Callback for walk_gimple_seq. Check if combined parallel
2017 contains gimple_omp_for_combined_into_p OMP_FOR. */
2019 static tree
2020 find_combined_for (gimple_stmt_iterator *gsi_p,
2021 bool *handled_ops_p,
2022 struct walk_stmt_info *wi)
2024 gimple stmt = gsi_stmt (*gsi_p);
2026 *handled_ops_p = true;
2027 switch (gimple_code (stmt))
2029 WALK_SUBSTMTS;
2031 case GIMPLE_OMP_FOR:
2032 if (gimple_omp_for_combined_into_p (stmt)
2033 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2035 wi->info = stmt;
2036 return integer_zero_node;
2038 break;
2039 default:
2040 break;
2042 return NULL;
2045 /* Scan an OpenMP parallel directive. */
2047 static void
2048 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2050 omp_context *ctx;
2051 tree name;
2052 gimple stmt = gsi_stmt (*gsi);
2054 /* Ignore parallel directives with empty bodies, unless there
2055 are copyin clauses. */
2056 if (optimize > 0
2057 && empty_body_p (gimple_omp_body (stmt))
2058 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2059 OMP_CLAUSE_COPYIN) == NULL)
2061 gsi_replace (gsi, gimple_build_nop (), false);
2062 return;
2065 if (gimple_omp_parallel_combined_p (stmt))
2067 gimple for_stmt;
2068 struct walk_stmt_info wi;
2070 memset (&wi, 0, sizeof (wi));
2071 wi.val_only = true;
2072 walk_gimple_seq (gimple_omp_body (stmt),
2073 find_combined_for, NULL, &wi);
2074 for_stmt = (gimple) wi.info;
2075 if (for_stmt)
2077 struct omp_for_data fd;
2078 extract_omp_for_data (for_stmt, &fd, NULL);
2079 /* We need two temporaries with fd.loop.v type (istart/iend)
2080 and then (fd.collapse - 1) temporaries with the same
2081 type for count2 ... countN-1 vars if not constant. */
2082 size_t count = 2, i;
2083 tree type = fd.iter_type;
2084 if (fd.collapse > 1
2085 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2086 count += fd.collapse - 1;
2087 for (i = 0; i < count; i++)
2089 tree temp = create_tmp_var (type, NULL);
2090 tree c = build_omp_clause (UNKNOWN_LOCATION,
2091 OMP_CLAUSE__LOOPTEMP_);
2092 insert_decl_map (&outer_ctx->cb, temp, temp);
2093 OMP_CLAUSE_DECL (c) = temp;
2094 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2095 gimple_omp_parallel_set_clauses (stmt, c);
2100 ctx = new_omp_context (stmt, outer_ctx);
2101 taskreg_contexts.safe_push (ctx);
2102 if (taskreg_nesting_level > 1)
2103 ctx->is_nested = true;
2104 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2105 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2106 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2107 name = create_tmp_var_name (".omp_data_s");
2108 name = build_decl (gimple_location (stmt),
2109 TYPE_DECL, name, ctx->record_type);
2110 DECL_ARTIFICIAL (name) = 1;
2111 DECL_NAMELESS (name) = 1;
2112 TYPE_NAME (ctx->record_type) = name;
2113 create_omp_child_function (ctx, false);
2114 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2116 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2117 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2119 if (TYPE_FIELDS (ctx->record_type) == NULL)
2120 ctx->record_type = ctx->receiver_decl = NULL;
2123 /* Scan an OpenMP task directive. */
2125 static void
2126 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2128 omp_context *ctx;
2129 tree name, t;
2130 gimple stmt = gsi_stmt (*gsi);
2132 /* Ignore task directives with empty bodies. */
2133 if (optimize > 0
2134 && empty_body_p (gimple_omp_body (stmt)))
2136 gsi_replace (gsi, gimple_build_nop (), false);
2137 return;
2140 ctx = new_omp_context (stmt, outer_ctx);
2141 taskreg_contexts.safe_push (ctx);
2142 if (taskreg_nesting_level > 1)
2143 ctx->is_nested = true;
2144 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2145 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2146 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2147 name = create_tmp_var_name (".omp_data_s");
2148 name = build_decl (gimple_location (stmt),
2149 TYPE_DECL, name, ctx->record_type);
2150 DECL_ARTIFICIAL (name) = 1;
2151 DECL_NAMELESS (name) = 1;
2152 TYPE_NAME (ctx->record_type) = name;
2153 create_omp_child_function (ctx, false);
2154 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2156 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2158 if (ctx->srecord_type)
2160 name = create_tmp_var_name (".omp_data_a");
2161 name = build_decl (gimple_location (stmt),
2162 TYPE_DECL, name, ctx->srecord_type);
2163 DECL_ARTIFICIAL (name) = 1;
2164 DECL_NAMELESS (name) = 1;
2165 TYPE_NAME (ctx->srecord_type) = name;
2166 create_omp_child_function (ctx, true);
2169 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2171 if (TYPE_FIELDS (ctx->record_type) == NULL)
2173 ctx->record_type = ctx->receiver_decl = NULL;
2174 t = build_int_cst (long_integer_type_node, 0);
2175 gimple_omp_task_set_arg_size (stmt, t);
2176 t = build_int_cst (long_integer_type_node, 1);
2177 gimple_omp_task_set_arg_align (stmt, t);
2182 /* If any decls have been made addressable during scan_omp,
2183 adjust their fields if needed, and layout record types
2184 of parallel/task constructs. */
2186 static void
2187 finish_taskreg_scan (omp_context *ctx)
2189 if (ctx->record_type == NULL_TREE)
2190 return;
2192 /* If any task_shared_vars were needed, verify all
2193 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2194 statements if use_pointer_for_field hasn't changed
2195 because of that. If it did, update field types now. */
2196 if (task_shared_vars)
2198 tree c;
2200 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2201 c; c = OMP_CLAUSE_CHAIN (c))
2202 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2204 tree decl = OMP_CLAUSE_DECL (c);
2206 /* Global variables don't need to be copied,
2207 the receiver side will use them directly. */
2208 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2209 continue;
2210 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2211 || !use_pointer_for_field (decl, ctx))
2212 continue;
2213 tree field = lookup_field (decl, ctx);
2214 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2215 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2216 continue;
2217 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2218 TREE_THIS_VOLATILE (field) = 0;
2219 DECL_USER_ALIGN (field) = 0;
2220 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2221 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2222 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2223 if (ctx->srecord_type)
2225 tree sfield = lookup_sfield (decl, ctx);
2226 TREE_TYPE (sfield) = TREE_TYPE (field);
2227 TREE_THIS_VOLATILE (sfield) = 0;
2228 DECL_USER_ALIGN (sfield) = 0;
2229 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2230 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2231 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2236 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2238 layout_type (ctx->record_type);
2239 fixup_child_record_type (ctx);
2241 else
2243 location_t loc = gimple_location (ctx->stmt);
2244 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2245 /* Move VLA fields to the end. */
2246 p = &TYPE_FIELDS (ctx->record_type);
2247 while (*p)
2248 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2249 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2251 *q = *p;
2252 *p = TREE_CHAIN (*p);
2253 TREE_CHAIN (*q) = NULL_TREE;
2254 q = &TREE_CHAIN (*q);
2256 else
2257 p = &DECL_CHAIN (*p);
2258 *p = vla_fields;
2259 layout_type (ctx->record_type);
2260 fixup_child_record_type (ctx);
2261 if (ctx->srecord_type)
2262 layout_type (ctx->srecord_type);
2263 tree t = fold_convert_loc (loc, long_integer_type_node,
2264 TYPE_SIZE_UNIT (ctx->record_type));
2265 gimple_omp_task_set_arg_size (ctx->stmt, t);
2266 t = build_int_cst (long_integer_type_node,
2267 TYPE_ALIGN_UNIT (ctx->record_type));
2268 gimple_omp_task_set_arg_align (ctx->stmt, t);
2273 /* Scan an OpenMP loop directive. */
2275 static void
2276 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2278 omp_context *ctx;
2279 size_t i;
2281 ctx = new_omp_context (stmt, outer_ctx);
2283 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2285 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2286 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2288 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2289 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2290 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2291 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2293 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2296 /* Scan an OpenMP sections directive. */
2298 static void
2299 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2301 omp_context *ctx;
2303 ctx = new_omp_context (stmt, outer_ctx);
2304 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2305 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2308 /* Scan an OpenMP single directive. */
2310 static void
2311 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2313 omp_context *ctx;
2314 tree name;
2316 ctx = new_omp_context (stmt, outer_ctx);
2317 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2318 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2319 name = create_tmp_var_name (".omp_copy_s");
2320 name = build_decl (gimple_location (stmt),
2321 TYPE_DECL, name, ctx->record_type);
2322 TYPE_NAME (ctx->record_type) = name;
2324 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2325 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2327 if (TYPE_FIELDS (ctx->record_type) == NULL)
2328 ctx->record_type = NULL;
2329 else
2330 layout_type (ctx->record_type);
2333 /* Scan an OpenMP target{, data, update} directive. */
2335 static void
2336 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2338 omp_context *ctx;
2339 tree name;
2340 int kind = gimple_omp_target_kind (stmt);
2342 ctx = new_omp_context (stmt, outer_ctx);
2343 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2344 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2345 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2346 name = create_tmp_var_name (".omp_data_t");
2347 name = build_decl (gimple_location (stmt),
2348 TYPE_DECL, name, ctx->record_type);
2349 DECL_ARTIFICIAL (name) = 1;
2350 DECL_NAMELESS (name) = 1;
2351 TYPE_NAME (ctx->record_type) = name;
2352 if (kind == GF_OMP_TARGET_KIND_REGION)
2354 create_omp_child_function (ctx, false);
2355 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2358 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2359 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2361 if (TYPE_FIELDS (ctx->record_type) == NULL)
2362 ctx->record_type = ctx->receiver_decl = NULL;
2363 else
2365 TYPE_FIELDS (ctx->record_type)
2366 = nreverse (TYPE_FIELDS (ctx->record_type));
2367 #ifdef ENABLE_CHECKING
2368 tree field;
2369 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2370 for (field = TYPE_FIELDS (ctx->record_type);
2371 field;
2372 field = DECL_CHAIN (field))
2373 gcc_assert (DECL_ALIGN (field) == align);
2374 #endif
2375 layout_type (ctx->record_type);
2376 if (kind == GF_OMP_TARGET_KIND_REGION)
2377 fixup_child_record_type (ctx);
2381 /* Scan an OpenMP teams directive. */
2383 static void
2384 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2386 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2387 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2388 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2391 /* Check OpenMP nesting restrictions. */
2392 static bool
2393 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2395 if (ctx != NULL)
2397 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2398 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2400 error_at (gimple_location (stmt),
2401 "OpenMP constructs may not be nested inside simd region");
2402 return false;
2404 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2406 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2407 || (gimple_omp_for_kind (stmt)
2408 != GF_OMP_FOR_KIND_DISTRIBUTE))
2409 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2411 error_at (gimple_location (stmt),
2412 "only distribute or parallel constructs are allowed to "
2413 "be closely nested inside teams construct");
2414 return false;
2418 switch (gimple_code (stmt))
2420 case GIMPLE_OMP_FOR:
2421 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2422 return true;
2423 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2425 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2427 error_at (gimple_location (stmt),
2428 "distribute construct must be closely nested inside "
2429 "teams construct");
2430 return false;
2432 return true;
2434 /* FALLTHRU */
2435 case GIMPLE_CALL:
2436 if (is_gimple_call (stmt)
2437 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2438 == BUILT_IN_GOMP_CANCEL
2439 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2440 == BUILT_IN_GOMP_CANCELLATION_POINT))
2442 const char *bad = NULL;
2443 const char *kind = NULL;
2444 if (ctx == NULL)
2446 error_at (gimple_location (stmt), "orphaned %qs construct",
2447 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2448 == BUILT_IN_GOMP_CANCEL
2449 ? "#pragma omp cancel"
2450 : "#pragma omp cancellation point");
2451 return false;
2453 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2454 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2455 : 0)
2457 case 1:
2458 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2459 bad = "#pragma omp parallel";
2460 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2461 == BUILT_IN_GOMP_CANCEL
2462 && !integer_zerop (gimple_call_arg (stmt, 1)))
2463 ctx->cancellable = true;
2464 kind = "parallel";
2465 break;
2466 case 2:
2467 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2468 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2469 bad = "#pragma omp for";
2470 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2471 == BUILT_IN_GOMP_CANCEL
2472 && !integer_zerop (gimple_call_arg (stmt, 1)))
2474 ctx->cancellable = true;
2475 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2476 OMP_CLAUSE_NOWAIT))
2477 warning_at (gimple_location (stmt), 0,
2478 "%<#pragma omp cancel for%> inside "
2479 "%<nowait%> for construct");
2480 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2481 OMP_CLAUSE_ORDERED))
2482 warning_at (gimple_location (stmt), 0,
2483 "%<#pragma omp cancel for%> inside "
2484 "%<ordered%> for construct");
2486 kind = "for";
2487 break;
2488 case 4:
2489 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2490 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2491 bad = "#pragma omp sections";
2492 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2493 == BUILT_IN_GOMP_CANCEL
2494 && !integer_zerop (gimple_call_arg (stmt, 1)))
2496 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2498 ctx->cancellable = true;
2499 if (find_omp_clause (gimple_omp_sections_clauses
2500 (ctx->stmt),
2501 OMP_CLAUSE_NOWAIT))
2502 warning_at (gimple_location (stmt), 0,
2503 "%<#pragma omp cancel sections%> inside "
2504 "%<nowait%> sections construct");
2506 else
2508 gcc_assert (ctx->outer
2509 && gimple_code (ctx->outer->stmt)
2510 == GIMPLE_OMP_SECTIONS);
2511 ctx->outer->cancellable = true;
2512 if (find_omp_clause (gimple_omp_sections_clauses
2513 (ctx->outer->stmt),
2514 OMP_CLAUSE_NOWAIT))
2515 warning_at (gimple_location (stmt), 0,
2516 "%<#pragma omp cancel sections%> inside "
2517 "%<nowait%> sections construct");
2520 kind = "sections";
2521 break;
2522 case 8:
2523 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2524 bad = "#pragma omp task";
2525 else
2526 ctx->cancellable = true;
2527 kind = "taskgroup";
2528 break;
2529 default:
2530 error_at (gimple_location (stmt), "invalid arguments");
2531 return false;
2533 if (bad)
2535 error_at (gimple_location (stmt),
2536 "%<%s %s%> construct not closely nested inside of %qs",
2537 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2538 == BUILT_IN_GOMP_CANCEL
2539 ? "#pragma omp cancel"
2540 : "#pragma omp cancellation point", kind, bad);
2541 return false;
2544 /* FALLTHRU */
2545 case GIMPLE_OMP_SECTIONS:
2546 case GIMPLE_OMP_SINGLE:
2547 for (; ctx != NULL; ctx = ctx->outer)
2548 switch (gimple_code (ctx->stmt))
2550 case GIMPLE_OMP_FOR:
2551 case GIMPLE_OMP_SECTIONS:
2552 case GIMPLE_OMP_SINGLE:
2553 case GIMPLE_OMP_ORDERED:
2554 case GIMPLE_OMP_MASTER:
2555 case GIMPLE_OMP_TASK:
2556 case GIMPLE_OMP_CRITICAL:
2557 if (is_gimple_call (stmt))
2559 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2560 != BUILT_IN_GOMP_BARRIER)
2561 return true;
2562 error_at (gimple_location (stmt),
2563 "barrier region may not be closely nested inside "
2564 "of work-sharing, critical, ordered, master or "
2565 "explicit task region");
2566 return false;
2568 error_at (gimple_location (stmt),
2569 "work-sharing region may not be closely nested inside "
2570 "of work-sharing, critical, ordered, master or explicit "
2571 "task region");
2572 return false;
2573 case GIMPLE_OMP_PARALLEL:
2574 return true;
2575 default:
2576 break;
2578 break;
2579 case GIMPLE_OMP_MASTER:
2580 for (; ctx != NULL; ctx = ctx->outer)
2581 switch (gimple_code (ctx->stmt))
2583 case GIMPLE_OMP_FOR:
2584 case GIMPLE_OMP_SECTIONS:
2585 case GIMPLE_OMP_SINGLE:
2586 case GIMPLE_OMP_TASK:
2587 error_at (gimple_location (stmt),
2588 "master region may not be closely nested inside "
2589 "of work-sharing or explicit task region");
2590 return false;
2591 case GIMPLE_OMP_PARALLEL:
2592 return true;
2593 default:
2594 break;
2596 break;
2597 case GIMPLE_OMP_ORDERED:
2598 for (; ctx != NULL; ctx = ctx->outer)
2599 switch (gimple_code (ctx->stmt))
2601 case GIMPLE_OMP_CRITICAL:
2602 case GIMPLE_OMP_TASK:
2603 error_at (gimple_location (stmt),
2604 "ordered region may not be closely nested inside "
2605 "of critical or explicit task region");
2606 return false;
2607 case GIMPLE_OMP_FOR:
2608 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2609 OMP_CLAUSE_ORDERED) == NULL)
2611 error_at (gimple_location (stmt),
2612 "ordered region must be closely nested inside "
2613 "a loop region with an ordered clause");
2614 return false;
2616 return true;
2617 case GIMPLE_OMP_PARALLEL:
2618 error_at (gimple_location (stmt),
2619 "ordered region must be closely nested inside "
2620 "a loop region with an ordered clause");
2621 return false;
2622 default:
2623 break;
2625 break;
2626 case GIMPLE_OMP_CRITICAL:
2627 for (; ctx != NULL; ctx = ctx->outer)
2628 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2629 && (gimple_omp_critical_name (stmt)
2630 == gimple_omp_critical_name (ctx->stmt)))
2632 error_at (gimple_location (stmt),
2633 "critical region may not be nested inside a critical "
2634 "region with the same name");
2635 return false;
2637 break;
2638 case GIMPLE_OMP_TEAMS:
2639 if (ctx == NULL
2640 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2641 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2643 error_at (gimple_location (stmt),
2644 "teams construct not closely nested inside of target "
2645 "region");
2646 return false;
2648 break;
2649 case GIMPLE_OMP_TARGET:
2650 for (; ctx != NULL; ctx = ctx->outer)
2651 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
2652 && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION)
2654 const char *name;
2655 switch (gimple_omp_target_kind (stmt))
2657 case GF_OMP_TARGET_KIND_REGION: name = "target"; break;
2658 case GF_OMP_TARGET_KIND_DATA: name = "target data"; break;
2659 case GF_OMP_TARGET_KIND_UPDATE: name = "target update"; break;
2660 default: gcc_unreachable ();
2662 warning_at (gimple_location (stmt), 0,
2663 "%s construct inside of target region", name);
2665 break;
2666 default:
2667 break;
2669 return true;
2673 /* Helper function scan_omp.
2675 Callback for walk_tree or operators in walk_gimple_stmt used to
2676 scan for OpenMP directives in TP. */
2678 static tree
2679 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2681 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2682 omp_context *ctx = (omp_context *) wi->info;
2683 tree t = *tp;
2685 switch (TREE_CODE (t))
2687 case VAR_DECL:
2688 case PARM_DECL:
2689 case LABEL_DECL:
2690 case RESULT_DECL:
2691 if (ctx)
2692 *tp = remap_decl (t, &ctx->cb);
2693 break;
2695 default:
2696 if (ctx && TYPE_P (t))
2697 *tp = remap_type (t, &ctx->cb);
2698 else if (!DECL_P (t))
2700 *walk_subtrees = 1;
2701 if (ctx)
2703 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2704 if (tem != TREE_TYPE (t))
2706 if (TREE_CODE (t) == INTEGER_CST)
2707 *tp = wide_int_to_tree (tem, t);
2708 else
2709 TREE_TYPE (t) = tem;
2713 break;
2716 return NULL_TREE;
2719 /* Return true if FNDECL is a setjmp or a longjmp. */
2721 static bool
2722 setjmp_or_longjmp_p (const_tree fndecl)
2724 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2725 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2726 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2727 return true;
2729 tree declname = DECL_NAME (fndecl);
2730 if (!declname)
2731 return false;
2732 const char *name = IDENTIFIER_POINTER (declname);
2733 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2737 /* Helper function for scan_omp.
2739 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2740 the current statement in GSI. */
2742 static tree
2743 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2744 struct walk_stmt_info *wi)
2746 gimple stmt = gsi_stmt (*gsi);
2747 omp_context *ctx = (omp_context *) wi->info;
2749 if (gimple_has_location (stmt))
2750 input_location = gimple_location (stmt);
2752 /* Check the OpenMP nesting restrictions. */
2753 bool remove = false;
2754 if (is_gimple_omp (stmt))
2755 remove = !check_omp_nesting_restrictions (stmt, ctx);
2756 else if (is_gimple_call (stmt))
2758 tree fndecl = gimple_call_fndecl (stmt);
2759 if (fndecl)
2761 if (setjmp_or_longjmp_p (fndecl)
2762 && ctx
2763 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2764 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2766 remove = true;
2767 error_at (gimple_location (stmt),
2768 "setjmp/longjmp inside simd construct");
2770 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2771 switch (DECL_FUNCTION_CODE (fndecl))
2773 case BUILT_IN_GOMP_BARRIER:
2774 case BUILT_IN_GOMP_CANCEL:
2775 case BUILT_IN_GOMP_CANCELLATION_POINT:
2776 case BUILT_IN_GOMP_TASKYIELD:
2777 case BUILT_IN_GOMP_TASKWAIT:
2778 case BUILT_IN_GOMP_TASKGROUP_START:
2779 case BUILT_IN_GOMP_TASKGROUP_END:
2780 remove = !check_omp_nesting_restrictions (stmt, ctx);
2781 break;
2782 default:
2783 break;
2787 if (remove)
2789 stmt = gimple_build_nop ();
2790 gsi_replace (gsi, stmt, false);
2793 *handled_ops_p = true;
2795 switch (gimple_code (stmt))
2797 case GIMPLE_OMP_PARALLEL:
2798 taskreg_nesting_level++;
2799 scan_omp_parallel (gsi, ctx);
2800 taskreg_nesting_level--;
2801 break;
2803 case GIMPLE_OMP_TASK:
2804 taskreg_nesting_level++;
2805 scan_omp_task (gsi, ctx);
2806 taskreg_nesting_level--;
2807 break;
2809 case GIMPLE_OMP_FOR:
2810 scan_omp_for (stmt, ctx);
2811 break;
2813 case GIMPLE_OMP_SECTIONS:
2814 scan_omp_sections (stmt, ctx);
2815 break;
2817 case GIMPLE_OMP_SINGLE:
2818 scan_omp_single (stmt, ctx);
2819 break;
2821 case GIMPLE_OMP_SECTION:
2822 case GIMPLE_OMP_MASTER:
2823 case GIMPLE_OMP_TASKGROUP:
2824 case GIMPLE_OMP_ORDERED:
2825 case GIMPLE_OMP_CRITICAL:
2826 ctx = new_omp_context (stmt, ctx);
2827 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2828 break;
2830 case GIMPLE_OMP_TARGET:
2831 scan_omp_target (stmt, ctx);
2832 break;
2834 case GIMPLE_OMP_TEAMS:
2835 scan_omp_teams (stmt, ctx);
2836 break;
2838 case GIMPLE_BIND:
2840 tree var;
2842 *handled_ops_p = false;
2843 if (ctx)
2844 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2845 insert_decl_map (&ctx->cb, var, var);
2847 break;
2848 default:
2849 *handled_ops_p = false;
2850 break;
2853 return NULL_TREE;
2857 /* Scan all the statements starting at the current statement. CTX
2858 contains context information about the OpenMP directives and
2859 clauses found during the scan. */
2861 static void
2862 scan_omp (gimple_seq *body_p, omp_context *ctx)
2864 location_t saved_location;
2865 struct walk_stmt_info wi;
2867 memset (&wi, 0, sizeof (wi));
2868 wi.info = ctx;
2869 wi.want_locations = true;
2871 saved_location = input_location;
2872 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2873 input_location = saved_location;
2876 /* Re-gimplification and code generation routines. */
2878 /* Build a call to GOMP_barrier. */
2880 static gimple
2881 build_omp_barrier (tree lhs)
2883 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2884 : BUILT_IN_GOMP_BARRIER);
2885 gimple g = gimple_build_call (fndecl, 0);
2886 if (lhs)
2887 gimple_call_set_lhs (g, lhs);
2888 return g;
2891 /* If a context was created for STMT when it was scanned, return it. */
2893 static omp_context *
2894 maybe_lookup_ctx (gimple stmt)
2896 splay_tree_node n;
2897 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2898 return n ? (omp_context *) n->value : NULL;
2902 /* Find the mapping for DECL in CTX or the immediately enclosing
2903 context that has a mapping for DECL.
2905 If CTX is a nested parallel directive, we may have to use the decl
2906 mappings created in CTX's parent context. Suppose that we have the
2907 following parallel nesting (variable UIDs showed for clarity):
2909 iD.1562 = 0;
2910 #omp parallel shared(iD.1562) -> outer parallel
2911 iD.1562 = iD.1562 + 1;
2913 #omp parallel shared (iD.1562) -> inner parallel
2914 iD.1562 = iD.1562 - 1;
2916 Each parallel structure will create a distinct .omp_data_s structure
2917 for copying iD.1562 in/out of the directive:
2919 outer parallel .omp_data_s.1.i -> iD.1562
2920 inner parallel .omp_data_s.2.i -> iD.1562
2922 A shared variable mapping will produce a copy-out operation before
2923 the parallel directive and a copy-in operation after it. So, in
2924 this case we would have:
2926 iD.1562 = 0;
2927 .omp_data_o.1.i = iD.1562;
2928 #omp parallel shared(iD.1562) -> outer parallel
2929 .omp_data_i.1 = &.omp_data_o.1
2930 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2932 .omp_data_o.2.i = iD.1562; -> **
2933 #omp parallel shared(iD.1562) -> inner parallel
2934 .omp_data_i.2 = &.omp_data_o.2
2935 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2938 ** This is a problem. The symbol iD.1562 cannot be referenced
2939 inside the body of the outer parallel region. But since we are
2940 emitting this copy operation while expanding the inner parallel
2941 directive, we need to access the CTX structure of the outer
2942 parallel directive to get the correct mapping:
2944 .omp_data_o.2.i = .omp_data_i.1->i
2946 Since there may be other workshare or parallel directives enclosing
2947 the parallel directive, it may be necessary to walk up the context
2948 parent chain. This is not a problem in general because nested
2949 parallelism happens only rarely. */
2951 static tree
2952 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2954 tree t;
2955 omp_context *up;
2957 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2958 t = maybe_lookup_decl (decl, up);
2960 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2962 return t ? t : decl;
2966 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2967 in outer contexts. */
2969 static tree
2970 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2972 tree t = NULL;
2973 omp_context *up;
2975 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2976 t = maybe_lookup_decl (decl, up);
2978 return t ? t : decl;
2982 /* Construct the initialization value for reduction CLAUSE. */
2984 tree
2985 omp_reduction_init (tree clause, tree type)
2987 location_t loc = OMP_CLAUSE_LOCATION (clause);
2988 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2990 case PLUS_EXPR:
2991 case MINUS_EXPR:
2992 case BIT_IOR_EXPR:
2993 case BIT_XOR_EXPR:
2994 case TRUTH_OR_EXPR:
2995 case TRUTH_ORIF_EXPR:
2996 case TRUTH_XOR_EXPR:
2997 case NE_EXPR:
2998 return build_zero_cst (type);
3000 case MULT_EXPR:
3001 case TRUTH_AND_EXPR:
3002 case TRUTH_ANDIF_EXPR:
3003 case EQ_EXPR:
3004 return fold_convert_loc (loc, type, integer_one_node);
3006 case BIT_AND_EXPR:
3007 return fold_convert_loc (loc, type, integer_minus_one_node);
3009 case MAX_EXPR:
3010 if (SCALAR_FLOAT_TYPE_P (type))
3012 REAL_VALUE_TYPE max, min;
3013 if (HONOR_INFINITIES (TYPE_MODE (type)))
3015 real_inf (&max);
3016 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3018 else
3019 real_maxval (&min, 1, TYPE_MODE (type));
3020 return build_real (type, min);
3022 else
3024 gcc_assert (INTEGRAL_TYPE_P (type));
3025 return TYPE_MIN_VALUE (type);
3028 case MIN_EXPR:
3029 if (SCALAR_FLOAT_TYPE_P (type))
3031 REAL_VALUE_TYPE max;
3032 if (HONOR_INFINITIES (TYPE_MODE (type)))
3033 real_inf (&max);
3034 else
3035 real_maxval (&max, 0, TYPE_MODE (type));
3036 return build_real (type, max);
3038 else
3040 gcc_assert (INTEGRAL_TYPE_P (type));
3041 return TYPE_MAX_VALUE (type);
3044 default:
3045 gcc_unreachable ();
3049 /* Return alignment to be assumed for var in CLAUSE, which should be
3050 OMP_CLAUSE_ALIGNED. */
3052 static tree
3053 omp_clause_aligned_alignment (tree clause)
3055 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3056 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3058 /* Otherwise return implementation defined alignment. */
3059 unsigned int al = 1;
3060 enum machine_mode mode, vmode;
3061 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3062 if (vs)
3063 vs = 1 << floor_log2 (vs);
3064 static enum mode_class classes[]
3065 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3066 for (int i = 0; i < 4; i += 2)
3067 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3068 mode != VOIDmode;
3069 mode = GET_MODE_WIDER_MODE (mode))
3071 vmode = targetm.vectorize.preferred_simd_mode (mode);
3072 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3073 continue;
3074 while (vs
3075 && GET_MODE_SIZE (vmode) < vs
3076 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3077 vmode = GET_MODE_2XWIDER_MODE (vmode);
3079 tree type = lang_hooks.types.type_for_mode (mode, 1);
3080 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3081 continue;
3082 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3083 / GET_MODE_SIZE (mode));
3084 if (TYPE_MODE (type) != vmode)
3085 continue;
3086 if (TYPE_ALIGN_UNIT (type) > al)
3087 al = TYPE_ALIGN_UNIT (type);
3089 return build_int_cst (integer_type_node, al);
3092 /* Return maximum possible vectorization factor for the target. */
3094 static int
3095 omp_max_vf (void)
3097 if (!optimize
3098 || optimize_debug
3099 || !flag_tree_loop_optimize
3100 || (!flag_tree_loop_vectorize
3101 && (global_options_set.x_flag_tree_loop_vectorize
3102 || global_options_set.x_flag_tree_vectorize)))
3103 return 1;
3105 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3106 if (vs)
3108 vs = 1 << floor_log2 (vs);
3109 return vs;
3111 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3112 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3113 return GET_MODE_NUNITS (vqimode);
3114 return 1;
3117 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3118 privatization. */
3120 static bool
3121 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3122 tree &idx, tree &lane, tree &ivar, tree &lvar)
3124 if (max_vf == 0)
3126 max_vf = omp_max_vf ();
3127 if (max_vf > 1)
3129 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3130 OMP_CLAUSE_SAFELEN);
3131 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3132 max_vf = 1;
3133 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3134 max_vf) == -1)
3135 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3137 if (max_vf > 1)
3139 idx = create_tmp_var (unsigned_type_node, NULL);
3140 lane = create_tmp_var (unsigned_type_node, NULL);
3143 if (max_vf == 1)
3144 return false;
3146 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3147 tree avar = create_tmp_var_raw (atype, NULL);
3148 if (TREE_ADDRESSABLE (new_var))
3149 TREE_ADDRESSABLE (avar) = 1;
3150 DECL_ATTRIBUTES (avar)
3151 = tree_cons (get_identifier ("omp simd array"), NULL,
3152 DECL_ATTRIBUTES (avar));
3153 gimple_add_tmp_var (avar);
3154 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3155 NULL_TREE, NULL_TREE);
3156 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3157 NULL_TREE, NULL_TREE);
3158 if (DECL_P (new_var))
3160 SET_DECL_VALUE_EXPR (new_var, lvar);
3161 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3163 return true;
3166 /* Helper function of lower_rec_input_clauses. For a reference
3167 in simd reduction, add an underlying variable it will reference. */
3169 static void
3170 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3172 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3173 if (TREE_CONSTANT (z))
3175 const char *name = NULL;
3176 if (DECL_NAME (new_vard))
3177 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3179 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3180 gimple_add_tmp_var (z);
3181 TREE_ADDRESSABLE (z) = 1;
3182 z = build_fold_addr_expr_loc (loc, z);
3183 gimplify_assign (new_vard, z, ilist);
3187 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3188 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3189 private variables. Initialization statements go in ILIST, while calls
3190 to destructors go in DLIST. */
3192 static void
3193 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3194 omp_context *ctx, struct omp_for_data *fd)
3196 tree c, dtor, copyin_seq, x, ptr;
3197 bool copyin_by_ref = false;
3198 bool lastprivate_firstprivate = false;
3199 bool reduction_omp_orig_ref = false;
3200 int pass;
3201 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3202 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3203 int max_vf = 0;
3204 tree lane = NULL_TREE, idx = NULL_TREE;
3205 tree ivar = NULL_TREE, lvar = NULL_TREE;
3206 gimple_seq llist[2] = { NULL, NULL };
3208 copyin_seq = NULL;
3210 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3211 with data sharing clauses referencing variable sized vars. That
3212 is unnecessarily hard to support and very unlikely to result in
3213 vectorized code anyway. */
3214 if (is_simd)
3215 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3216 switch (OMP_CLAUSE_CODE (c))
3218 case OMP_CLAUSE_LINEAR:
3219 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3220 max_vf = 1;
3221 /* FALLTHRU */
3222 case OMP_CLAUSE_REDUCTION:
3223 case OMP_CLAUSE_PRIVATE:
3224 case OMP_CLAUSE_FIRSTPRIVATE:
3225 case OMP_CLAUSE_LASTPRIVATE:
3226 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3227 max_vf = 1;
3228 break;
3229 default:
3230 continue;
3233 /* Do all the fixed sized types in the first pass, and the variable sized
3234 types in the second pass. This makes sure that the scalar arguments to
3235 the variable sized types are processed before we use them in the
3236 variable sized operations. */
3237 for (pass = 0; pass < 2; ++pass)
3239 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3241 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3242 tree var, new_var;
3243 bool by_ref;
3244 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3246 switch (c_kind)
3248 case OMP_CLAUSE_PRIVATE:
3249 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3250 continue;
3251 break;
3252 case OMP_CLAUSE_SHARED:
3253 /* Ignore shared directives in teams construct. */
3254 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3255 continue;
3256 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3258 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3259 continue;
3261 case OMP_CLAUSE_FIRSTPRIVATE:
3262 case OMP_CLAUSE_COPYIN:
3263 case OMP_CLAUSE_LINEAR:
3264 break;
3265 case OMP_CLAUSE_REDUCTION:
3266 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3267 reduction_omp_orig_ref = true;
3268 break;
3269 case OMP_CLAUSE__LOOPTEMP_:
3270 /* Handle _looptemp_ clauses only on parallel. */
3271 if (fd)
3272 continue;
3273 break;
3274 case OMP_CLAUSE_LASTPRIVATE:
3275 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3277 lastprivate_firstprivate = true;
3278 if (pass != 0)
3279 continue;
3281 /* Even without corresponding firstprivate, if
3282 decl is Fortran allocatable, it needs outer var
3283 reference. */
3284 else if (pass == 0
3285 && lang_hooks.decls.omp_private_outer_ref
3286 (OMP_CLAUSE_DECL (c)))
3287 lastprivate_firstprivate = true;
3288 break;
3289 case OMP_CLAUSE_ALIGNED:
3290 if (pass == 0)
3291 continue;
3292 var = OMP_CLAUSE_DECL (c);
3293 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3294 && !is_global_var (var))
3296 new_var = maybe_lookup_decl (var, ctx);
3297 if (new_var == NULL_TREE)
3298 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3299 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3300 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3301 omp_clause_aligned_alignment (c));
3302 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3303 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3304 gimplify_and_add (x, ilist);
3306 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3307 && is_global_var (var))
3309 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3310 new_var = lookup_decl (var, ctx);
3311 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3312 t = build_fold_addr_expr_loc (clause_loc, t);
3313 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3314 t = build_call_expr_loc (clause_loc, t2, 2, t,
3315 omp_clause_aligned_alignment (c));
3316 t = fold_convert_loc (clause_loc, ptype, t);
3317 x = create_tmp_var (ptype, NULL);
3318 t = build2 (MODIFY_EXPR, ptype, x, t);
3319 gimplify_and_add (t, ilist);
3320 t = build_simple_mem_ref_loc (clause_loc, x);
3321 SET_DECL_VALUE_EXPR (new_var, t);
3322 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3324 continue;
3325 default:
3326 continue;
3329 new_var = var = OMP_CLAUSE_DECL (c);
3330 if (c_kind != OMP_CLAUSE_COPYIN)
3331 new_var = lookup_decl (var, ctx);
3333 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3335 if (pass != 0)
3336 continue;
3338 else if (is_variable_sized (var))
3340 /* For variable sized types, we need to allocate the
3341 actual storage here. Call alloca and store the
3342 result in the pointer decl that we created elsewhere. */
3343 if (pass == 0)
3344 continue;
3346 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3348 gimple stmt;
3349 tree tmp, atmp;
3351 ptr = DECL_VALUE_EXPR (new_var);
3352 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3353 ptr = TREE_OPERAND (ptr, 0);
3354 gcc_assert (DECL_P (ptr));
3355 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3357 /* void *tmp = __builtin_alloca */
3358 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3359 stmt = gimple_build_call (atmp, 1, x);
3360 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3361 gimple_add_tmp_var (tmp);
3362 gimple_call_set_lhs (stmt, tmp);
3364 gimple_seq_add_stmt (ilist, stmt);
3366 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3367 gimplify_assign (ptr, x, ilist);
3370 else if (is_reference (var))
3372 /* For references that are being privatized for Fortran,
3373 allocate new backing storage for the new pointer
3374 variable. This allows us to avoid changing all the
3375 code that expects a pointer to something that expects
3376 a direct variable. */
3377 if (pass == 0)
3378 continue;
3380 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3381 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3383 x = build_receiver_ref (var, false, ctx);
3384 x = build_fold_addr_expr_loc (clause_loc, x);
3386 else if (TREE_CONSTANT (x))
3388 /* For reduction in SIMD loop, defer adding the
3389 initialization of the reference, because if we decide
3390 to use SIMD array for it, the initilization could cause
3391 expansion ICE. */
3392 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3393 x = NULL_TREE;
3394 else
3396 const char *name = NULL;
3397 if (DECL_NAME (var))
3398 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3400 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3401 name);
3402 gimple_add_tmp_var (x);
3403 TREE_ADDRESSABLE (x) = 1;
3404 x = build_fold_addr_expr_loc (clause_loc, x);
3407 else
3409 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3410 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3413 if (x)
3415 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3416 gimplify_assign (new_var, x, ilist);
3419 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3421 else if (c_kind == OMP_CLAUSE_REDUCTION
3422 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3424 if (pass == 0)
3425 continue;
3427 else if (pass != 0)
3428 continue;
3430 switch (OMP_CLAUSE_CODE (c))
3432 case OMP_CLAUSE_SHARED:
3433 /* Ignore shared directives in teams construct. */
3434 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3435 continue;
3436 /* Shared global vars are just accessed directly. */
3437 if (is_global_var (new_var))
3438 break;
3439 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3440 needs to be delayed until after fixup_child_record_type so
3441 that we get the correct type during the dereference. */
3442 by_ref = use_pointer_for_field (var, ctx);
3443 x = build_receiver_ref (var, by_ref, ctx);
3444 SET_DECL_VALUE_EXPR (new_var, x);
3445 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3447 /* ??? If VAR is not passed by reference, and the variable
3448 hasn't been initialized yet, then we'll get a warning for
3449 the store into the omp_data_s structure. Ideally, we'd be
3450 able to notice this and not store anything at all, but
3451 we're generating code too early. Suppress the warning. */
3452 if (!by_ref)
3453 TREE_NO_WARNING (var) = 1;
3454 break;
3456 case OMP_CLAUSE_LASTPRIVATE:
3457 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3458 break;
3459 /* FALLTHRU */
3461 case OMP_CLAUSE_PRIVATE:
3462 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3463 x = build_outer_var_ref (var, ctx);
3464 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3466 if (is_task_ctx (ctx))
3467 x = build_receiver_ref (var, false, ctx);
3468 else
3469 x = build_outer_var_ref (var, ctx);
3471 else
3472 x = NULL;
3473 do_private:
3474 tree nx;
3475 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3476 if (is_simd)
3478 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3479 if ((TREE_ADDRESSABLE (new_var) || nx || y
3480 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3481 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3482 idx, lane, ivar, lvar))
3484 if (nx)
3485 x = lang_hooks.decls.omp_clause_default_ctor
3486 (c, unshare_expr (ivar), x);
3487 if (nx && x)
3488 gimplify_and_add (x, &llist[0]);
3489 if (y)
3491 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3492 if (y)
3494 gimple_seq tseq = NULL;
3496 dtor = y;
3497 gimplify_stmt (&dtor, &tseq);
3498 gimple_seq_add_seq (&llist[1], tseq);
3501 break;
3504 if (nx)
3505 gimplify_and_add (nx, ilist);
3506 /* FALLTHRU */
3508 do_dtor:
3509 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3510 if (x)
3512 gimple_seq tseq = NULL;
3514 dtor = x;
3515 gimplify_stmt (&dtor, &tseq);
3516 gimple_seq_add_seq (dlist, tseq);
3518 break;
3520 case OMP_CLAUSE_LINEAR:
3521 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3522 goto do_firstprivate;
3523 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3524 x = NULL;
3525 else
3526 x = build_outer_var_ref (var, ctx);
3527 goto do_private;
3529 case OMP_CLAUSE_FIRSTPRIVATE:
3530 if (is_task_ctx (ctx))
3532 if (is_reference (var) || is_variable_sized (var))
3533 goto do_dtor;
3534 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3535 ctx))
3536 || use_pointer_for_field (var, NULL))
3538 x = build_receiver_ref (var, false, ctx);
3539 SET_DECL_VALUE_EXPR (new_var, x);
3540 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3541 goto do_dtor;
3544 do_firstprivate:
3545 x = build_outer_var_ref (var, ctx);
3546 if (is_simd)
3548 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3549 && gimple_omp_for_combined_into_p (ctx->stmt))
3551 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3552 tree stept = TREE_TYPE (t);
3553 tree ct = find_omp_clause (clauses,
3554 OMP_CLAUSE__LOOPTEMP_);
3555 gcc_assert (ct);
3556 tree l = OMP_CLAUSE_DECL (ct);
3557 tree n1 = fd->loop.n1;
3558 tree step = fd->loop.step;
3559 tree itype = TREE_TYPE (l);
3560 if (POINTER_TYPE_P (itype))
3561 itype = signed_type_for (itype);
3562 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3563 if (TYPE_UNSIGNED (itype)
3564 && fd->loop.cond_code == GT_EXPR)
3565 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3566 fold_build1 (NEGATE_EXPR, itype, l),
3567 fold_build1 (NEGATE_EXPR,
3568 itype, step));
3569 else
3570 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3571 t = fold_build2 (MULT_EXPR, stept,
3572 fold_convert (stept, l), t);
3574 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3576 x = lang_hooks.decls.omp_clause_linear_ctor
3577 (c, new_var, x, t);
3578 gimplify_and_add (x, ilist);
3579 goto do_dtor;
3582 if (POINTER_TYPE_P (TREE_TYPE (x)))
3583 x = fold_build2 (POINTER_PLUS_EXPR,
3584 TREE_TYPE (x), x, t);
3585 else
3586 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3589 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3590 || TREE_ADDRESSABLE (new_var))
3591 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3592 idx, lane, ivar, lvar))
3594 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3596 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3597 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3598 gimplify_and_add (x, ilist);
3599 gimple_stmt_iterator gsi
3600 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3601 gimple g
3602 = gimple_build_assign (unshare_expr (lvar), iv);
3603 gsi_insert_before_without_update (&gsi, g,
3604 GSI_SAME_STMT);
3605 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3606 enum tree_code code = PLUS_EXPR;
3607 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3608 code = POINTER_PLUS_EXPR;
3609 g = gimple_build_assign_with_ops (code, iv, iv, t);
3610 gsi_insert_before_without_update (&gsi, g,
3611 GSI_SAME_STMT);
3612 break;
3614 x = lang_hooks.decls.omp_clause_copy_ctor
3615 (c, unshare_expr (ivar), x);
3616 gimplify_and_add (x, &llist[0]);
3617 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3618 if (x)
3620 gimple_seq tseq = NULL;
3622 dtor = x;
3623 gimplify_stmt (&dtor, &tseq);
3624 gimple_seq_add_seq (&llist[1], tseq);
3626 break;
3629 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3630 gimplify_and_add (x, ilist);
3631 goto do_dtor;
3633 case OMP_CLAUSE__LOOPTEMP_:
3634 gcc_assert (is_parallel_ctx (ctx));
3635 x = build_outer_var_ref (var, ctx);
3636 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3637 gimplify_and_add (x, ilist);
3638 break;
3640 case OMP_CLAUSE_COPYIN:
3641 by_ref = use_pointer_for_field (var, NULL);
3642 x = build_receiver_ref (var, by_ref, ctx);
3643 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3644 append_to_statement_list (x, &copyin_seq);
3645 copyin_by_ref |= by_ref;
3646 break;
3648 case OMP_CLAUSE_REDUCTION:
3649 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3651 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3652 gimple tseq;
3653 x = build_outer_var_ref (var, ctx);
3655 if (is_reference (var)
3656 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3657 TREE_TYPE (x)))
3658 x = build_fold_addr_expr_loc (clause_loc, x);
3659 SET_DECL_VALUE_EXPR (placeholder, x);
3660 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3661 tree new_vard = new_var;
3662 if (is_reference (var))
3664 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3665 new_vard = TREE_OPERAND (new_var, 0);
3666 gcc_assert (DECL_P (new_vard));
3668 if (is_simd
3669 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3670 idx, lane, ivar, lvar))
3672 if (new_vard == new_var)
3674 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3675 SET_DECL_VALUE_EXPR (new_var, ivar);
3677 else
3679 SET_DECL_VALUE_EXPR (new_vard,
3680 build_fold_addr_expr (ivar));
3681 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3683 x = lang_hooks.decls.omp_clause_default_ctor
3684 (c, unshare_expr (ivar),
3685 build_outer_var_ref (var, ctx));
3686 if (x)
3687 gimplify_and_add (x, &llist[0]);
3688 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3690 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3691 lower_omp (&tseq, ctx);
3692 gimple_seq_add_seq (&llist[0], tseq);
3694 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3695 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3696 lower_omp (&tseq, ctx);
3697 gimple_seq_add_seq (&llist[1], tseq);
3698 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3699 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3700 if (new_vard == new_var)
3701 SET_DECL_VALUE_EXPR (new_var, lvar);
3702 else
3703 SET_DECL_VALUE_EXPR (new_vard,
3704 build_fold_addr_expr (lvar));
3705 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3706 if (x)
3708 tseq = NULL;
3709 dtor = x;
3710 gimplify_stmt (&dtor, &tseq);
3711 gimple_seq_add_seq (&llist[1], tseq);
3713 break;
3715 /* If this is a reference to constant size reduction var
3716 with placeholder, we haven't emitted the initializer
3717 for it because it is undesirable if SIMD arrays are used.
3718 But if they aren't used, we need to emit the deferred
3719 initialization now. */
3720 else if (is_reference (var) && is_simd)
3721 handle_simd_reference (clause_loc, new_vard, ilist);
3722 x = lang_hooks.decls.omp_clause_default_ctor
3723 (c, unshare_expr (new_var),
3724 build_outer_var_ref (var, ctx));
3725 if (x)
3726 gimplify_and_add (x, ilist);
3727 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3729 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3730 lower_omp (&tseq, ctx);
3731 gimple_seq_add_seq (ilist, tseq);
3733 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3734 if (is_simd)
3736 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3737 lower_omp (&tseq, ctx);
3738 gimple_seq_add_seq (dlist, tseq);
3739 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3741 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3742 goto do_dtor;
3744 else
3746 x = omp_reduction_init (c, TREE_TYPE (new_var));
3747 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3748 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3750 /* reduction(-:var) sums up the partial results, so it
3751 acts identically to reduction(+:var). */
3752 if (code == MINUS_EXPR)
3753 code = PLUS_EXPR;
3755 tree new_vard = new_var;
3756 if (is_simd && is_reference (var))
3758 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3759 new_vard = TREE_OPERAND (new_var, 0);
3760 gcc_assert (DECL_P (new_vard));
3762 if (is_simd
3763 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3764 idx, lane, ivar, lvar))
3766 tree ref = build_outer_var_ref (var, ctx);
3768 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3770 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3771 ref = build_outer_var_ref (var, ctx);
3772 gimplify_assign (ref, x, &llist[1]);
3774 if (new_vard != new_var)
3776 SET_DECL_VALUE_EXPR (new_vard,
3777 build_fold_addr_expr (lvar));
3778 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3781 else
3783 if (is_reference (var) && is_simd)
3784 handle_simd_reference (clause_loc, new_vard, ilist);
3785 gimplify_assign (new_var, x, ilist);
3786 if (is_simd)
3788 tree ref = build_outer_var_ref (var, ctx);
3790 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3791 ref = build_outer_var_ref (var, ctx);
3792 gimplify_assign (ref, x, dlist);
3796 break;
3798 default:
3799 gcc_unreachable ();
3804 if (lane)
3806 tree uid = create_tmp_var (ptr_type_node, "simduid");
3807 /* Don't want uninit warnings on simduid, it is always uninitialized,
3808 but we use it not for the value, but for the DECL_UID only. */
3809 TREE_NO_WARNING (uid) = 1;
3810 gimple g
3811 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3812 gimple_call_set_lhs (g, lane);
3813 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3814 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3815 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3816 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3817 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3818 gimple_omp_for_set_clauses (ctx->stmt, c);
3819 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3820 build_int_cst (unsigned_type_node, 0),
3821 NULL_TREE);
3822 gimple_seq_add_stmt (ilist, g);
3823 for (int i = 0; i < 2; i++)
3824 if (llist[i])
3826 tree vf = create_tmp_var (unsigned_type_node, NULL);
3827 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3828 gimple_call_set_lhs (g, vf);
3829 gimple_seq *seq = i == 0 ? ilist : dlist;
3830 gimple_seq_add_stmt (seq, g);
3831 tree t = build_int_cst (unsigned_type_node, 0);
3832 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3833 gimple_seq_add_stmt (seq, g);
3834 tree body = create_artificial_label (UNKNOWN_LOCATION);
3835 tree header = create_artificial_label (UNKNOWN_LOCATION);
3836 tree end = create_artificial_label (UNKNOWN_LOCATION);
3837 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3838 gimple_seq_add_stmt (seq, gimple_build_label (body));
3839 gimple_seq_add_seq (seq, llist[i]);
3840 t = build_int_cst (unsigned_type_node, 1);
3841 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3842 gimple_seq_add_stmt (seq, g);
3843 gimple_seq_add_stmt (seq, gimple_build_label (header));
3844 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3845 gimple_seq_add_stmt (seq, g);
3846 gimple_seq_add_stmt (seq, gimple_build_label (end));
3850 /* The copyin sequence is not to be executed by the main thread, since
3851 that would result in self-copies. Perhaps not visible to scalars,
3852 but it certainly is to C++ operator=. */
3853 if (copyin_seq)
3855 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3857 x = build2 (NE_EXPR, boolean_type_node, x,
3858 build_int_cst (TREE_TYPE (x), 0));
3859 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3860 gimplify_and_add (x, ilist);
3863 /* If any copyin variable is passed by reference, we must ensure the
3864 master thread doesn't modify it before it is copied over in all
3865 threads. Similarly for variables in both firstprivate and
3866 lastprivate clauses we need to ensure the lastprivate copying
3867 happens after firstprivate copying in all threads. And similarly
3868 for UDRs if initializer expression refers to omp_orig. */
3869 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3871 /* Don't add any barrier for #pragma omp simd or
3872 #pragma omp distribute. */
3873 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3874 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3875 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3878 /* If max_vf is non-zero, then we can use only a vectorization factor
3879 up to the max_vf we chose. So stick it into the safelen clause. */
3880 if (max_vf)
3882 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3883 OMP_CLAUSE_SAFELEN);
3884 if (c == NULL_TREE
3885 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
3886 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3887 max_vf) == 1))
3889 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3890 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3891 max_vf);
3892 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3893 gimple_omp_for_set_clauses (ctx->stmt, c);
3899 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3900 both parallel and workshare constructs. PREDICATE may be NULL if it's
3901 always true. */
3903 static void
3904 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3905 omp_context *ctx)
3907 tree x, c, label = NULL, orig_clauses = clauses;
3908 bool par_clauses = false;
3909 tree simduid = NULL, lastlane = NULL;
3911 /* Early exit if there are no lastprivate or linear clauses. */
3912 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3913 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3914 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3915 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3916 break;
3917 if (clauses == NULL)
3919 /* If this was a workshare clause, see if it had been combined
3920 with its parallel. In that case, look for the clauses on the
3921 parallel statement itself. */
3922 if (is_parallel_ctx (ctx))
3923 return;
3925 ctx = ctx->outer;
3926 if (ctx == NULL || !is_parallel_ctx (ctx))
3927 return;
3929 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3930 OMP_CLAUSE_LASTPRIVATE);
3931 if (clauses == NULL)
3932 return;
3933 par_clauses = true;
3936 if (predicate)
3938 gimple stmt;
3939 tree label_true, arm1, arm2;
3941 label = create_artificial_label (UNKNOWN_LOCATION);
3942 label_true = create_artificial_label (UNKNOWN_LOCATION);
3943 arm1 = TREE_OPERAND (predicate, 0);
3944 arm2 = TREE_OPERAND (predicate, 1);
3945 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3946 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3947 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3948 label_true, label);
3949 gimple_seq_add_stmt (stmt_list, stmt);
3950 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3953 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3954 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3956 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3957 if (simduid)
3958 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3961 for (c = clauses; c ;)
3963 tree var, new_var;
3964 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3966 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3967 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3968 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3970 var = OMP_CLAUSE_DECL (c);
3971 new_var = lookup_decl (var, ctx);
3973 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3975 tree val = DECL_VALUE_EXPR (new_var);
3976 if (TREE_CODE (val) == ARRAY_REF
3977 && VAR_P (TREE_OPERAND (val, 0))
3978 && lookup_attribute ("omp simd array",
3979 DECL_ATTRIBUTES (TREE_OPERAND (val,
3980 0))))
3982 if (lastlane == NULL)
3984 lastlane = create_tmp_var (unsigned_type_node, NULL);
3985 gimple g
3986 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
3987 2, simduid,
3988 TREE_OPERAND (val, 1));
3989 gimple_call_set_lhs (g, lastlane);
3990 gimple_seq_add_stmt (stmt_list, g);
3992 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
3993 TREE_OPERAND (val, 0), lastlane,
3994 NULL_TREE, NULL_TREE);
3998 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3999 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4001 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4002 gimple_seq_add_seq (stmt_list,
4003 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4004 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4006 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4007 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4009 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4010 gimple_seq_add_seq (stmt_list,
4011 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4012 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4015 x = build_outer_var_ref (var, ctx);
4016 if (is_reference (var))
4017 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4018 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4019 gimplify_and_add (x, stmt_list);
4021 c = OMP_CLAUSE_CHAIN (c);
4022 if (c == NULL && !par_clauses)
4024 /* If this was a workshare clause, see if it had been combined
4025 with its parallel. In that case, continue looking for the
4026 clauses also on the parallel statement itself. */
4027 if (is_parallel_ctx (ctx))
4028 break;
4030 ctx = ctx->outer;
4031 if (ctx == NULL || !is_parallel_ctx (ctx))
4032 break;
4034 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4035 OMP_CLAUSE_LASTPRIVATE);
4036 par_clauses = true;
4040 if (label)
4041 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4045 /* Generate code to implement the REDUCTION clauses. */
4047 static void
4048 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4050 gimple_seq sub_seq = NULL;
4051 gimple stmt;
4052 tree x, c;
4053 int count = 0;
4055 /* SIMD reductions are handled in lower_rec_input_clauses. */
4056 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4057 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4058 return;
4060 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4061 update in that case, otherwise use a lock. */
4062 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4063 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4065 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4067 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4068 count = -1;
4069 break;
4071 count++;
4074 if (count == 0)
4075 return;
4077 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4079 tree var, ref, new_var;
4080 enum tree_code code;
4081 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4083 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4084 continue;
4086 var = OMP_CLAUSE_DECL (c);
4087 new_var = lookup_decl (var, ctx);
4088 if (is_reference (var))
4089 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4090 ref = build_outer_var_ref (var, ctx);
4091 code = OMP_CLAUSE_REDUCTION_CODE (c);
4093 /* reduction(-:var) sums up the partial results, so it acts
4094 identically to reduction(+:var). */
4095 if (code == MINUS_EXPR)
4096 code = PLUS_EXPR;
4098 if (count == 1)
4100 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4102 addr = save_expr (addr);
4103 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4104 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4105 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4106 gimplify_and_add (x, stmt_seqp);
4107 return;
4110 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4112 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4114 if (is_reference (var)
4115 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4116 TREE_TYPE (ref)))
4117 ref = build_fold_addr_expr_loc (clause_loc, ref);
4118 SET_DECL_VALUE_EXPR (placeholder, ref);
4119 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4120 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4121 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4122 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4123 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4125 else
4127 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4128 ref = build_outer_var_ref (var, ctx);
4129 gimplify_assign (ref, x, &sub_seq);
4133 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4135 gimple_seq_add_stmt (stmt_seqp, stmt);
4137 gimple_seq_add_seq (stmt_seqp, sub_seq);
4139 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4141 gimple_seq_add_stmt (stmt_seqp, stmt);
4145 /* Generate code to implement the COPYPRIVATE clauses. */
4147 static void
4148 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4149 omp_context *ctx)
4151 tree c;
4153 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4155 tree var, new_var, ref, x;
4156 bool by_ref;
4157 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4159 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4160 continue;
4162 var = OMP_CLAUSE_DECL (c);
4163 by_ref = use_pointer_for_field (var, NULL);
4165 ref = build_sender_ref (var, ctx);
4166 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4167 if (by_ref)
4169 x = build_fold_addr_expr_loc (clause_loc, new_var);
4170 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4172 gimplify_assign (ref, x, slist);
4174 ref = build_receiver_ref (var, false, ctx);
4175 if (by_ref)
4177 ref = fold_convert_loc (clause_loc,
4178 build_pointer_type (TREE_TYPE (new_var)),
4179 ref);
4180 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4182 if (is_reference (var))
4184 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4185 ref = build_simple_mem_ref_loc (clause_loc, ref);
4186 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4188 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4189 gimplify_and_add (x, rlist);
4194 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4195 and REDUCTION from the sender (aka parent) side. */
4197 static void
4198 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4199 omp_context *ctx)
4201 tree c;
4203 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4205 tree val, ref, x, var;
4206 bool by_ref, do_in = false, do_out = false;
4207 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4209 switch (OMP_CLAUSE_CODE (c))
4211 case OMP_CLAUSE_PRIVATE:
4212 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4213 break;
4214 continue;
4215 case OMP_CLAUSE_FIRSTPRIVATE:
4216 case OMP_CLAUSE_COPYIN:
4217 case OMP_CLAUSE_LASTPRIVATE:
4218 case OMP_CLAUSE_REDUCTION:
4219 case OMP_CLAUSE__LOOPTEMP_:
4220 break;
4221 default:
4222 continue;
4225 val = OMP_CLAUSE_DECL (c);
4226 var = lookup_decl_in_outer_ctx (val, ctx);
4228 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4229 && is_global_var (var))
4230 continue;
4231 if (is_variable_sized (val))
4232 continue;
4233 by_ref = use_pointer_for_field (val, NULL);
4235 switch (OMP_CLAUSE_CODE (c))
4237 case OMP_CLAUSE_PRIVATE:
4238 case OMP_CLAUSE_FIRSTPRIVATE:
4239 case OMP_CLAUSE_COPYIN:
4240 case OMP_CLAUSE__LOOPTEMP_:
4241 do_in = true;
4242 break;
4244 case OMP_CLAUSE_LASTPRIVATE:
4245 if (by_ref || is_reference (val))
4247 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4248 continue;
4249 do_in = true;
4251 else
4253 do_out = true;
4254 if (lang_hooks.decls.omp_private_outer_ref (val))
4255 do_in = true;
4257 break;
4259 case OMP_CLAUSE_REDUCTION:
4260 do_in = true;
4261 do_out = !(by_ref || is_reference (val));
4262 break;
4264 default:
4265 gcc_unreachable ();
4268 if (do_in)
4270 ref = build_sender_ref (val, ctx);
4271 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4272 gimplify_assign (ref, x, ilist);
4273 if (is_task_ctx (ctx))
4274 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4277 if (do_out)
4279 ref = build_sender_ref (val, ctx);
4280 gimplify_assign (var, ref, olist);
4285 /* Generate code to implement SHARED from the sender (aka parent)
4286 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4287 list things that got automatically shared. */
4289 static void
4290 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4292 tree var, ovar, nvar, f, x, record_type;
4294 if (ctx->record_type == NULL)
4295 return;
4297 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4298 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4300 ovar = DECL_ABSTRACT_ORIGIN (f);
4301 nvar = maybe_lookup_decl (ovar, ctx);
4302 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4303 continue;
4305 /* If CTX is a nested parallel directive. Find the immediately
4306 enclosing parallel or workshare construct that contains a
4307 mapping for OVAR. */
4308 var = lookup_decl_in_outer_ctx (ovar, ctx);
4310 if (use_pointer_for_field (ovar, ctx))
4312 x = build_sender_ref (ovar, ctx);
4313 var = build_fold_addr_expr (var);
4314 gimplify_assign (x, var, ilist);
4316 else
4318 x = build_sender_ref (ovar, ctx);
4319 gimplify_assign (x, var, ilist);
4321 if (!TREE_READONLY (var)
4322 /* We don't need to receive a new reference to a result
4323 or parm decl. In fact we may not store to it as we will
4324 invalidate any pending RSO and generate wrong gimple
4325 during inlining. */
4326 && !((TREE_CODE (var) == RESULT_DECL
4327 || TREE_CODE (var) == PARM_DECL)
4328 && DECL_BY_REFERENCE (var)))
4330 x = build_sender_ref (ovar, ctx);
4331 gimplify_assign (var, x, olist);
4338 /* A convenience function to build an empty GIMPLE_COND with just the
4339 condition. */
4341 static gimple
4342 gimple_build_cond_empty (tree cond)
4344 enum tree_code pred_code;
4345 tree lhs, rhs;
4347 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4348 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4352 /* Build the function calls to GOMP_parallel_start etc to actually
4353 generate the parallel operation. REGION is the parallel region
4354 being expanded. BB is the block where to insert the code. WS_ARGS
4355 will be set if this is a call to a combined parallel+workshare
4356 construct, it contains the list of additional arguments needed by
4357 the workshare construct. */
4359 static void
4360 expand_parallel_call (struct omp_region *region, basic_block bb,
4361 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4363 tree t, t1, t2, val, cond, c, clauses, flags;
4364 gimple_stmt_iterator gsi;
4365 gimple stmt;
4366 enum built_in_function start_ix;
4367 int start_ix2;
4368 location_t clause_loc;
4369 vec<tree, va_gc> *args;
4371 clauses = gimple_omp_parallel_clauses (entry_stmt);
4373 /* Determine what flavor of GOMP_parallel we will be
4374 emitting. */
4375 start_ix = BUILT_IN_GOMP_PARALLEL;
4376 if (is_combined_parallel (region))
4378 switch (region->inner->type)
4380 case GIMPLE_OMP_FOR:
4381 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4382 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4383 + (region->inner->sched_kind
4384 == OMP_CLAUSE_SCHEDULE_RUNTIME
4385 ? 3 : region->inner->sched_kind));
4386 start_ix = (enum built_in_function)start_ix2;
4387 break;
4388 case GIMPLE_OMP_SECTIONS:
4389 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4390 break;
4391 default:
4392 gcc_unreachable ();
4396 /* By default, the value of NUM_THREADS is zero (selected at run time)
4397 and there is no conditional. */
4398 cond = NULL_TREE;
4399 val = build_int_cst (unsigned_type_node, 0);
4400 flags = build_int_cst (unsigned_type_node, 0);
4402 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4403 if (c)
4404 cond = OMP_CLAUSE_IF_EXPR (c);
4406 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4407 if (c)
4409 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4410 clause_loc = OMP_CLAUSE_LOCATION (c);
4412 else
4413 clause_loc = gimple_location (entry_stmt);
4415 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4416 if (c)
4417 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4419 /* Ensure 'val' is of the correct type. */
4420 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4422 /* If we found the clause 'if (cond)', build either
4423 (cond != 0) or (cond ? val : 1u). */
4424 if (cond)
4426 cond = gimple_boolify (cond);
4428 if (integer_zerop (val))
4429 val = fold_build2_loc (clause_loc,
4430 EQ_EXPR, unsigned_type_node, cond,
4431 build_int_cst (TREE_TYPE (cond), 0));
4432 else
4434 basic_block cond_bb, then_bb, else_bb;
4435 edge e, e_then, e_else;
4436 tree tmp_then, tmp_else, tmp_join, tmp_var;
4438 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4439 if (gimple_in_ssa_p (cfun))
4441 tmp_then = make_ssa_name (tmp_var, NULL);
4442 tmp_else = make_ssa_name (tmp_var, NULL);
4443 tmp_join = make_ssa_name (tmp_var, NULL);
4445 else
4447 tmp_then = tmp_var;
4448 tmp_else = tmp_var;
4449 tmp_join = tmp_var;
4452 e = split_block (bb, NULL);
4453 cond_bb = e->src;
4454 bb = e->dest;
4455 remove_edge (e);
4457 then_bb = create_empty_bb (cond_bb);
4458 else_bb = create_empty_bb (then_bb);
4459 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4460 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4462 stmt = gimple_build_cond_empty (cond);
4463 gsi = gsi_start_bb (cond_bb);
4464 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4466 gsi = gsi_start_bb (then_bb);
4467 stmt = gimple_build_assign (tmp_then, val);
4468 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4470 gsi = gsi_start_bb (else_bb);
4471 stmt = gimple_build_assign
4472 (tmp_else, build_int_cst (unsigned_type_node, 1));
4473 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4475 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4476 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4477 add_bb_to_loop (then_bb, cond_bb->loop_father);
4478 add_bb_to_loop (else_bb, cond_bb->loop_father);
4479 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4480 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4482 if (gimple_in_ssa_p (cfun))
4484 gimple phi = create_phi_node (tmp_join, bb);
4485 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4486 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4489 val = tmp_join;
4492 gsi = gsi_start_bb (bb);
4493 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4494 false, GSI_CONTINUE_LINKING);
4497 gsi = gsi_last_bb (bb);
4498 t = gimple_omp_parallel_data_arg (entry_stmt);
4499 if (t == NULL)
4500 t1 = null_pointer_node;
4501 else
4502 t1 = build_fold_addr_expr (t);
4503 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4505 vec_alloc (args, 4 + vec_safe_length (ws_args));
4506 args->quick_push (t2);
4507 args->quick_push (t1);
4508 args->quick_push (val);
4509 if (ws_args)
4510 args->splice (*ws_args);
4511 args->quick_push (flags);
4513 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4514 builtin_decl_explicit (start_ix), args);
4516 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4517 false, GSI_CONTINUE_LINKING);
4520 /* Insert a function call whose name is FUNC_NAME with the information from
4521 ENTRY_STMT into the basic_block BB. */
4523 static void
4524 expand_cilk_for_call (basic_block bb, gimple entry_stmt,
4525 vec <tree, va_gc> *ws_args)
4527 tree t, t1, t2;
4528 gimple_stmt_iterator gsi;
4529 vec <tree, va_gc> *args;
4531 gcc_assert (vec_safe_length (ws_args) == 2);
4532 tree func_name = (*ws_args)[0];
4533 tree grain = (*ws_args)[1];
4535 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
4536 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
4537 gcc_assert (count != NULL_TREE);
4538 count = OMP_CLAUSE_OPERAND (count, 0);
4540 gsi = gsi_last_bb (bb);
4541 t = gimple_omp_parallel_data_arg (entry_stmt);
4542 if (t == NULL)
4543 t1 = null_pointer_node;
4544 else
4545 t1 = build_fold_addr_expr (t);
4546 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4548 vec_alloc (args, 4);
4549 args->quick_push (t2);
4550 args->quick_push (t1);
4551 args->quick_push (count);
4552 args->quick_push (grain);
4553 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
4555 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
4556 GSI_CONTINUE_LINKING);
4559 /* Build the function call to GOMP_task to actually
4560 generate the task operation. BB is the block where to insert the code. */
4562 static void
4563 expand_task_call (basic_block bb, gimple entry_stmt)
4565 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4566 gimple_stmt_iterator gsi;
4567 location_t loc = gimple_location (entry_stmt);
4569 clauses = gimple_omp_task_clauses (entry_stmt);
4571 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4572 if (c)
4573 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4574 else
4575 cond = boolean_true_node;
4577 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4578 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4579 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4580 flags = build_int_cst (unsigned_type_node,
4581 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4583 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4584 if (c)
4586 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4587 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4588 build_int_cst (unsigned_type_node, 2),
4589 build_int_cst (unsigned_type_node, 0));
4590 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4592 if (depend)
4593 depend = OMP_CLAUSE_DECL (depend);
4594 else
4595 depend = build_int_cst (ptr_type_node, 0);
4597 gsi = gsi_last_bb (bb);
4598 t = gimple_omp_task_data_arg (entry_stmt);
4599 if (t == NULL)
4600 t2 = null_pointer_node;
4601 else
4602 t2 = build_fold_addr_expr_loc (loc, t);
4603 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4604 t = gimple_omp_task_copy_fn (entry_stmt);
4605 if (t == NULL)
4606 t3 = null_pointer_node;
4607 else
4608 t3 = build_fold_addr_expr_loc (loc, t);
4610 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4611 8, t1, t2, t3,
4612 gimple_omp_task_arg_size (entry_stmt),
4613 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4614 depend);
4616 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4617 false, GSI_CONTINUE_LINKING);
4621 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4622 catch handler and return it. This prevents programs from violating the
4623 structured block semantics with throws. */
4625 static gimple_seq
4626 maybe_catch_exception (gimple_seq body)
4628 gimple g;
4629 tree decl;
4631 if (!flag_exceptions)
4632 return body;
4634 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4635 decl = lang_hooks.eh_protect_cleanup_actions ();
4636 else
4637 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4639 g = gimple_build_eh_must_not_throw (decl);
4640 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4641 GIMPLE_TRY_CATCH);
4643 return gimple_seq_alloc_with_stmt (g);
4646 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4648 static tree
4649 vec2chain (vec<tree, va_gc> *v)
4651 tree chain = NULL_TREE, t;
4652 unsigned ix;
4654 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4656 DECL_CHAIN (t) = chain;
4657 chain = t;
4660 return chain;
4664 /* Remove barriers in REGION->EXIT's block. Note that this is only
4665 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4666 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4667 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4668 removed. */
4670 static void
4671 remove_exit_barrier (struct omp_region *region)
4673 gimple_stmt_iterator gsi;
4674 basic_block exit_bb;
4675 edge_iterator ei;
4676 edge e;
4677 gimple stmt;
4678 int any_addressable_vars = -1;
4680 exit_bb = region->exit;
4682 /* If the parallel region doesn't return, we don't have REGION->EXIT
4683 block at all. */
4684 if (! exit_bb)
4685 return;
4687 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4688 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4689 statements that can appear in between are extremely limited -- no
4690 memory operations at all. Here, we allow nothing at all, so the
4691 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4692 gsi = gsi_last_bb (exit_bb);
4693 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4694 gsi_prev (&gsi);
4695 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4696 return;
4698 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4700 gsi = gsi_last_bb (e->src);
4701 if (gsi_end_p (gsi))
4702 continue;
4703 stmt = gsi_stmt (gsi);
4704 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4705 && !gimple_omp_return_nowait_p (stmt))
4707 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4708 in many cases. If there could be tasks queued, the barrier
4709 might be needed to let the tasks run before some local
4710 variable of the parallel that the task uses as shared
4711 runs out of scope. The task can be spawned either
4712 from within current function (this would be easy to check)
4713 or from some function it calls and gets passed an address
4714 of such a variable. */
4715 if (any_addressable_vars < 0)
4717 gimple parallel_stmt = last_stmt (region->entry);
4718 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4719 tree local_decls, block, decl;
4720 unsigned ix;
4722 any_addressable_vars = 0;
4723 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4724 if (TREE_ADDRESSABLE (decl))
4726 any_addressable_vars = 1;
4727 break;
4729 for (block = gimple_block (stmt);
4730 !any_addressable_vars
4731 && block
4732 && TREE_CODE (block) == BLOCK;
4733 block = BLOCK_SUPERCONTEXT (block))
4735 for (local_decls = BLOCK_VARS (block);
4736 local_decls;
4737 local_decls = DECL_CHAIN (local_decls))
4738 if (TREE_ADDRESSABLE (local_decls))
4740 any_addressable_vars = 1;
4741 break;
4743 if (block == gimple_block (parallel_stmt))
4744 break;
4747 if (!any_addressable_vars)
4748 gimple_omp_return_set_nowait (stmt);
4753 static void
4754 remove_exit_barriers (struct omp_region *region)
4756 if (region->type == GIMPLE_OMP_PARALLEL)
4757 remove_exit_barrier (region);
4759 if (region->inner)
4761 region = region->inner;
4762 remove_exit_barriers (region);
4763 while (region->next)
4765 region = region->next;
4766 remove_exit_barriers (region);
4771 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4772 calls. These can't be declared as const functions, but
4773 within one parallel body they are constant, so they can be
4774 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4775 which are declared const. Similarly for task body, except
4776 that in untied task omp_get_thread_num () can change at any task
4777 scheduling point. */
4779 static void
4780 optimize_omp_library_calls (gimple entry_stmt)
4782 basic_block bb;
4783 gimple_stmt_iterator gsi;
4784 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4785 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4786 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4787 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4788 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4789 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4790 OMP_CLAUSE_UNTIED) != NULL);
4792 FOR_EACH_BB_FN (bb, cfun)
4793 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4795 gimple call = gsi_stmt (gsi);
4796 tree decl;
4798 if (is_gimple_call (call)
4799 && (decl = gimple_call_fndecl (call))
4800 && DECL_EXTERNAL (decl)
4801 && TREE_PUBLIC (decl)
4802 && DECL_INITIAL (decl) == NULL)
4804 tree built_in;
4806 if (DECL_NAME (decl) == thr_num_id)
4808 /* In #pragma omp task untied omp_get_thread_num () can change
4809 during the execution of the task region. */
4810 if (untied_task)
4811 continue;
4812 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4814 else if (DECL_NAME (decl) == num_thr_id)
4815 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4816 else
4817 continue;
4819 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4820 || gimple_call_num_args (call) != 0)
4821 continue;
4823 if (flag_exceptions && !TREE_NOTHROW (decl))
4824 continue;
4826 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4827 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4828 TREE_TYPE (TREE_TYPE (built_in))))
4829 continue;
4831 gimple_call_set_fndecl (call, built_in);
4836 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4837 regimplified. */
4839 static tree
4840 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4842 tree t = *tp;
4844 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4845 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4846 return t;
4848 if (TREE_CODE (t) == ADDR_EXPR)
4849 recompute_tree_invariant_for_addr_expr (t);
4851 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4852 return NULL_TREE;
4855 /* Prepend TO = FROM assignment before *GSI_P. */
4857 static void
4858 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4860 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4861 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4862 true, GSI_SAME_STMT);
4863 gimple stmt = gimple_build_assign (to, from);
4864 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4865 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4866 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4868 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4869 gimple_regimplify_operands (stmt, &gsi);
4873 /* Expand the OpenMP parallel or task directive starting at REGION. */
4875 static void
4876 expand_omp_taskreg (struct omp_region *region)
4878 basic_block entry_bb, exit_bb, new_bb;
4879 struct function *child_cfun;
4880 tree child_fn, block, t;
4881 gimple_stmt_iterator gsi;
4882 gimple entry_stmt, stmt;
4883 edge e;
4884 vec<tree, va_gc> *ws_args;
4886 entry_stmt = last_stmt (region->entry);
4887 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4888 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4890 entry_bb = region->entry;
4891 exit_bb = region->exit;
4893 bool is_cilk_for
4894 = (flag_cilkplus
4895 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
4896 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
4897 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
4899 if (is_cilk_for)
4900 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
4901 and the inner statement contains the name of the built-in function
4902 and grain. */
4903 ws_args = region->inner->ws_args;
4904 else if (is_combined_parallel (region))
4905 ws_args = region->ws_args;
4906 else
4907 ws_args = NULL;
4909 if (child_cfun->cfg)
4911 /* Due to inlining, it may happen that we have already outlined
4912 the region, in which case all we need to do is make the
4913 sub-graph unreachable and emit the parallel call. */
4914 edge entry_succ_e, exit_succ_e;
4916 entry_succ_e = single_succ_edge (entry_bb);
4918 gsi = gsi_last_bb (entry_bb);
4919 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4920 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4921 gsi_remove (&gsi, true);
4923 new_bb = entry_bb;
4924 if (exit_bb)
4926 exit_succ_e = single_succ_edge (exit_bb);
4927 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4929 remove_edge_and_dominated_blocks (entry_succ_e);
4931 else
4933 unsigned srcidx, dstidx, num;
4935 /* If the parallel region needs data sent from the parent
4936 function, then the very first statement (except possible
4937 tree profile counter updates) of the parallel body
4938 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4939 &.OMP_DATA_O is passed as an argument to the child function,
4940 we need to replace it with the argument as seen by the child
4941 function.
4943 In most cases, this will end up being the identity assignment
4944 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4945 a function call that has been inlined, the original PARM_DECL
4946 .OMP_DATA_I may have been converted into a different local
4947 variable. In which case, we need to keep the assignment. */
4948 if (gimple_omp_taskreg_data_arg (entry_stmt))
4950 basic_block entry_succ_bb = single_succ (entry_bb);
4951 tree arg, narg;
4952 gimple parcopy_stmt = NULL;
4954 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4956 gimple stmt;
4958 gcc_assert (!gsi_end_p (gsi));
4959 stmt = gsi_stmt (gsi);
4960 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4961 continue;
4963 if (gimple_num_ops (stmt) == 2)
4965 tree arg = gimple_assign_rhs1 (stmt);
4967 /* We're ignore the subcode because we're
4968 effectively doing a STRIP_NOPS. */
4970 if (TREE_CODE (arg) == ADDR_EXPR
4971 && TREE_OPERAND (arg, 0)
4972 == gimple_omp_taskreg_data_arg (entry_stmt))
4974 parcopy_stmt = stmt;
4975 break;
4980 gcc_assert (parcopy_stmt != NULL);
4981 arg = DECL_ARGUMENTS (child_fn);
4983 if (!gimple_in_ssa_p (cfun))
4985 if (gimple_assign_lhs (parcopy_stmt) == arg)
4986 gsi_remove (&gsi, true);
4987 else
4989 /* ?? Is setting the subcode really necessary ?? */
4990 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
4991 gimple_assign_set_rhs1 (parcopy_stmt, arg);
4994 else
4996 /* If we are in ssa form, we must load the value from the default
4997 definition of the argument. That should not be defined now,
4998 since the argument is not used uninitialized. */
4999 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5000 narg = make_ssa_name (arg, gimple_build_nop ());
5001 set_ssa_default_def (cfun, arg, narg);
5002 /* ?? Is setting the subcode really necessary ?? */
5003 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5004 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5005 update_stmt (parcopy_stmt);
5009 /* Declare local variables needed in CHILD_CFUN. */
5010 block = DECL_INITIAL (child_fn);
5011 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5012 /* The gimplifier could record temporaries in parallel/task block
5013 rather than in containing function's local_decls chain,
5014 which would mean cgraph missed finalizing them. Do it now. */
5015 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5016 if (TREE_CODE (t) == VAR_DECL
5017 && TREE_STATIC (t)
5018 && !DECL_EXTERNAL (t))
5019 varpool_node::finalize_decl (t);
5020 DECL_SAVED_TREE (child_fn) = NULL;
5021 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5022 gimple_set_body (child_fn, NULL);
5023 TREE_USED (block) = 1;
5025 /* Reset DECL_CONTEXT on function arguments. */
5026 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5027 DECL_CONTEXT (t) = child_fn;
5029 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5030 so that it can be moved to the child function. */
5031 gsi = gsi_last_bb (entry_bb);
5032 stmt = gsi_stmt (gsi);
5033 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5034 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5035 gsi_remove (&gsi, true);
5036 e = split_block (entry_bb, stmt);
5037 entry_bb = e->dest;
5038 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5040 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5041 if (exit_bb)
5043 gsi = gsi_last_bb (exit_bb);
5044 gcc_assert (!gsi_end_p (gsi)
5045 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5046 stmt = gimple_build_return (NULL);
5047 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5048 gsi_remove (&gsi, true);
5051 /* Move the parallel region into CHILD_CFUN. */
5053 if (gimple_in_ssa_p (cfun))
5055 init_tree_ssa (child_cfun);
5056 init_ssa_operands (child_cfun);
5057 child_cfun->gimple_df->in_ssa_p = true;
5058 block = NULL_TREE;
5060 else
5061 block = gimple_block (entry_stmt);
5063 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5064 if (exit_bb)
5065 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5066 /* When the OMP expansion process cannot guarantee an up-to-date
5067 loop tree arrange for the child function to fixup loops. */
5068 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5069 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5071 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5072 num = vec_safe_length (child_cfun->local_decls);
5073 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5075 t = (*child_cfun->local_decls)[srcidx];
5076 if (DECL_CONTEXT (t) == cfun->decl)
5077 continue;
5078 if (srcidx != dstidx)
5079 (*child_cfun->local_decls)[dstidx] = t;
5080 dstidx++;
5082 if (dstidx != num)
5083 vec_safe_truncate (child_cfun->local_decls, dstidx);
5085 /* Inform the callgraph about the new function. */
5086 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5087 cgraph_node::add_new_function (child_fn, true);
5089 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5090 fixed in a following pass. */
5091 push_cfun (child_cfun);
5092 if (optimize)
5093 optimize_omp_library_calls (entry_stmt);
5094 cgraph_edge::rebuild_edges ();
5096 /* Some EH regions might become dead, see PR34608. If
5097 pass_cleanup_cfg isn't the first pass to happen with the
5098 new child, these dead EH edges might cause problems.
5099 Clean them up now. */
5100 if (flag_exceptions)
5102 basic_block bb;
5103 bool changed = false;
5105 FOR_EACH_BB_FN (bb, cfun)
5106 changed |= gimple_purge_dead_eh_edges (bb);
5107 if (changed)
5108 cleanup_tree_cfg ();
5110 if (gimple_in_ssa_p (cfun))
5111 update_ssa (TODO_update_ssa);
5112 pop_cfun ();
5115 /* Emit a library call to launch the children threads. */
5116 if (is_cilk_for)
5117 expand_cilk_for_call (new_bb, entry_stmt, ws_args);
5118 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5119 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
5120 else
5121 expand_task_call (new_bb, entry_stmt);
5122 if (gimple_in_ssa_p (cfun))
5123 update_ssa (TODO_update_ssa_only_virtuals);
5127 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5128 of the combined collapse > 1 loop constructs, generate code like:
5129 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5130 if (cond3 is <)
5131 adj = STEP3 - 1;
5132 else
5133 adj = STEP3 + 1;
5134 count3 = (adj + N32 - N31) / STEP3;
5135 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5136 if (cond2 is <)
5137 adj = STEP2 - 1;
5138 else
5139 adj = STEP2 + 1;
5140 count2 = (adj + N22 - N21) / STEP2;
5141 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5142 if (cond1 is <)
5143 adj = STEP1 - 1;
5144 else
5145 adj = STEP1 + 1;
5146 count1 = (adj + N12 - N11) / STEP1;
5147 count = count1 * count2 * count3;
5148 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5149 count = 0;
5150 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5151 of the combined loop constructs, just initialize COUNTS array
5152 from the _looptemp_ clauses. */
5154 /* NOTE: It *could* be better to moosh all of the BBs together,
5155 creating one larger BB with all the computation and the unexpected
5156 jump at the end. I.e.
5158 bool zero3, zero2, zero1, zero;
5160 zero3 = N32 c3 N31;
5161 count3 = (N32 - N31) /[cl] STEP3;
5162 zero2 = N22 c2 N21;
5163 count2 = (N22 - N21) /[cl] STEP2;
5164 zero1 = N12 c1 N11;
5165 count1 = (N12 - N11) /[cl] STEP1;
5166 zero = zero3 || zero2 || zero1;
5167 count = count1 * count2 * count3;
5168 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5170 After all, we expect the zero=false, and thus we expect to have to
5171 evaluate all of the comparison expressions, so short-circuiting
5172 oughtn't be a win. Since the condition isn't protecting a
5173 denominator, we're not concerned about divide-by-zero, so we can
5174 fully evaluate count even if a numerator turned out to be wrong.
5176 It seems like putting this all together would create much better
5177 scheduling opportunities, and less pressure on the chip's branch
5178 predictor. */
5180 static void
5181 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5182 basic_block &entry_bb, tree *counts,
5183 basic_block &zero_iter_bb, int &first_zero_iter,
5184 basic_block &l2_dom_bb)
5186 tree t, type = TREE_TYPE (fd->loop.v);
5187 gimple stmt;
5188 edge e, ne;
5189 int i;
5191 /* Collapsed loops need work for expansion into SSA form. */
5192 gcc_assert (!gimple_in_ssa_p (cfun));
5194 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5195 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5197 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5198 isn't supposed to be handled, as the inner loop doesn't
5199 use it. */
5200 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5201 OMP_CLAUSE__LOOPTEMP_);
5202 gcc_assert (innerc);
5203 for (i = 0; i < fd->collapse; i++)
5205 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5206 OMP_CLAUSE__LOOPTEMP_);
5207 gcc_assert (innerc);
5208 if (i)
5209 counts[i] = OMP_CLAUSE_DECL (innerc);
5210 else
5211 counts[0] = NULL_TREE;
5213 return;
5216 for (i = 0; i < fd->collapse; i++)
5218 tree itype = TREE_TYPE (fd->loops[i].v);
5220 if (SSA_VAR_P (fd->loop.n2)
5221 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5222 fold_convert (itype, fd->loops[i].n1),
5223 fold_convert (itype, fd->loops[i].n2)))
5224 == NULL_TREE || !integer_onep (t)))
5226 tree n1, n2;
5227 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5228 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5229 true, GSI_SAME_STMT);
5230 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5231 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5232 true, GSI_SAME_STMT);
5233 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5234 NULL_TREE, NULL_TREE);
5235 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5236 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5237 expand_omp_regimplify_p, NULL, NULL)
5238 || walk_tree (gimple_cond_rhs_ptr (stmt),
5239 expand_omp_regimplify_p, NULL, NULL))
5241 *gsi = gsi_for_stmt (stmt);
5242 gimple_regimplify_operands (stmt, gsi);
5244 e = split_block (entry_bb, stmt);
5245 if (zero_iter_bb == NULL)
5247 first_zero_iter = i;
5248 zero_iter_bb = create_empty_bb (entry_bb);
5249 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5250 *gsi = gsi_after_labels (zero_iter_bb);
5251 stmt = gimple_build_assign (fd->loop.n2,
5252 build_zero_cst (type));
5253 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5254 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5255 entry_bb);
5257 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5258 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5259 e->flags = EDGE_TRUE_VALUE;
5260 e->probability = REG_BR_PROB_BASE - ne->probability;
5261 if (l2_dom_bb == NULL)
5262 l2_dom_bb = entry_bb;
5263 entry_bb = e->dest;
5264 *gsi = gsi_last_bb (entry_bb);
5267 if (POINTER_TYPE_P (itype))
5268 itype = signed_type_for (itype);
5269 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5270 ? -1 : 1));
5271 t = fold_build2 (PLUS_EXPR, itype,
5272 fold_convert (itype, fd->loops[i].step), t);
5273 t = fold_build2 (PLUS_EXPR, itype, t,
5274 fold_convert (itype, fd->loops[i].n2));
5275 t = fold_build2 (MINUS_EXPR, itype, t,
5276 fold_convert (itype, fd->loops[i].n1));
5277 /* ?? We could probably use CEIL_DIV_EXPR instead of
5278 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5279 generate the same code in the end because generically we
5280 don't know that the values involved must be negative for
5281 GT?? */
5282 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5283 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5284 fold_build1 (NEGATE_EXPR, itype, t),
5285 fold_build1 (NEGATE_EXPR, itype,
5286 fold_convert (itype,
5287 fd->loops[i].step)));
5288 else
5289 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5290 fold_convert (itype, fd->loops[i].step));
5291 t = fold_convert (type, t);
5292 if (TREE_CODE (t) == INTEGER_CST)
5293 counts[i] = t;
5294 else
5296 counts[i] = create_tmp_reg (type, ".count");
5297 expand_omp_build_assign (gsi, counts[i], t);
5299 if (SSA_VAR_P (fd->loop.n2))
5301 if (i == 0)
5302 t = counts[0];
5303 else
5304 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5305 expand_omp_build_assign (gsi, fd->loop.n2, t);
5311 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5312 T = V;
5313 V3 = N31 + (T % count3) * STEP3;
5314 T = T / count3;
5315 V2 = N21 + (T % count2) * STEP2;
5316 T = T / count2;
5317 V1 = N11 + T * STEP1;
5318 if this loop doesn't have an inner loop construct combined with it.
5319 If it does have an inner loop construct combined with it and the
5320 iteration count isn't known constant, store values from counts array
5321 into its _looptemp_ temporaries instead. */
5323 static void
5324 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5325 tree *counts, gimple inner_stmt, tree startvar)
5327 int i;
5328 if (gimple_omp_for_combined_p (fd->for_stmt))
5330 /* If fd->loop.n2 is constant, then no propagation of the counts
5331 is needed, they are constant. */
5332 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5333 return;
5335 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5336 ? gimple_omp_parallel_clauses (inner_stmt)
5337 : gimple_omp_for_clauses (inner_stmt);
5338 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5339 isn't supposed to be handled, as the inner loop doesn't
5340 use it. */
5341 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5342 gcc_assert (innerc);
5343 for (i = 0; i < fd->collapse; i++)
5345 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5346 OMP_CLAUSE__LOOPTEMP_);
5347 gcc_assert (innerc);
5348 if (i)
5350 tree tem = OMP_CLAUSE_DECL (innerc);
5351 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5352 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5353 false, GSI_CONTINUE_LINKING);
5354 gimple stmt = gimple_build_assign (tem, t);
5355 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5358 return;
5361 tree type = TREE_TYPE (fd->loop.v);
5362 tree tem = create_tmp_reg (type, ".tem");
5363 gimple stmt = gimple_build_assign (tem, startvar);
5364 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5366 for (i = fd->collapse - 1; i >= 0; i--)
5368 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5369 itype = vtype;
5370 if (POINTER_TYPE_P (vtype))
5371 itype = signed_type_for (vtype);
5372 if (i != 0)
5373 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5374 else
5375 t = tem;
5376 t = fold_convert (itype, t);
5377 t = fold_build2 (MULT_EXPR, itype, t,
5378 fold_convert (itype, fd->loops[i].step));
5379 if (POINTER_TYPE_P (vtype))
5380 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5381 else
5382 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5383 t = force_gimple_operand_gsi (gsi, t,
5384 DECL_P (fd->loops[i].v)
5385 && TREE_ADDRESSABLE (fd->loops[i].v),
5386 NULL_TREE, false,
5387 GSI_CONTINUE_LINKING);
5388 stmt = gimple_build_assign (fd->loops[i].v, t);
5389 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5390 if (i != 0)
5392 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5393 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5394 false, GSI_CONTINUE_LINKING);
5395 stmt = gimple_build_assign (tem, t);
5396 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5402 /* Helper function for expand_omp_for_*. Generate code like:
5403 L10:
5404 V3 += STEP3;
5405 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5406 L11:
5407 V3 = N31;
5408 V2 += STEP2;
5409 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5410 L12:
5411 V2 = N21;
5412 V1 += STEP1;
5413 goto BODY_BB; */
5415 static basic_block
5416 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5417 basic_block body_bb)
5419 basic_block last_bb, bb, collapse_bb = NULL;
5420 int i;
5421 gimple_stmt_iterator gsi;
5422 edge e;
5423 tree t;
5424 gimple stmt;
5426 last_bb = cont_bb;
5427 for (i = fd->collapse - 1; i >= 0; i--)
5429 tree vtype = TREE_TYPE (fd->loops[i].v);
5431 bb = create_empty_bb (last_bb);
5432 add_bb_to_loop (bb, last_bb->loop_father);
5433 gsi = gsi_start_bb (bb);
5435 if (i < fd->collapse - 1)
5437 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5438 e->probability = REG_BR_PROB_BASE / 8;
5440 t = fd->loops[i + 1].n1;
5441 t = force_gimple_operand_gsi (&gsi, t,
5442 DECL_P (fd->loops[i + 1].v)
5443 && TREE_ADDRESSABLE (fd->loops[i
5444 + 1].v),
5445 NULL_TREE, false,
5446 GSI_CONTINUE_LINKING);
5447 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5448 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5450 else
5451 collapse_bb = bb;
5453 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5455 if (POINTER_TYPE_P (vtype))
5456 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5457 else
5458 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5459 t = force_gimple_operand_gsi (&gsi, t,
5460 DECL_P (fd->loops[i].v)
5461 && TREE_ADDRESSABLE (fd->loops[i].v),
5462 NULL_TREE, false, GSI_CONTINUE_LINKING);
5463 stmt = gimple_build_assign (fd->loops[i].v, t);
5464 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5466 if (i > 0)
5468 t = fd->loops[i].n2;
5469 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5470 false, GSI_CONTINUE_LINKING);
5471 tree v = fd->loops[i].v;
5472 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5473 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5474 false, GSI_CONTINUE_LINKING);
5475 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5476 stmt = gimple_build_cond_empty (t);
5477 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5478 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5479 e->probability = REG_BR_PROB_BASE * 7 / 8;
5481 else
5482 make_edge (bb, body_bb, EDGE_FALLTHRU);
5483 last_bb = bb;
5486 return collapse_bb;
5490 /* A subroutine of expand_omp_for. Generate code for a parallel
5491 loop with any schedule. Given parameters:
5493 for (V = N1; V cond N2; V += STEP) BODY;
5495 where COND is "<" or ">", we generate pseudocode
5497 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5498 if (more) goto L0; else goto L3;
5500 V = istart0;
5501 iend = iend0;
5503 BODY;
5504 V += STEP;
5505 if (V cond iend) goto L1; else goto L2;
5507 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5510 If this is a combined omp parallel loop, instead of the call to
5511 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5512 If this is gimple_omp_for_combined_p loop, then instead of assigning
5513 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5514 inner GIMPLE_OMP_FOR and V += STEP; and
5515 if (V cond iend) goto L1; else goto L2; are removed.
5517 For collapsed loops, given parameters:
5518 collapse(3)
5519 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5520 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5521 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5522 BODY;
5524 we generate pseudocode
5526 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5527 if (cond3 is <)
5528 adj = STEP3 - 1;
5529 else
5530 adj = STEP3 + 1;
5531 count3 = (adj + N32 - N31) / STEP3;
5532 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5533 if (cond2 is <)
5534 adj = STEP2 - 1;
5535 else
5536 adj = STEP2 + 1;
5537 count2 = (adj + N22 - N21) / STEP2;
5538 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5539 if (cond1 is <)
5540 adj = STEP1 - 1;
5541 else
5542 adj = STEP1 + 1;
5543 count1 = (adj + N12 - N11) / STEP1;
5544 count = count1 * count2 * count3;
5545 goto Z1;
5547 count = 0;
5549 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5550 if (more) goto L0; else goto L3;
5552 V = istart0;
5553 T = V;
5554 V3 = N31 + (T % count3) * STEP3;
5555 T = T / count3;
5556 V2 = N21 + (T % count2) * STEP2;
5557 T = T / count2;
5558 V1 = N11 + T * STEP1;
5559 iend = iend0;
5561 BODY;
5562 V += 1;
5563 if (V < iend) goto L10; else goto L2;
5564 L10:
5565 V3 += STEP3;
5566 if (V3 cond3 N32) goto L1; else goto L11;
5567 L11:
5568 V3 = N31;
5569 V2 += STEP2;
5570 if (V2 cond2 N22) goto L1; else goto L12;
5571 L12:
5572 V2 = N21;
5573 V1 += STEP1;
5574 goto L1;
5576 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5581 static void
5582 expand_omp_for_generic (struct omp_region *region,
5583 struct omp_for_data *fd,
5584 enum built_in_function start_fn,
5585 enum built_in_function next_fn,
5586 gimple inner_stmt)
5588 tree type, istart0, iend0, iend;
5589 tree t, vmain, vback, bias = NULL_TREE;
5590 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5591 basic_block l2_bb = NULL, l3_bb = NULL;
5592 gimple_stmt_iterator gsi;
5593 gimple stmt;
5594 bool in_combined_parallel = is_combined_parallel (region);
5595 bool broken_loop = region->cont == NULL;
5596 edge e, ne;
5597 tree *counts = NULL;
5598 int i;
5600 gcc_assert (!broken_loop || !in_combined_parallel);
5601 gcc_assert (fd->iter_type == long_integer_type_node
5602 || !in_combined_parallel);
5604 type = TREE_TYPE (fd->loop.v);
5605 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5606 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5607 TREE_ADDRESSABLE (istart0) = 1;
5608 TREE_ADDRESSABLE (iend0) = 1;
5610 /* See if we need to bias by LLONG_MIN. */
5611 if (fd->iter_type == long_long_unsigned_type_node
5612 && TREE_CODE (type) == INTEGER_TYPE
5613 && !TYPE_UNSIGNED (type))
5615 tree n1, n2;
5617 if (fd->loop.cond_code == LT_EXPR)
5619 n1 = fd->loop.n1;
5620 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5622 else
5624 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5625 n2 = fd->loop.n1;
5627 if (TREE_CODE (n1) != INTEGER_CST
5628 || TREE_CODE (n2) != INTEGER_CST
5629 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5630 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5633 entry_bb = region->entry;
5634 cont_bb = region->cont;
5635 collapse_bb = NULL;
5636 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5637 gcc_assert (broken_loop
5638 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5639 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5640 l1_bb = single_succ (l0_bb);
5641 if (!broken_loop)
5643 l2_bb = create_empty_bb (cont_bb);
5644 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5645 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5647 else
5648 l2_bb = NULL;
5649 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5650 exit_bb = region->exit;
5652 gsi = gsi_last_bb (entry_bb);
5654 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5655 if (fd->collapse > 1)
5657 int first_zero_iter = -1;
5658 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5660 counts = XALLOCAVEC (tree, fd->collapse);
5661 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5662 zero_iter_bb, first_zero_iter,
5663 l2_dom_bb);
5665 if (zero_iter_bb)
5667 /* Some counts[i] vars might be uninitialized if
5668 some loop has zero iterations. But the body shouldn't
5669 be executed in that case, so just avoid uninit warnings. */
5670 for (i = first_zero_iter; i < fd->collapse; i++)
5671 if (SSA_VAR_P (counts[i]))
5672 TREE_NO_WARNING (counts[i]) = 1;
5673 gsi_prev (&gsi);
5674 e = split_block (entry_bb, gsi_stmt (gsi));
5675 entry_bb = e->dest;
5676 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5677 gsi = gsi_last_bb (entry_bb);
5678 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5679 get_immediate_dominator (CDI_DOMINATORS,
5680 zero_iter_bb));
5683 if (in_combined_parallel)
5685 /* In a combined parallel loop, emit a call to
5686 GOMP_loop_foo_next. */
5687 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5688 build_fold_addr_expr (istart0),
5689 build_fold_addr_expr (iend0));
5691 else
5693 tree t0, t1, t2, t3, t4;
5694 /* If this is not a combined parallel loop, emit a call to
5695 GOMP_loop_foo_start in ENTRY_BB. */
5696 t4 = build_fold_addr_expr (iend0);
5697 t3 = build_fold_addr_expr (istart0);
5698 t2 = fold_convert (fd->iter_type, fd->loop.step);
5699 t1 = fd->loop.n2;
5700 t0 = fd->loop.n1;
5701 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5703 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5704 OMP_CLAUSE__LOOPTEMP_);
5705 gcc_assert (innerc);
5706 t0 = OMP_CLAUSE_DECL (innerc);
5707 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5708 OMP_CLAUSE__LOOPTEMP_);
5709 gcc_assert (innerc);
5710 t1 = OMP_CLAUSE_DECL (innerc);
5712 if (POINTER_TYPE_P (TREE_TYPE (t0))
5713 && TYPE_PRECISION (TREE_TYPE (t0))
5714 != TYPE_PRECISION (fd->iter_type))
5716 /* Avoid casting pointers to integer of a different size. */
5717 tree itype = signed_type_for (type);
5718 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5719 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5721 else
5723 t1 = fold_convert (fd->iter_type, t1);
5724 t0 = fold_convert (fd->iter_type, t0);
5726 if (bias)
5728 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5729 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5731 if (fd->iter_type == long_integer_type_node)
5733 if (fd->chunk_size)
5735 t = fold_convert (fd->iter_type, fd->chunk_size);
5736 t = build_call_expr (builtin_decl_explicit (start_fn),
5737 6, t0, t1, t2, t, t3, t4);
5739 else
5740 t = build_call_expr (builtin_decl_explicit (start_fn),
5741 5, t0, t1, t2, t3, t4);
5743 else
5745 tree t5;
5746 tree c_bool_type;
5747 tree bfn_decl;
5749 /* The GOMP_loop_ull_*start functions have additional boolean
5750 argument, true for < loops and false for > loops.
5751 In Fortran, the C bool type can be different from
5752 boolean_type_node. */
5753 bfn_decl = builtin_decl_explicit (start_fn);
5754 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5755 t5 = build_int_cst (c_bool_type,
5756 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5757 if (fd->chunk_size)
5759 tree bfn_decl = builtin_decl_explicit (start_fn);
5760 t = fold_convert (fd->iter_type, fd->chunk_size);
5761 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5763 else
5764 t = build_call_expr (builtin_decl_explicit (start_fn),
5765 6, t5, t0, t1, t2, t3, t4);
5768 if (TREE_TYPE (t) != boolean_type_node)
5769 t = fold_build2 (NE_EXPR, boolean_type_node,
5770 t, build_int_cst (TREE_TYPE (t), 0));
5771 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5772 true, GSI_SAME_STMT);
5773 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5775 /* Remove the GIMPLE_OMP_FOR statement. */
5776 gsi_remove (&gsi, true);
5778 /* Iteration setup for sequential loop goes in L0_BB. */
5779 tree startvar = fd->loop.v;
5780 tree endvar = NULL_TREE;
5782 if (gimple_omp_for_combined_p (fd->for_stmt))
5784 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5785 && gimple_omp_for_kind (inner_stmt)
5786 == GF_OMP_FOR_KIND_SIMD);
5787 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5788 OMP_CLAUSE__LOOPTEMP_);
5789 gcc_assert (innerc);
5790 startvar = OMP_CLAUSE_DECL (innerc);
5791 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5792 OMP_CLAUSE__LOOPTEMP_);
5793 gcc_assert (innerc);
5794 endvar = OMP_CLAUSE_DECL (innerc);
5797 gsi = gsi_start_bb (l0_bb);
5798 t = istart0;
5799 if (bias)
5800 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5801 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5802 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5803 t = fold_convert (TREE_TYPE (startvar), t);
5804 t = force_gimple_operand_gsi (&gsi, t,
5805 DECL_P (startvar)
5806 && TREE_ADDRESSABLE (startvar),
5807 NULL_TREE, false, GSI_CONTINUE_LINKING);
5808 stmt = gimple_build_assign (startvar, t);
5809 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5811 t = iend0;
5812 if (bias)
5813 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5814 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5815 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5816 t = fold_convert (TREE_TYPE (startvar), t);
5817 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5818 false, GSI_CONTINUE_LINKING);
5819 if (endvar)
5821 stmt = gimple_build_assign (endvar, iend);
5822 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5823 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
5824 stmt = gimple_build_assign (fd->loop.v, iend);
5825 else
5826 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend,
5827 NULL_TREE);
5828 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5830 if (fd->collapse > 1)
5831 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5833 if (!broken_loop)
5835 /* Code to control the increment and predicate for the sequential
5836 loop goes in the CONT_BB. */
5837 gsi = gsi_last_bb (cont_bb);
5838 stmt = gsi_stmt (gsi);
5839 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5840 vmain = gimple_omp_continue_control_use (stmt);
5841 vback = gimple_omp_continue_control_def (stmt);
5843 if (!gimple_omp_for_combined_p (fd->for_stmt))
5845 if (POINTER_TYPE_P (type))
5846 t = fold_build_pointer_plus (vmain, fd->loop.step);
5847 else
5848 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5849 t = force_gimple_operand_gsi (&gsi, t,
5850 DECL_P (vback)
5851 && TREE_ADDRESSABLE (vback),
5852 NULL_TREE, true, GSI_SAME_STMT);
5853 stmt = gimple_build_assign (vback, t);
5854 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5856 t = build2 (fd->loop.cond_code, boolean_type_node,
5857 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5858 iend);
5859 stmt = gimple_build_cond_empty (t);
5860 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5863 /* Remove GIMPLE_OMP_CONTINUE. */
5864 gsi_remove (&gsi, true);
5866 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5867 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5869 /* Emit code to get the next parallel iteration in L2_BB. */
5870 gsi = gsi_start_bb (l2_bb);
5872 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5873 build_fold_addr_expr (istart0),
5874 build_fold_addr_expr (iend0));
5875 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5876 false, GSI_CONTINUE_LINKING);
5877 if (TREE_TYPE (t) != boolean_type_node)
5878 t = fold_build2 (NE_EXPR, boolean_type_node,
5879 t, build_int_cst (TREE_TYPE (t), 0));
5880 stmt = gimple_build_cond_empty (t);
5881 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5884 /* Add the loop cleanup function. */
5885 gsi = gsi_last_bb (exit_bb);
5886 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5887 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5888 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5889 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5890 else
5891 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5892 stmt = gimple_build_call (t, 0);
5893 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5894 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5895 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5896 gsi_remove (&gsi, true);
5898 /* Connect the new blocks. */
5899 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5900 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5902 if (!broken_loop)
5904 gimple_seq phis;
5906 e = find_edge (cont_bb, l3_bb);
5907 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5909 phis = phi_nodes (l3_bb);
5910 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5912 gimple phi = gsi_stmt (gsi);
5913 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5914 PHI_ARG_DEF_FROM_EDGE (phi, e));
5916 remove_edge (e);
5918 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5919 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5920 e = find_edge (cont_bb, l1_bb);
5921 if (gimple_omp_for_combined_p (fd->for_stmt))
5923 remove_edge (e);
5924 e = NULL;
5926 else if (fd->collapse > 1)
5928 remove_edge (e);
5929 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5931 else
5932 e->flags = EDGE_TRUE_VALUE;
5933 if (e)
5935 e->probability = REG_BR_PROB_BASE * 7 / 8;
5936 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5938 else
5940 e = find_edge (cont_bb, l2_bb);
5941 e->flags = EDGE_FALLTHRU;
5943 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5945 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5946 recompute_dominator (CDI_DOMINATORS, l2_bb));
5947 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5948 recompute_dominator (CDI_DOMINATORS, l3_bb));
5949 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5950 recompute_dominator (CDI_DOMINATORS, l0_bb));
5951 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5952 recompute_dominator (CDI_DOMINATORS, l1_bb));
5954 struct loop *outer_loop = alloc_loop ();
5955 outer_loop->header = l0_bb;
5956 outer_loop->latch = l2_bb;
5957 add_loop (outer_loop, l0_bb->loop_father);
5959 if (!gimple_omp_for_combined_p (fd->for_stmt))
5961 struct loop *loop = alloc_loop ();
5962 loop->header = l1_bb;
5963 /* The loop may have multiple latches. */
5964 add_loop (loop, outer_loop);
5970 /* A subroutine of expand_omp_for. Generate code for a parallel
5971 loop with static schedule and no specified chunk size. Given
5972 parameters:
5974 for (V = N1; V cond N2; V += STEP) BODY;
5976 where COND is "<" or ">", we generate pseudocode
5978 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5979 if (cond is <)
5980 adj = STEP - 1;
5981 else
5982 adj = STEP + 1;
5983 if ((__typeof (V)) -1 > 0 && cond is >)
5984 n = -(adj + N2 - N1) / -STEP;
5985 else
5986 n = (adj + N2 - N1) / STEP;
5987 q = n / nthreads;
5988 tt = n % nthreads;
5989 if (threadid < tt) goto L3; else goto L4;
5991 tt = 0;
5992 q = q + 1;
5994 s0 = q * threadid + tt;
5995 e0 = s0 + q;
5996 V = s0 * STEP + N1;
5997 if (s0 >= e0) goto L2; else goto L0;
5999 e = e0 * STEP + N1;
6001 BODY;
6002 V += STEP;
6003 if (V cond e) goto L1;
6007 static void
6008 expand_omp_for_static_nochunk (struct omp_region *region,
6009 struct omp_for_data *fd,
6010 gimple inner_stmt)
6012 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6013 tree type, itype, vmain, vback;
6014 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6015 basic_block body_bb, cont_bb, collapse_bb = NULL;
6016 basic_block fin_bb;
6017 gimple_stmt_iterator gsi;
6018 gimple stmt;
6019 edge ep;
6020 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6021 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6022 bool broken_loop = region->cont == NULL;
6023 tree *counts = NULL;
6024 tree n1, n2, step;
6026 itype = type = TREE_TYPE (fd->loop.v);
6027 if (POINTER_TYPE_P (type))
6028 itype = signed_type_for (type);
6030 entry_bb = region->entry;
6031 cont_bb = region->cont;
6032 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6033 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6034 gcc_assert (broken_loop
6035 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6036 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6037 body_bb = single_succ (seq_start_bb);
6038 if (!broken_loop)
6040 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6041 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6043 exit_bb = region->exit;
6045 /* Iteration space partitioning goes in ENTRY_BB. */
6046 gsi = gsi_last_bb (entry_bb);
6047 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6049 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6051 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6052 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6055 if (fd->collapse > 1)
6057 int first_zero_iter = -1;
6058 basic_block l2_dom_bb = NULL;
6060 counts = XALLOCAVEC (tree, fd->collapse);
6061 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6062 fin_bb, first_zero_iter,
6063 l2_dom_bb);
6064 t = NULL_TREE;
6066 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6067 t = integer_one_node;
6068 else
6069 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6070 fold_convert (type, fd->loop.n1),
6071 fold_convert (type, fd->loop.n2));
6072 if (fd->collapse == 1
6073 && TYPE_UNSIGNED (type)
6074 && (t == NULL_TREE || !integer_onep (t)))
6076 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6077 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6078 true, GSI_SAME_STMT);
6079 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6080 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6081 true, GSI_SAME_STMT);
6082 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6083 NULL_TREE, NULL_TREE);
6084 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6085 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6086 expand_omp_regimplify_p, NULL, NULL)
6087 || walk_tree (gimple_cond_rhs_ptr (stmt),
6088 expand_omp_regimplify_p, NULL, NULL))
6090 gsi = gsi_for_stmt (stmt);
6091 gimple_regimplify_operands (stmt, &gsi);
6093 ep = split_block (entry_bb, stmt);
6094 ep->flags = EDGE_TRUE_VALUE;
6095 entry_bb = ep->dest;
6096 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6097 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6098 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6099 if (gimple_in_ssa_p (cfun))
6101 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6102 for (gsi = gsi_start_phis (fin_bb);
6103 !gsi_end_p (gsi); gsi_next (&gsi))
6105 gimple phi = gsi_stmt (gsi);
6106 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6107 ep, UNKNOWN_LOCATION);
6110 gsi = gsi_last_bb (entry_bb);
6113 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6114 t = fold_convert (itype, t);
6115 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6116 true, GSI_SAME_STMT);
6118 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6119 t = fold_convert (itype, t);
6120 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6121 true, GSI_SAME_STMT);
6123 n1 = fd->loop.n1;
6124 n2 = fd->loop.n2;
6125 step = fd->loop.step;
6126 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6128 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6129 OMP_CLAUSE__LOOPTEMP_);
6130 gcc_assert (innerc);
6131 n1 = OMP_CLAUSE_DECL (innerc);
6132 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6133 OMP_CLAUSE__LOOPTEMP_);
6134 gcc_assert (innerc);
6135 n2 = OMP_CLAUSE_DECL (innerc);
6137 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6138 true, NULL_TREE, true, GSI_SAME_STMT);
6139 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6140 true, NULL_TREE, true, GSI_SAME_STMT);
6141 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6142 true, NULL_TREE, true, GSI_SAME_STMT);
6144 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6145 t = fold_build2 (PLUS_EXPR, itype, step, t);
6146 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6147 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6148 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6149 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6150 fold_build1 (NEGATE_EXPR, itype, t),
6151 fold_build1 (NEGATE_EXPR, itype, step));
6152 else
6153 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6154 t = fold_convert (itype, t);
6155 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6157 q = create_tmp_reg (itype, "q");
6158 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6159 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6160 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6162 tt = create_tmp_reg (itype, "tt");
6163 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6164 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6165 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6167 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6168 stmt = gimple_build_cond_empty (t);
6169 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6171 second_bb = split_block (entry_bb, stmt)->dest;
6172 gsi = gsi_last_bb (second_bb);
6173 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6175 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6176 GSI_SAME_STMT);
6177 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
6178 build_int_cst (itype, 1));
6179 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6181 third_bb = split_block (second_bb, stmt)->dest;
6182 gsi = gsi_last_bb (third_bb);
6183 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6185 t = build2 (MULT_EXPR, itype, q, threadid);
6186 t = build2 (PLUS_EXPR, itype, t, tt);
6187 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6189 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6190 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6192 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6193 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6195 /* Remove the GIMPLE_OMP_FOR statement. */
6196 gsi_remove (&gsi, true);
6198 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6199 gsi = gsi_start_bb (seq_start_bb);
6201 tree startvar = fd->loop.v;
6202 tree endvar = NULL_TREE;
6204 if (gimple_omp_for_combined_p (fd->for_stmt))
6206 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6207 ? gimple_omp_parallel_clauses (inner_stmt)
6208 : gimple_omp_for_clauses (inner_stmt);
6209 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6210 gcc_assert (innerc);
6211 startvar = OMP_CLAUSE_DECL (innerc);
6212 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6213 OMP_CLAUSE__LOOPTEMP_);
6214 gcc_assert (innerc);
6215 endvar = OMP_CLAUSE_DECL (innerc);
6217 t = fold_convert (itype, s0);
6218 t = fold_build2 (MULT_EXPR, itype, t, step);
6219 if (POINTER_TYPE_P (type))
6220 t = fold_build_pointer_plus (n1, t);
6221 else
6222 t = fold_build2 (PLUS_EXPR, type, t, n1);
6223 t = fold_convert (TREE_TYPE (startvar), t);
6224 t = force_gimple_operand_gsi (&gsi, t,
6225 DECL_P (startvar)
6226 && TREE_ADDRESSABLE (startvar),
6227 NULL_TREE, false, GSI_CONTINUE_LINKING);
6228 stmt = gimple_build_assign (startvar, t);
6229 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6231 t = fold_convert (itype, e0);
6232 t = fold_build2 (MULT_EXPR, itype, t, step);
6233 if (POINTER_TYPE_P (type))
6234 t = fold_build_pointer_plus (n1, t);
6235 else
6236 t = fold_build2 (PLUS_EXPR, type, t, n1);
6237 t = fold_convert (TREE_TYPE (startvar), t);
6238 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6239 false, GSI_CONTINUE_LINKING);
6240 if (endvar)
6242 stmt = gimple_build_assign (endvar, e);
6243 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6244 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6245 stmt = gimple_build_assign (fd->loop.v, e);
6246 else
6247 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6248 NULL_TREE);
6249 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6251 if (fd->collapse > 1)
6252 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6254 if (!broken_loop)
6256 /* The code controlling the sequential loop replaces the
6257 GIMPLE_OMP_CONTINUE. */
6258 gsi = gsi_last_bb (cont_bb);
6259 stmt = gsi_stmt (gsi);
6260 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6261 vmain = gimple_omp_continue_control_use (stmt);
6262 vback = gimple_omp_continue_control_def (stmt);
6264 if (!gimple_omp_for_combined_p (fd->for_stmt))
6266 if (POINTER_TYPE_P (type))
6267 t = fold_build_pointer_plus (vmain, step);
6268 else
6269 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6270 t = force_gimple_operand_gsi (&gsi, t,
6271 DECL_P (vback)
6272 && TREE_ADDRESSABLE (vback),
6273 NULL_TREE, true, GSI_SAME_STMT);
6274 stmt = gimple_build_assign (vback, t);
6275 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6277 t = build2 (fd->loop.cond_code, boolean_type_node,
6278 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6279 ? t : vback, e);
6280 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6283 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6284 gsi_remove (&gsi, true);
6286 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6287 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6290 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6291 gsi = gsi_last_bb (exit_bb);
6292 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6294 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6295 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6297 gsi_remove (&gsi, true);
6299 /* Connect all the blocks. */
6300 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6301 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6302 ep = find_edge (entry_bb, second_bb);
6303 ep->flags = EDGE_TRUE_VALUE;
6304 ep->probability = REG_BR_PROB_BASE / 4;
6305 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6306 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6308 if (!broken_loop)
6310 ep = find_edge (cont_bb, body_bb);
6311 if (gimple_omp_for_combined_p (fd->for_stmt))
6313 remove_edge (ep);
6314 ep = NULL;
6316 else if (fd->collapse > 1)
6318 remove_edge (ep);
6319 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6321 else
6322 ep->flags = EDGE_TRUE_VALUE;
6323 find_edge (cont_bb, fin_bb)->flags
6324 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6327 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6328 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6329 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6331 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6332 recompute_dominator (CDI_DOMINATORS, body_bb));
6333 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6334 recompute_dominator (CDI_DOMINATORS, fin_bb));
6336 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6338 struct loop *loop = alloc_loop ();
6339 loop->header = body_bb;
6340 if (collapse_bb == NULL)
6341 loop->latch = cont_bb;
6342 add_loop (loop, body_bb->loop_father);
6347 /* A subroutine of expand_omp_for. Generate code for a parallel
6348 loop with static schedule and a specified chunk size. Given
6349 parameters:
6351 for (V = N1; V cond N2; V += STEP) BODY;
6353 where COND is "<" or ">", we generate pseudocode
6355 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6356 if (cond is <)
6357 adj = STEP - 1;
6358 else
6359 adj = STEP + 1;
6360 if ((__typeof (V)) -1 > 0 && cond is >)
6361 n = -(adj + N2 - N1) / -STEP;
6362 else
6363 n = (adj + N2 - N1) / STEP;
6364 trip = 0;
6365 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6366 here so that V is defined
6367 if the loop is not entered
6369 s0 = (trip * nthreads + threadid) * CHUNK;
6370 e0 = min(s0 + CHUNK, n);
6371 if (s0 < n) goto L1; else goto L4;
6373 V = s0 * STEP + N1;
6374 e = e0 * STEP + N1;
6376 BODY;
6377 V += STEP;
6378 if (V cond e) goto L2; else goto L3;
6380 trip += 1;
6381 goto L0;
6385 static void
6386 expand_omp_for_static_chunk (struct omp_region *region,
6387 struct omp_for_data *fd, gimple inner_stmt)
6389 tree n, s0, e0, e, t;
6390 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6391 tree type, itype, vmain, vback, vextra;
6392 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6393 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6394 gimple_stmt_iterator gsi;
6395 gimple stmt;
6396 edge se;
6397 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6398 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6399 bool broken_loop = region->cont == NULL;
6400 tree *counts = NULL;
6401 tree n1, n2, step;
6403 itype = type = TREE_TYPE (fd->loop.v);
6404 if (POINTER_TYPE_P (type))
6405 itype = signed_type_for (type);
6407 entry_bb = region->entry;
6408 se = split_block (entry_bb, last_stmt (entry_bb));
6409 entry_bb = se->src;
6410 iter_part_bb = se->dest;
6411 cont_bb = region->cont;
6412 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6413 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6414 gcc_assert (broken_loop
6415 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6416 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6417 body_bb = single_succ (seq_start_bb);
6418 if (!broken_loop)
6420 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6421 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6422 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6424 exit_bb = region->exit;
6426 /* Trip and adjustment setup goes in ENTRY_BB. */
6427 gsi = gsi_last_bb (entry_bb);
6428 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6430 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6432 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6433 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6436 if (fd->collapse > 1)
6438 int first_zero_iter = -1;
6439 basic_block l2_dom_bb = NULL;
6441 counts = XALLOCAVEC (tree, fd->collapse);
6442 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6443 fin_bb, first_zero_iter,
6444 l2_dom_bb);
6445 t = NULL_TREE;
6447 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6448 t = integer_one_node;
6449 else
6450 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6451 fold_convert (type, fd->loop.n1),
6452 fold_convert (type, fd->loop.n2));
6453 if (fd->collapse == 1
6454 && TYPE_UNSIGNED (type)
6455 && (t == NULL_TREE || !integer_onep (t)))
6457 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6458 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6459 true, GSI_SAME_STMT);
6460 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6461 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6462 true, GSI_SAME_STMT);
6463 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6464 NULL_TREE, NULL_TREE);
6465 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6466 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6467 expand_omp_regimplify_p, NULL, NULL)
6468 || walk_tree (gimple_cond_rhs_ptr (stmt),
6469 expand_omp_regimplify_p, NULL, NULL))
6471 gsi = gsi_for_stmt (stmt);
6472 gimple_regimplify_operands (stmt, &gsi);
6474 se = split_block (entry_bb, stmt);
6475 se->flags = EDGE_TRUE_VALUE;
6476 entry_bb = se->dest;
6477 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6478 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6479 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6480 if (gimple_in_ssa_p (cfun))
6482 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6483 for (gsi = gsi_start_phis (fin_bb);
6484 !gsi_end_p (gsi); gsi_next (&gsi))
6486 gimple phi = gsi_stmt (gsi);
6487 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6488 se, UNKNOWN_LOCATION);
6491 gsi = gsi_last_bb (entry_bb);
6494 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6495 t = fold_convert (itype, t);
6496 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6497 true, GSI_SAME_STMT);
6499 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6500 t = fold_convert (itype, t);
6501 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6502 true, GSI_SAME_STMT);
6504 n1 = fd->loop.n1;
6505 n2 = fd->loop.n2;
6506 step = fd->loop.step;
6507 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6509 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6510 OMP_CLAUSE__LOOPTEMP_);
6511 gcc_assert (innerc);
6512 n1 = OMP_CLAUSE_DECL (innerc);
6513 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6514 OMP_CLAUSE__LOOPTEMP_);
6515 gcc_assert (innerc);
6516 n2 = OMP_CLAUSE_DECL (innerc);
6518 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6519 true, NULL_TREE, true, GSI_SAME_STMT);
6520 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6521 true, NULL_TREE, true, GSI_SAME_STMT);
6522 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6523 true, NULL_TREE, true, GSI_SAME_STMT);
6524 fd->chunk_size
6525 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
6526 true, NULL_TREE, true, GSI_SAME_STMT);
6528 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6529 t = fold_build2 (PLUS_EXPR, itype, step, t);
6530 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6531 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6532 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6533 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6534 fold_build1 (NEGATE_EXPR, itype, t),
6535 fold_build1 (NEGATE_EXPR, itype, step));
6536 else
6537 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6538 t = fold_convert (itype, t);
6539 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6540 true, GSI_SAME_STMT);
6542 trip_var = create_tmp_reg (itype, ".trip");
6543 if (gimple_in_ssa_p (cfun))
6545 trip_init = make_ssa_name (trip_var, NULL);
6546 trip_main = make_ssa_name (trip_var, NULL);
6547 trip_back = make_ssa_name (trip_var, NULL);
6549 else
6551 trip_init = trip_var;
6552 trip_main = trip_var;
6553 trip_back = trip_var;
6556 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6557 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6559 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6560 t = fold_build2 (MULT_EXPR, itype, t, step);
6561 if (POINTER_TYPE_P (type))
6562 t = fold_build_pointer_plus (n1, t);
6563 else
6564 t = fold_build2 (PLUS_EXPR, type, t, n1);
6565 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6566 true, GSI_SAME_STMT);
6568 /* Remove the GIMPLE_OMP_FOR. */
6569 gsi_remove (&gsi, true);
6571 /* Iteration space partitioning goes in ITER_PART_BB. */
6572 gsi = gsi_last_bb (iter_part_bb);
6574 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6575 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6576 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6577 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6578 false, GSI_CONTINUE_LINKING);
6580 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6581 t = fold_build2 (MIN_EXPR, itype, t, n);
6582 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6583 false, GSI_CONTINUE_LINKING);
6585 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6586 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6588 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6589 gsi = gsi_start_bb (seq_start_bb);
6591 tree startvar = fd->loop.v;
6592 tree endvar = NULL_TREE;
6594 if (gimple_omp_for_combined_p (fd->for_stmt))
6596 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6597 ? gimple_omp_parallel_clauses (inner_stmt)
6598 : gimple_omp_for_clauses (inner_stmt);
6599 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6600 gcc_assert (innerc);
6601 startvar = OMP_CLAUSE_DECL (innerc);
6602 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6603 OMP_CLAUSE__LOOPTEMP_);
6604 gcc_assert (innerc);
6605 endvar = OMP_CLAUSE_DECL (innerc);
6608 t = fold_convert (itype, s0);
6609 t = fold_build2 (MULT_EXPR, itype, t, step);
6610 if (POINTER_TYPE_P (type))
6611 t = fold_build_pointer_plus (n1, t);
6612 else
6613 t = fold_build2 (PLUS_EXPR, type, t, n1);
6614 t = fold_convert (TREE_TYPE (startvar), t);
6615 t = force_gimple_operand_gsi (&gsi, t,
6616 DECL_P (startvar)
6617 && TREE_ADDRESSABLE (startvar),
6618 NULL_TREE, false, GSI_CONTINUE_LINKING);
6619 stmt = gimple_build_assign (startvar, t);
6620 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6622 t = fold_convert (itype, e0);
6623 t = fold_build2 (MULT_EXPR, itype, t, step);
6624 if (POINTER_TYPE_P (type))
6625 t = fold_build_pointer_plus (n1, t);
6626 else
6627 t = fold_build2 (PLUS_EXPR, type, t, n1);
6628 t = fold_convert (TREE_TYPE (startvar), t);
6629 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6630 false, GSI_CONTINUE_LINKING);
6631 if (endvar)
6633 stmt = gimple_build_assign (endvar, e);
6634 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6635 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6636 stmt = gimple_build_assign (fd->loop.v, e);
6637 else
6638 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6639 NULL_TREE);
6640 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6642 if (fd->collapse > 1)
6643 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6645 if (!broken_loop)
6647 /* The code controlling the sequential loop goes in CONT_BB,
6648 replacing the GIMPLE_OMP_CONTINUE. */
6649 gsi = gsi_last_bb (cont_bb);
6650 stmt = gsi_stmt (gsi);
6651 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6652 vmain = gimple_omp_continue_control_use (stmt);
6653 vback = gimple_omp_continue_control_def (stmt);
6655 if (!gimple_omp_for_combined_p (fd->for_stmt))
6657 if (POINTER_TYPE_P (type))
6658 t = fold_build_pointer_plus (vmain, step);
6659 else
6660 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6661 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
6662 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6663 true, GSI_SAME_STMT);
6664 stmt = gimple_build_assign (vback, t);
6665 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6667 t = build2 (fd->loop.cond_code, boolean_type_node,
6668 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6669 ? t : vback, e);
6670 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6673 /* Remove GIMPLE_OMP_CONTINUE. */
6674 gsi_remove (&gsi, true);
6676 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6677 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6679 /* Trip update code goes into TRIP_UPDATE_BB. */
6680 gsi = gsi_start_bb (trip_update_bb);
6682 t = build_int_cst (itype, 1);
6683 t = build2 (PLUS_EXPR, itype, trip_main, t);
6684 stmt = gimple_build_assign (trip_back, t);
6685 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6688 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6689 gsi = gsi_last_bb (exit_bb);
6690 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6692 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6693 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6695 gsi_remove (&gsi, true);
6697 /* Connect the new blocks. */
6698 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6699 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6701 if (!broken_loop)
6703 se = find_edge (cont_bb, body_bb);
6704 if (gimple_omp_for_combined_p (fd->for_stmt))
6706 remove_edge (se);
6707 se = NULL;
6709 else if (fd->collapse > 1)
6711 remove_edge (se);
6712 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6714 else
6715 se->flags = EDGE_TRUE_VALUE;
6716 find_edge (cont_bb, trip_update_bb)->flags
6717 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6719 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6722 if (gimple_in_ssa_p (cfun))
6724 gimple_stmt_iterator psi;
6725 gimple phi;
6726 edge re, ene;
6727 edge_var_map *vm;
6728 size_t i;
6730 gcc_assert (fd->collapse == 1 && !broken_loop);
6732 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6733 remove arguments of the phi nodes in fin_bb. We need to create
6734 appropriate phi nodes in iter_part_bb instead. */
6735 se = single_pred_edge (fin_bb);
6736 re = single_succ_edge (trip_update_bb);
6737 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
6738 ene = single_succ_edge (entry_bb);
6740 psi = gsi_start_phis (fin_bb);
6741 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6742 gsi_next (&psi), ++i)
6744 gimple nphi;
6745 source_location locus;
6747 phi = gsi_stmt (psi);
6748 t = gimple_phi_result (phi);
6749 gcc_assert (t == redirect_edge_var_map_result (vm));
6750 nphi = create_phi_node (t, iter_part_bb);
6752 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6753 locus = gimple_phi_arg_location_from_edge (phi, se);
6755 /* A special case -- fd->loop.v is not yet computed in
6756 iter_part_bb, we need to use vextra instead. */
6757 if (t == fd->loop.v)
6758 t = vextra;
6759 add_phi_arg (nphi, t, ene, locus);
6760 locus = redirect_edge_var_map_location (vm);
6761 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6763 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6764 redirect_edge_var_map_clear (re);
6765 while (1)
6767 psi = gsi_start_phis (fin_bb);
6768 if (gsi_end_p (psi))
6769 break;
6770 remove_phi_node (&psi, false);
6773 /* Make phi node for trip. */
6774 phi = create_phi_node (trip_main, iter_part_bb);
6775 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6776 UNKNOWN_LOCATION);
6777 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6778 UNKNOWN_LOCATION);
6781 if (!broken_loop)
6782 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6783 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6784 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6785 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6786 recompute_dominator (CDI_DOMINATORS, fin_bb));
6787 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6788 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6789 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6790 recompute_dominator (CDI_DOMINATORS, body_bb));
6792 if (!broken_loop)
6794 struct loop *trip_loop = alloc_loop ();
6795 trip_loop->header = iter_part_bb;
6796 trip_loop->latch = trip_update_bb;
6797 add_loop (trip_loop, iter_part_bb->loop_father);
6799 if (!gimple_omp_for_combined_p (fd->for_stmt))
6801 struct loop *loop = alloc_loop ();
6802 loop->header = body_bb;
6803 if (collapse_bb == NULL)
6804 loop->latch = cont_bb;
6805 add_loop (loop, trip_loop);
6810 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
6811 Given parameters:
6812 for (V = N1; V cond N2; V += STEP) BODY;
6814 where COND is "<" or ">" or "!=", we generate pseudocode
6816 for (ind_var = low; ind_var < high; ind_var++)
6818 V = n1 + (ind_var * STEP)
6820 <BODY>
6823 In the above pseudocode, low and high are function parameters of the
6824 child function. In the function below, we are inserting a temp.
6825 variable that will be making a call to two OMP functions that will not be
6826 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
6827 with _Cilk_for). These functions are replaced with low and high
6828 by the function that handles taskreg. */
6831 static void
6832 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
6834 bool broken_loop = region->cont == NULL;
6835 basic_block entry_bb = region->entry;
6836 basic_block cont_bb = region->cont;
6838 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6839 gcc_assert (broken_loop
6840 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6841 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6842 basic_block l1_bb, l2_bb;
6844 if (!broken_loop)
6846 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6847 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6848 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6849 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6851 else
6853 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6854 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6855 l2_bb = single_succ (l1_bb);
6857 basic_block exit_bb = region->exit;
6858 basic_block l2_dom_bb = NULL;
6860 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
6862 /* Below statements until the "tree high_val = ..." are pseudo statements
6863 used to pass information to be used by expand_omp_taskreg.
6864 low_val and high_val will be replaced by the __low and __high
6865 parameter from the child function.
6867 The call_exprs part is a place-holder, it is mainly used
6868 to distinctly identify to the top-level part that this is
6869 where we should put low and high (reasoning given in header
6870 comment). */
6872 tree child_fndecl
6873 = gimple_omp_parallel_child_fn (last_stmt (region->outer->entry));
6874 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
6875 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
6877 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
6878 high_val = t;
6879 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
6880 low_val = t;
6882 gcc_assert (low_val && high_val);
6884 tree type = TREE_TYPE (low_val);
6885 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
6886 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6888 /* Not needed in SSA form right now. */
6889 gcc_assert (!gimple_in_ssa_p (cfun));
6890 if (l2_dom_bb == NULL)
6891 l2_dom_bb = l1_bb;
6893 tree n1 = low_val;
6894 tree n2 = high_val;
6896 gimple stmt = gimple_build_assign (ind_var, n1);
6898 /* Replace the GIMPLE_OMP_FOR statement. */
6899 gsi_replace (&gsi, stmt, true);
6901 if (!broken_loop)
6903 /* Code to control the increment goes in the CONT_BB. */
6904 gsi = gsi_last_bb (cont_bb);
6905 stmt = gsi_stmt (gsi);
6906 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6907 stmt = gimple_build_assign_with_ops (PLUS_EXPR, ind_var, ind_var,
6908 build_one_cst (type));
6910 /* Replace GIMPLE_OMP_CONTINUE. */
6911 gsi_replace (&gsi, stmt, true);
6914 /* Emit the condition in L1_BB. */
6915 gsi = gsi_after_labels (l1_bb);
6916 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
6917 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
6918 fd->loop.step);
6919 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
6920 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6921 fd->loop.n1, fold_convert (sizetype, t));
6922 else
6923 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6924 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
6925 t = fold_convert (TREE_TYPE (fd->loop.v), t);
6926 expand_omp_build_assign (&gsi, fd->loop.v, t);
6928 /* The condition is always '<' since the runtime will fill in the low
6929 and high values. */
6930 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
6931 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6933 /* Remove GIMPLE_OMP_RETURN. */
6934 gsi = gsi_last_bb (exit_bb);
6935 gsi_remove (&gsi, true);
6937 /* Connect the new blocks. */
6938 remove_edge (FALLTHRU_EDGE (entry_bb));
6940 edge e, ne;
6941 if (!broken_loop)
6943 remove_edge (BRANCH_EDGE (entry_bb));
6944 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6946 e = BRANCH_EDGE (l1_bb);
6947 ne = FALLTHRU_EDGE (l1_bb);
6948 e->flags = EDGE_TRUE_VALUE;
6950 else
6952 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6954 ne = single_succ_edge (l1_bb);
6955 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6958 ne->flags = EDGE_FALSE_VALUE;
6959 e->probability = REG_BR_PROB_BASE * 7 / 8;
6960 ne->probability = REG_BR_PROB_BASE / 8;
6962 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6963 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6964 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6966 if (!broken_loop)
6968 struct loop *loop = alloc_loop ();
6969 loop->header = l1_bb;
6970 loop->latch = cont_bb;
6971 add_loop (loop, l1_bb->loop_father);
6972 loop->safelen = INT_MAX;
6975 /* Pick the correct library function based on the precision of the
6976 induction variable type. */
6977 tree lib_fun = NULL_TREE;
6978 if (TYPE_PRECISION (type) == 32)
6979 lib_fun = cilk_for_32_fndecl;
6980 else if (TYPE_PRECISION (type) == 64)
6981 lib_fun = cilk_for_64_fndecl;
6982 else
6983 gcc_unreachable ();
6985 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
6987 /* WS_ARGS contains the library function flavor to call:
6988 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
6989 user-defined grain value. If the user does not define one, then zero
6990 is passed in by the parser. */
6991 vec_alloc (region->ws_args, 2);
6992 region->ws_args->quick_push (lib_fun);
6993 region->ws_args->quick_push (fd->chunk_size);
6996 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6997 loop. Given parameters:
6999 for (V = N1; V cond N2; V += STEP) BODY;
7001 where COND is "<" or ">", we generate pseudocode
7003 V = N1;
7004 goto L1;
7006 BODY;
7007 V += STEP;
7009 if (V cond N2) goto L0; else goto L2;
7012 For collapsed loops, given parameters:
7013 collapse(3)
7014 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7015 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7016 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7017 BODY;
7019 we generate pseudocode
7021 if (cond3 is <)
7022 adj = STEP3 - 1;
7023 else
7024 adj = STEP3 + 1;
7025 count3 = (adj + N32 - N31) / STEP3;
7026 if (cond2 is <)
7027 adj = STEP2 - 1;
7028 else
7029 adj = STEP2 + 1;
7030 count2 = (adj + N22 - N21) / STEP2;
7031 if (cond1 is <)
7032 adj = STEP1 - 1;
7033 else
7034 adj = STEP1 + 1;
7035 count1 = (adj + N12 - N11) / STEP1;
7036 count = count1 * count2 * count3;
7037 V = 0;
7038 V1 = N11;
7039 V2 = N21;
7040 V3 = N31;
7041 goto L1;
7043 BODY;
7044 V += 1;
7045 V3 += STEP3;
7046 V2 += (V3 cond3 N32) ? 0 : STEP2;
7047 V3 = (V3 cond3 N32) ? V3 : N31;
7048 V1 += (V2 cond2 N22) ? 0 : STEP1;
7049 V2 = (V2 cond2 N22) ? V2 : N21;
7051 if (V < count) goto L0; else goto L2;
7056 static void
7057 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7059 tree type, t;
7060 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7061 gimple_stmt_iterator gsi;
7062 gimple stmt;
7063 bool broken_loop = region->cont == NULL;
7064 edge e, ne;
7065 tree *counts = NULL;
7066 int i;
7067 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7068 OMP_CLAUSE_SAFELEN);
7069 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7070 OMP_CLAUSE__SIMDUID_);
7071 tree n1, n2;
7073 type = TREE_TYPE (fd->loop.v);
7074 entry_bb = region->entry;
7075 cont_bb = region->cont;
7076 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7077 gcc_assert (broken_loop
7078 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7079 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7080 if (!broken_loop)
7082 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7083 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7084 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7085 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7087 else
7089 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7090 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7091 l2_bb = single_succ (l1_bb);
7093 exit_bb = region->exit;
7094 l2_dom_bb = NULL;
7096 gsi = gsi_last_bb (entry_bb);
7098 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7099 /* Not needed in SSA form right now. */
7100 gcc_assert (!gimple_in_ssa_p (cfun));
7101 if (fd->collapse > 1)
7103 int first_zero_iter = -1;
7104 basic_block zero_iter_bb = l2_bb;
7106 counts = XALLOCAVEC (tree, fd->collapse);
7107 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7108 zero_iter_bb, first_zero_iter,
7109 l2_dom_bb);
7111 if (l2_dom_bb == NULL)
7112 l2_dom_bb = l1_bb;
7114 n1 = fd->loop.n1;
7115 n2 = fd->loop.n2;
7116 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7118 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7119 OMP_CLAUSE__LOOPTEMP_);
7120 gcc_assert (innerc);
7121 n1 = OMP_CLAUSE_DECL (innerc);
7122 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7123 OMP_CLAUSE__LOOPTEMP_);
7124 gcc_assert (innerc);
7125 n2 = OMP_CLAUSE_DECL (innerc);
7126 expand_omp_build_assign (&gsi, fd->loop.v,
7127 fold_convert (type, n1));
7128 if (fd->collapse > 1)
7130 gsi_prev (&gsi);
7131 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7132 gsi_next (&gsi);
7135 else
7137 expand_omp_build_assign (&gsi, fd->loop.v,
7138 fold_convert (type, fd->loop.n1));
7139 if (fd->collapse > 1)
7140 for (i = 0; i < fd->collapse; i++)
7142 tree itype = TREE_TYPE (fd->loops[i].v);
7143 if (POINTER_TYPE_P (itype))
7144 itype = signed_type_for (itype);
7145 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7146 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7150 /* Remove the GIMPLE_OMP_FOR statement. */
7151 gsi_remove (&gsi, true);
7153 if (!broken_loop)
7155 /* Code to control the increment goes in the CONT_BB. */
7156 gsi = gsi_last_bb (cont_bb);
7157 stmt = gsi_stmt (gsi);
7158 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7160 if (POINTER_TYPE_P (type))
7161 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7162 else
7163 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7164 expand_omp_build_assign (&gsi, fd->loop.v, t);
7166 if (fd->collapse > 1)
7168 i = fd->collapse - 1;
7169 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7171 t = fold_convert (sizetype, fd->loops[i].step);
7172 t = fold_build_pointer_plus (fd->loops[i].v, t);
7174 else
7176 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7177 fd->loops[i].step);
7178 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7179 fd->loops[i].v, t);
7181 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7183 for (i = fd->collapse - 1; i > 0; i--)
7185 tree itype = TREE_TYPE (fd->loops[i].v);
7186 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7187 if (POINTER_TYPE_P (itype2))
7188 itype2 = signed_type_for (itype2);
7189 t = build3 (COND_EXPR, itype2,
7190 build2 (fd->loops[i].cond_code, boolean_type_node,
7191 fd->loops[i].v,
7192 fold_convert (itype, fd->loops[i].n2)),
7193 build_int_cst (itype2, 0),
7194 fold_convert (itype2, fd->loops[i - 1].step));
7195 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7196 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7197 else
7198 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7199 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7201 t = build3 (COND_EXPR, itype,
7202 build2 (fd->loops[i].cond_code, boolean_type_node,
7203 fd->loops[i].v,
7204 fold_convert (itype, fd->loops[i].n2)),
7205 fd->loops[i].v,
7206 fold_convert (itype, fd->loops[i].n1));
7207 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7211 /* Remove GIMPLE_OMP_CONTINUE. */
7212 gsi_remove (&gsi, true);
7215 /* Emit the condition in L1_BB. */
7216 gsi = gsi_start_bb (l1_bb);
7218 t = fold_convert (type, n2);
7219 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7220 false, GSI_CONTINUE_LINKING);
7221 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7222 stmt = gimple_build_cond_empty (t);
7223 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7224 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
7225 NULL, NULL)
7226 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
7227 NULL, NULL))
7229 gsi = gsi_for_stmt (stmt);
7230 gimple_regimplify_operands (stmt, &gsi);
7233 /* Remove GIMPLE_OMP_RETURN. */
7234 gsi = gsi_last_bb (exit_bb);
7235 gsi_remove (&gsi, true);
7237 /* Connect the new blocks. */
7238 remove_edge (FALLTHRU_EDGE (entry_bb));
7240 if (!broken_loop)
7242 remove_edge (BRANCH_EDGE (entry_bb));
7243 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7245 e = BRANCH_EDGE (l1_bb);
7246 ne = FALLTHRU_EDGE (l1_bb);
7247 e->flags = EDGE_TRUE_VALUE;
7249 else
7251 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7253 ne = single_succ_edge (l1_bb);
7254 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7257 ne->flags = EDGE_FALSE_VALUE;
7258 e->probability = REG_BR_PROB_BASE * 7 / 8;
7259 ne->probability = REG_BR_PROB_BASE / 8;
7261 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7262 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7263 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7265 if (!broken_loop)
7267 struct loop *loop = alloc_loop ();
7268 loop->header = l1_bb;
7269 loop->latch = cont_bb;
7270 add_loop (loop, l1_bb->loop_father);
7271 if (safelen == NULL_TREE)
7272 loop->safelen = INT_MAX;
7273 else
7275 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7276 if (TREE_CODE (safelen) != INTEGER_CST)
7277 loop->safelen = 0;
7278 else if (!tree_fits_uhwi_p (safelen)
7279 || tree_to_uhwi (safelen) > INT_MAX)
7280 loop->safelen = INT_MAX;
7281 else
7282 loop->safelen = tree_to_uhwi (safelen);
7283 if (loop->safelen == 1)
7284 loop->safelen = 0;
7286 if (simduid)
7288 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7289 cfun->has_simduid_loops = true;
7291 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7292 the loop. */
7293 if ((flag_tree_loop_vectorize
7294 || (!global_options_set.x_flag_tree_loop_vectorize
7295 && !global_options_set.x_flag_tree_vectorize))
7296 && flag_tree_loop_optimize
7297 && loop->safelen > 1)
7299 loop->force_vectorize = true;
7300 cfun->has_force_vectorize_loops = true;
7306 /* Expand the OpenMP loop defined by REGION. */
7308 static void
7309 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7311 struct omp_for_data fd;
7312 struct omp_for_data_loop *loops;
7314 loops
7315 = (struct omp_for_data_loop *)
7316 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7317 * sizeof (struct omp_for_data_loop));
7318 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
7319 region->sched_kind = fd.sched_kind;
7321 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7322 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7323 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7324 if (region->cont)
7326 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7327 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7328 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7330 else
7331 /* If there isn't a continue then this is a degerate case where
7332 the introduction of abnormal edges during lowering will prevent
7333 original loops from being detected. Fix that up. */
7334 loops_state_set (LOOPS_NEED_FIXUP);
7336 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7337 expand_omp_simd (region, &fd);
7338 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7339 expand_cilk_for (region, &fd);
7340 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7341 && !fd.have_ordered)
7343 if (fd.chunk_size == NULL)
7344 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7345 else
7346 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7348 else
7350 int fn_index, start_ix, next_ix;
7352 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7353 == GF_OMP_FOR_KIND_FOR);
7354 if (fd.chunk_size == NULL
7355 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7356 fd.chunk_size = integer_zero_node;
7357 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7358 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7359 ? 3 : fd.sched_kind;
7360 fn_index += fd.have_ordered * 4;
7361 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7362 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7363 if (fd.iter_type == long_long_unsigned_type_node)
7365 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7366 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7367 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7368 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7370 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7371 (enum built_in_function) next_ix, inner_stmt);
7374 if (gimple_in_ssa_p (cfun))
7375 update_ssa (TODO_update_ssa_only_virtuals);
7379 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7381 v = GOMP_sections_start (n);
7383 switch (v)
7385 case 0:
7386 goto L2;
7387 case 1:
7388 section 1;
7389 goto L1;
7390 case 2:
7392 case n:
7394 default:
7395 abort ();
7398 v = GOMP_sections_next ();
7399 goto L0;
7401 reduction;
7403 If this is a combined parallel sections, replace the call to
7404 GOMP_sections_start with call to GOMP_sections_next. */
7406 static void
7407 expand_omp_sections (struct omp_region *region)
7409 tree t, u, vin = NULL, vmain, vnext, l2;
7410 unsigned len;
7411 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7412 gimple_stmt_iterator si, switch_si;
7413 gimple sections_stmt, stmt, cont;
7414 edge_iterator ei;
7415 edge e;
7416 struct omp_region *inner;
7417 unsigned i, casei;
7418 bool exit_reachable = region->cont != NULL;
7420 gcc_assert (region->exit != NULL);
7421 entry_bb = region->entry;
7422 l0_bb = single_succ (entry_bb);
7423 l1_bb = region->cont;
7424 l2_bb = region->exit;
7425 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7426 l2 = gimple_block_label (l2_bb);
7427 else
7429 /* This can happen if there are reductions. */
7430 len = EDGE_COUNT (l0_bb->succs);
7431 gcc_assert (len > 0);
7432 e = EDGE_SUCC (l0_bb, len - 1);
7433 si = gsi_last_bb (e->dest);
7434 l2 = NULL_TREE;
7435 if (gsi_end_p (si)
7436 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7437 l2 = gimple_block_label (e->dest);
7438 else
7439 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7441 si = gsi_last_bb (e->dest);
7442 if (gsi_end_p (si)
7443 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7445 l2 = gimple_block_label (e->dest);
7446 break;
7450 if (exit_reachable)
7451 default_bb = create_empty_bb (l1_bb->prev_bb);
7452 else
7453 default_bb = create_empty_bb (l0_bb);
7455 /* We will build a switch() with enough cases for all the
7456 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7457 and a default case to abort if something goes wrong. */
7458 len = EDGE_COUNT (l0_bb->succs);
7460 /* Use vec::quick_push on label_vec throughout, since we know the size
7461 in advance. */
7462 auto_vec<tree> label_vec (len);
7464 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7465 GIMPLE_OMP_SECTIONS statement. */
7466 si = gsi_last_bb (entry_bb);
7467 sections_stmt = gsi_stmt (si);
7468 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7469 vin = gimple_omp_sections_control (sections_stmt);
7470 if (!is_combined_parallel (region))
7472 /* If we are not inside a combined parallel+sections region,
7473 call GOMP_sections_start. */
7474 t = build_int_cst (unsigned_type_node, len - 1);
7475 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7476 stmt = gimple_build_call (u, 1, t);
7478 else
7480 /* Otherwise, call GOMP_sections_next. */
7481 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7482 stmt = gimple_build_call (u, 0);
7484 gimple_call_set_lhs (stmt, vin);
7485 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7486 gsi_remove (&si, true);
7488 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7489 L0_BB. */
7490 switch_si = gsi_last_bb (l0_bb);
7491 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7492 if (exit_reachable)
7494 cont = last_stmt (l1_bb);
7495 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7496 vmain = gimple_omp_continue_control_use (cont);
7497 vnext = gimple_omp_continue_control_def (cont);
7499 else
7501 vmain = vin;
7502 vnext = NULL_TREE;
7505 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7506 label_vec.quick_push (t);
7507 i = 1;
7509 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7510 for (inner = region->inner, casei = 1;
7511 inner;
7512 inner = inner->next, i++, casei++)
7514 basic_block s_entry_bb, s_exit_bb;
7516 /* Skip optional reduction region. */
7517 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7519 --i;
7520 --casei;
7521 continue;
7524 s_entry_bb = inner->entry;
7525 s_exit_bb = inner->exit;
7527 t = gimple_block_label (s_entry_bb);
7528 u = build_int_cst (unsigned_type_node, casei);
7529 u = build_case_label (u, NULL, t);
7530 label_vec.quick_push (u);
7532 si = gsi_last_bb (s_entry_bb);
7533 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7534 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7535 gsi_remove (&si, true);
7536 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7538 if (s_exit_bb == NULL)
7539 continue;
7541 si = gsi_last_bb (s_exit_bb);
7542 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7543 gsi_remove (&si, true);
7545 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7548 /* Error handling code goes in DEFAULT_BB. */
7549 t = gimple_block_label (default_bb);
7550 u = build_case_label (NULL, NULL, t);
7551 make_edge (l0_bb, default_bb, 0);
7552 add_bb_to_loop (default_bb, current_loops->tree_root);
7554 stmt = gimple_build_switch (vmain, u, label_vec);
7555 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7556 gsi_remove (&switch_si, true);
7558 si = gsi_start_bb (default_bb);
7559 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7560 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7562 if (exit_reachable)
7564 tree bfn_decl;
7566 /* Code to get the next section goes in L1_BB. */
7567 si = gsi_last_bb (l1_bb);
7568 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7570 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7571 stmt = gimple_build_call (bfn_decl, 0);
7572 gimple_call_set_lhs (stmt, vnext);
7573 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7574 gsi_remove (&si, true);
7576 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7579 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7580 si = gsi_last_bb (l2_bb);
7581 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7582 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7583 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7584 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7585 else
7586 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7587 stmt = gimple_build_call (t, 0);
7588 if (gimple_omp_return_lhs (gsi_stmt (si)))
7589 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7590 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7591 gsi_remove (&si, true);
7593 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7597 /* Expand code for an OpenMP single directive. We've already expanded
7598 much of the code, here we simply place the GOMP_barrier call. */
7600 static void
7601 expand_omp_single (struct omp_region *region)
7603 basic_block entry_bb, exit_bb;
7604 gimple_stmt_iterator si;
7606 entry_bb = region->entry;
7607 exit_bb = region->exit;
7609 si = gsi_last_bb (entry_bb);
7610 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7611 gsi_remove (&si, true);
7612 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7614 si = gsi_last_bb (exit_bb);
7615 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7617 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7618 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7620 gsi_remove (&si, true);
7621 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7625 /* Generic expansion for OpenMP synchronization directives: master,
7626 ordered and critical. All we need to do here is remove the entry
7627 and exit markers for REGION. */
7629 static void
7630 expand_omp_synch (struct omp_region *region)
7632 basic_block entry_bb, exit_bb;
7633 gimple_stmt_iterator si;
7635 entry_bb = region->entry;
7636 exit_bb = region->exit;
7638 si = gsi_last_bb (entry_bb);
7639 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7640 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7641 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7642 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7643 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7644 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7645 gsi_remove (&si, true);
7646 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7648 if (exit_bb)
7650 si = gsi_last_bb (exit_bb);
7651 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7652 gsi_remove (&si, true);
7653 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7657 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7658 operation as a normal volatile load. */
7660 static bool
7661 expand_omp_atomic_load (basic_block load_bb, tree addr,
7662 tree loaded_val, int index)
7664 enum built_in_function tmpbase;
7665 gimple_stmt_iterator gsi;
7666 basic_block store_bb;
7667 location_t loc;
7668 gimple stmt;
7669 tree decl, call, type, itype;
7671 gsi = gsi_last_bb (load_bb);
7672 stmt = gsi_stmt (gsi);
7673 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7674 loc = gimple_location (stmt);
7676 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7677 is smaller than word size, then expand_atomic_load assumes that the load
7678 is atomic. We could avoid the builtin entirely in this case. */
7680 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7681 decl = builtin_decl_explicit (tmpbase);
7682 if (decl == NULL_TREE)
7683 return false;
7685 type = TREE_TYPE (loaded_val);
7686 itype = TREE_TYPE (TREE_TYPE (decl));
7688 call = build_call_expr_loc (loc, decl, 2, addr,
7689 build_int_cst (NULL,
7690 gimple_omp_atomic_seq_cst_p (stmt)
7691 ? MEMMODEL_SEQ_CST
7692 : MEMMODEL_RELAXED));
7693 if (!useless_type_conversion_p (type, itype))
7694 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7695 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7697 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7698 gsi_remove (&gsi, true);
7700 store_bb = single_succ (load_bb);
7701 gsi = gsi_last_bb (store_bb);
7702 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7703 gsi_remove (&gsi, true);
7705 if (gimple_in_ssa_p (cfun))
7706 update_ssa (TODO_update_ssa_no_phi);
7708 return true;
7711 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7712 operation as a normal volatile store. */
7714 static bool
7715 expand_omp_atomic_store (basic_block load_bb, tree addr,
7716 tree loaded_val, tree stored_val, int index)
7718 enum built_in_function tmpbase;
7719 gimple_stmt_iterator gsi;
7720 basic_block store_bb = single_succ (load_bb);
7721 location_t loc;
7722 gimple stmt;
7723 tree decl, call, type, itype;
7724 enum machine_mode imode;
7725 bool exchange;
7727 gsi = gsi_last_bb (load_bb);
7728 stmt = gsi_stmt (gsi);
7729 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7731 /* If the load value is needed, then this isn't a store but an exchange. */
7732 exchange = gimple_omp_atomic_need_value_p (stmt);
7734 gsi = gsi_last_bb (store_bb);
7735 stmt = gsi_stmt (gsi);
7736 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7737 loc = gimple_location (stmt);
7739 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7740 is smaller than word size, then expand_atomic_store assumes that the store
7741 is atomic. We could avoid the builtin entirely in this case. */
7743 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7744 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7745 decl = builtin_decl_explicit (tmpbase);
7746 if (decl == NULL_TREE)
7747 return false;
7749 type = TREE_TYPE (stored_val);
7751 /* Dig out the type of the function's second argument. */
7752 itype = TREE_TYPE (decl);
7753 itype = TYPE_ARG_TYPES (itype);
7754 itype = TREE_CHAIN (itype);
7755 itype = TREE_VALUE (itype);
7756 imode = TYPE_MODE (itype);
7758 if (exchange && !can_atomic_exchange_p (imode, true))
7759 return false;
7761 if (!useless_type_conversion_p (itype, type))
7762 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7763 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7764 build_int_cst (NULL,
7765 gimple_omp_atomic_seq_cst_p (stmt)
7766 ? MEMMODEL_SEQ_CST
7767 : MEMMODEL_RELAXED));
7768 if (exchange)
7770 if (!useless_type_conversion_p (type, itype))
7771 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7772 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7775 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7776 gsi_remove (&gsi, true);
7778 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7779 gsi = gsi_last_bb (load_bb);
7780 gsi_remove (&gsi, true);
7782 if (gimple_in_ssa_p (cfun))
7783 update_ssa (TODO_update_ssa_no_phi);
7785 return true;
7788 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7789 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7790 size of the data type, and thus usable to find the index of the builtin
7791 decl. Returns false if the expression is not of the proper form. */
7793 static bool
7794 expand_omp_atomic_fetch_op (basic_block load_bb,
7795 tree addr, tree loaded_val,
7796 tree stored_val, int index)
7798 enum built_in_function oldbase, newbase, tmpbase;
7799 tree decl, itype, call;
7800 tree lhs, rhs;
7801 basic_block store_bb = single_succ (load_bb);
7802 gimple_stmt_iterator gsi;
7803 gimple stmt;
7804 location_t loc;
7805 enum tree_code code;
7806 bool need_old, need_new;
7807 enum machine_mode imode;
7808 bool seq_cst;
7810 /* We expect to find the following sequences:
7812 load_bb:
7813 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7815 store_bb:
7816 val = tmp OP something; (or: something OP tmp)
7817 GIMPLE_OMP_STORE (val)
7819 ???FIXME: Allow a more flexible sequence.
7820 Perhaps use data flow to pick the statements.
7824 gsi = gsi_after_labels (store_bb);
7825 stmt = gsi_stmt (gsi);
7826 loc = gimple_location (stmt);
7827 if (!is_gimple_assign (stmt))
7828 return false;
7829 gsi_next (&gsi);
7830 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7831 return false;
7832 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7833 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7834 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7835 gcc_checking_assert (!need_old || !need_new);
7837 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7838 return false;
7840 /* Check for one of the supported fetch-op operations. */
7841 code = gimple_assign_rhs_code (stmt);
7842 switch (code)
7844 case PLUS_EXPR:
7845 case POINTER_PLUS_EXPR:
7846 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7847 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7848 break;
7849 case MINUS_EXPR:
7850 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7851 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7852 break;
7853 case BIT_AND_EXPR:
7854 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7855 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7856 break;
7857 case BIT_IOR_EXPR:
7858 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7859 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7860 break;
7861 case BIT_XOR_EXPR:
7862 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7863 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7864 break;
7865 default:
7866 return false;
7869 /* Make sure the expression is of the proper form. */
7870 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7871 rhs = gimple_assign_rhs2 (stmt);
7872 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7873 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7874 rhs = gimple_assign_rhs1 (stmt);
7875 else
7876 return false;
7878 tmpbase = ((enum built_in_function)
7879 ((need_new ? newbase : oldbase) + index + 1));
7880 decl = builtin_decl_explicit (tmpbase);
7881 if (decl == NULL_TREE)
7882 return false;
7883 itype = TREE_TYPE (TREE_TYPE (decl));
7884 imode = TYPE_MODE (itype);
7886 /* We could test all of the various optabs involved, but the fact of the
7887 matter is that (with the exception of i486 vs i586 and xadd) all targets
7888 that support any atomic operaton optab also implements compare-and-swap.
7889 Let optabs.c take care of expanding any compare-and-swap loop. */
7890 if (!can_compare_and_swap_p (imode, true))
7891 return false;
7893 gsi = gsi_last_bb (load_bb);
7894 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7896 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7897 It only requires that the operation happen atomically. Thus we can
7898 use the RELAXED memory model. */
7899 call = build_call_expr_loc (loc, decl, 3, addr,
7900 fold_convert_loc (loc, itype, rhs),
7901 build_int_cst (NULL,
7902 seq_cst ? MEMMODEL_SEQ_CST
7903 : MEMMODEL_RELAXED));
7905 if (need_old || need_new)
7907 lhs = need_old ? loaded_val : stored_val;
7908 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7909 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7911 else
7912 call = fold_convert_loc (loc, void_type_node, call);
7913 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7914 gsi_remove (&gsi, true);
7916 gsi = gsi_last_bb (store_bb);
7917 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7918 gsi_remove (&gsi, true);
7919 gsi = gsi_last_bb (store_bb);
7920 gsi_remove (&gsi, true);
7922 if (gimple_in_ssa_p (cfun))
7923 update_ssa (TODO_update_ssa_no_phi);
7925 return true;
7928 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7930 oldval = *addr;
7931 repeat:
7932 newval = rhs; // with oldval replacing *addr in rhs
7933 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7934 if (oldval != newval)
7935 goto repeat;
7937 INDEX is log2 of the size of the data type, and thus usable to find the
7938 index of the builtin decl. */
7940 static bool
7941 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7942 tree addr, tree loaded_val, tree stored_val,
7943 int index)
7945 tree loadedi, storedi, initial, new_storedi, old_vali;
7946 tree type, itype, cmpxchg, iaddr;
7947 gimple_stmt_iterator si;
7948 basic_block loop_header = single_succ (load_bb);
7949 gimple phi, stmt;
7950 edge e;
7951 enum built_in_function fncode;
7953 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7954 order to use the RELAXED memory model effectively. */
7955 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7956 + index + 1);
7957 cmpxchg = builtin_decl_explicit (fncode);
7958 if (cmpxchg == NULL_TREE)
7959 return false;
7960 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7961 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7963 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7964 return false;
7966 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7967 si = gsi_last_bb (load_bb);
7968 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7970 /* For floating-point values, we'll need to view-convert them to integers
7971 so that we can perform the atomic compare and swap. Simplify the
7972 following code by always setting up the "i"ntegral variables. */
7973 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7975 tree iaddr_val;
7977 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7978 true), NULL);
7979 iaddr_val
7980 = force_gimple_operand_gsi (&si,
7981 fold_convert (TREE_TYPE (iaddr), addr),
7982 false, NULL_TREE, true, GSI_SAME_STMT);
7983 stmt = gimple_build_assign (iaddr, iaddr_val);
7984 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7985 loadedi = create_tmp_var (itype, NULL);
7986 if (gimple_in_ssa_p (cfun))
7987 loadedi = make_ssa_name (loadedi, NULL);
7989 else
7991 iaddr = addr;
7992 loadedi = loaded_val;
7995 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7996 tree loaddecl = builtin_decl_explicit (fncode);
7997 if (loaddecl)
7998 initial
7999 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8000 build_call_expr (loaddecl, 2, iaddr,
8001 build_int_cst (NULL_TREE,
8002 MEMMODEL_RELAXED)));
8003 else
8004 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8005 build_int_cst (TREE_TYPE (iaddr), 0));
8007 initial
8008 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8009 GSI_SAME_STMT);
8011 /* Move the value to the LOADEDI temporary. */
8012 if (gimple_in_ssa_p (cfun))
8014 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8015 phi = create_phi_node (loadedi, loop_header);
8016 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8017 initial);
8019 else
8020 gsi_insert_before (&si,
8021 gimple_build_assign (loadedi, initial),
8022 GSI_SAME_STMT);
8023 if (loadedi != loaded_val)
8025 gimple_stmt_iterator gsi2;
8026 tree x;
8028 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8029 gsi2 = gsi_start_bb (loop_header);
8030 if (gimple_in_ssa_p (cfun))
8032 gimple stmt;
8033 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8034 true, GSI_SAME_STMT);
8035 stmt = gimple_build_assign (loaded_val, x);
8036 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8038 else
8040 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8041 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8042 true, GSI_SAME_STMT);
8045 gsi_remove (&si, true);
8047 si = gsi_last_bb (store_bb);
8048 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8050 if (iaddr == addr)
8051 storedi = stored_val;
8052 else
8053 storedi =
8054 force_gimple_operand_gsi (&si,
8055 build1 (VIEW_CONVERT_EXPR, itype,
8056 stored_val), true, NULL_TREE, true,
8057 GSI_SAME_STMT);
8059 /* Build the compare&swap statement. */
8060 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8061 new_storedi = force_gimple_operand_gsi (&si,
8062 fold_convert (TREE_TYPE (loadedi),
8063 new_storedi),
8064 true, NULL_TREE,
8065 true, GSI_SAME_STMT);
8067 if (gimple_in_ssa_p (cfun))
8068 old_vali = loadedi;
8069 else
8071 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
8072 stmt = gimple_build_assign (old_vali, loadedi);
8073 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8075 stmt = gimple_build_assign (loadedi, new_storedi);
8076 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8079 /* Note that we always perform the comparison as an integer, even for
8080 floating point. This allows the atomic operation to properly
8081 succeed even with NaNs and -0.0. */
8082 stmt = gimple_build_cond_empty
8083 (build2 (NE_EXPR, boolean_type_node,
8084 new_storedi, old_vali));
8085 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8087 /* Update cfg. */
8088 e = single_succ_edge (store_bb);
8089 e->flags &= ~EDGE_FALLTHRU;
8090 e->flags |= EDGE_FALSE_VALUE;
8092 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8094 /* Copy the new value to loadedi (we already did that before the condition
8095 if we are not in SSA). */
8096 if (gimple_in_ssa_p (cfun))
8098 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8099 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8102 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8103 gsi_remove (&si, true);
8105 struct loop *loop = alloc_loop ();
8106 loop->header = loop_header;
8107 loop->latch = store_bb;
8108 add_loop (loop, loop_header->loop_father);
8110 if (gimple_in_ssa_p (cfun))
8111 update_ssa (TODO_update_ssa_no_phi);
8113 return true;
8116 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8118 GOMP_atomic_start ();
8119 *addr = rhs;
8120 GOMP_atomic_end ();
8122 The result is not globally atomic, but works so long as all parallel
8123 references are within #pragma omp atomic directives. According to
8124 responses received from omp@openmp.org, appears to be within spec.
8125 Which makes sense, since that's how several other compilers handle
8126 this situation as well.
8127 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8128 expanding. STORED_VAL is the operand of the matching
8129 GIMPLE_OMP_ATOMIC_STORE.
8131 We replace
8132 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8133 loaded_val = *addr;
8135 and replace
8136 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8137 *addr = stored_val;
8140 static bool
8141 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8142 tree addr, tree loaded_val, tree stored_val)
8144 gimple_stmt_iterator si;
8145 gimple stmt;
8146 tree t;
8148 si = gsi_last_bb (load_bb);
8149 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8151 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8152 t = build_call_expr (t, 0);
8153 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8155 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8156 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8157 gsi_remove (&si, true);
8159 si = gsi_last_bb (store_bb);
8160 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8162 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8163 stored_val);
8164 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8166 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8167 t = build_call_expr (t, 0);
8168 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8169 gsi_remove (&si, true);
8171 if (gimple_in_ssa_p (cfun))
8172 update_ssa (TODO_update_ssa_no_phi);
8173 return true;
8176 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8177 using expand_omp_atomic_fetch_op. If it failed, we try to
8178 call expand_omp_atomic_pipeline, and if it fails too, the
8179 ultimate fallback is wrapping the operation in a mutex
8180 (expand_omp_atomic_mutex). REGION is the atomic region built
8181 by build_omp_regions_1(). */
8183 static void
8184 expand_omp_atomic (struct omp_region *region)
8186 basic_block load_bb = region->entry, store_bb = region->exit;
8187 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
8188 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8189 tree addr = gimple_omp_atomic_load_rhs (load);
8190 tree stored_val = gimple_omp_atomic_store_val (store);
8191 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8192 HOST_WIDE_INT index;
8194 /* Make sure the type is one of the supported sizes. */
8195 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8196 index = exact_log2 (index);
8197 if (index >= 0 && index <= 4)
8199 unsigned int align = TYPE_ALIGN_UNIT (type);
8201 /* __sync builtins require strict data alignment. */
8202 if (exact_log2 (align) >= index)
8204 /* Atomic load. */
8205 if (loaded_val == stored_val
8206 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8207 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8208 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8209 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8210 return;
8212 /* Atomic store. */
8213 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8214 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8215 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8216 && store_bb == single_succ (load_bb)
8217 && first_stmt (store_bb) == store
8218 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8219 stored_val, index))
8220 return;
8222 /* When possible, use specialized atomic update functions. */
8223 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8224 && store_bb == single_succ (load_bb)
8225 && expand_omp_atomic_fetch_op (load_bb, addr,
8226 loaded_val, stored_val, index))
8227 return;
8229 /* If we don't have specialized __sync builtins, try and implement
8230 as a compare and swap loop. */
8231 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8232 loaded_val, stored_val, index))
8233 return;
8237 /* The ultimate fallback is wrapping the operation in a mutex. */
8238 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8242 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
8244 static void
8245 expand_omp_target (struct omp_region *region)
8247 basic_block entry_bb, exit_bb, new_bb;
8248 struct function *child_cfun = NULL;
8249 tree child_fn = NULL_TREE, block, t;
8250 gimple_stmt_iterator gsi;
8251 gimple entry_stmt, stmt;
8252 edge e;
8254 entry_stmt = last_stmt (region->entry);
8255 new_bb = region->entry;
8256 int kind = gimple_omp_target_kind (entry_stmt);
8257 if (kind == GF_OMP_TARGET_KIND_REGION)
8259 child_fn = gimple_omp_target_child_fn (entry_stmt);
8260 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8263 entry_bb = region->entry;
8264 exit_bb = region->exit;
8266 if (kind == GF_OMP_TARGET_KIND_REGION)
8268 unsigned srcidx, dstidx, num;
8270 /* If the target region needs data sent from the parent
8271 function, then the very first statement (except possible
8272 tree profile counter updates) of the parallel body
8273 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8274 &.OMP_DATA_O is passed as an argument to the child function,
8275 we need to replace it with the argument as seen by the child
8276 function.
8278 In most cases, this will end up being the identity assignment
8279 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8280 a function call that has been inlined, the original PARM_DECL
8281 .OMP_DATA_I may have been converted into a different local
8282 variable. In which case, we need to keep the assignment. */
8283 if (gimple_omp_target_data_arg (entry_stmt))
8285 basic_block entry_succ_bb = single_succ (entry_bb);
8286 gimple_stmt_iterator gsi;
8287 tree arg;
8288 gimple tgtcopy_stmt = NULL;
8289 tree sender
8290 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
8292 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8294 gcc_assert (!gsi_end_p (gsi));
8295 stmt = gsi_stmt (gsi);
8296 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8297 continue;
8299 if (gimple_num_ops (stmt) == 2)
8301 tree arg = gimple_assign_rhs1 (stmt);
8303 /* We're ignoring the subcode because we're
8304 effectively doing a STRIP_NOPS. */
8306 if (TREE_CODE (arg) == ADDR_EXPR
8307 && TREE_OPERAND (arg, 0) == sender)
8309 tgtcopy_stmt = stmt;
8310 break;
8315 gcc_assert (tgtcopy_stmt != NULL);
8316 arg = DECL_ARGUMENTS (child_fn);
8318 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8319 gsi_remove (&gsi, true);
8322 /* Declare local variables needed in CHILD_CFUN. */
8323 block = DECL_INITIAL (child_fn);
8324 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8325 /* The gimplifier could record temporaries in target block
8326 rather than in containing function's local_decls chain,
8327 which would mean cgraph missed finalizing them. Do it now. */
8328 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8329 if (TREE_CODE (t) == VAR_DECL
8330 && TREE_STATIC (t)
8331 && !DECL_EXTERNAL (t))
8332 varpool_node::finalize_decl (t);
8333 DECL_SAVED_TREE (child_fn) = NULL;
8334 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8335 gimple_set_body (child_fn, NULL);
8336 TREE_USED (block) = 1;
8338 /* Reset DECL_CONTEXT on function arguments. */
8339 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8340 DECL_CONTEXT (t) = child_fn;
8342 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8343 so that it can be moved to the child function. */
8344 gsi = gsi_last_bb (entry_bb);
8345 stmt = gsi_stmt (gsi);
8346 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
8347 && gimple_omp_target_kind (stmt)
8348 == GF_OMP_TARGET_KIND_REGION);
8349 gsi_remove (&gsi, true);
8350 e = split_block (entry_bb, stmt);
8351 entry_bb = e->dest;
8352 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8354 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8355 if (exit_bb)
8357 gsi = gsi_last_bb (exit_bb);
8358 gcc_assert (!gsi_end_p (gsi)
8359 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8360 stmt = gimple_build_return (NULL);
8361 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8362 gsi_remove (&gsi, true);
8365 /* Move the target region into CHILD_CFUN. */
8367 block = gimple_block (entry_stmt);
8369 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8370 if (exit_bb)
8371 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8372 /* When the OMP expansion process cannot guarantee an up-to-date
8373 loop tree arrange for the child function to fixup loops. */
8374 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8375 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8377 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8378 num = vec_safe_length (child_cfun->local_decls);
8379 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8381 t = (*child_cfun->local_decls)[srcidx];
8382 if (DECL_CONTEXT (t) == cfun->decl)
8383 continue;
8384 if (srcidx != dstidx)
8385 (*child_cfun->local_decls)[dstidx] = t;
8386 dstidx++;
8388 if (dstidx != num)
8389 vec_safe_truncate (child_cfun->local_decls, dstidx);
8391 /* Inform the callgraph about the new function. */
8392 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8393 cgraph_node::add_new_function (child_fn, true);
8395 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8396 fixed in a following pass. */
8397 push_cfun (child_cfun);
8398 cgraph_edge::rebuild_edges ();
8400 /* Some EH regions might become dead, see PR34608. If
8401 pass_cleanup_cfg isn't the first pass to happen with the
8402 new child, these dead EH edges might cause problems.
8403 Clean them up now. */
8404 if (flag_exceptions)
8406 basic_block bb;
8407 bool changed = false;
8409 FOR_EACH_BB_FN (bb, cfun)
8410 changed |= gimple_purge_dead_eh_edges (bb);
8411 if (changed)
8412 cleanup_tree_cfg ();
8414 pop_cfun ();
8417 /* Emit a library call to launch the target region, or do data
8418 transfers. */
8419 tree t1, t2, t3, t4, device, cond, c, clauses;
8420 enum built_in_function start_ix;
8421 location_t clause_loc;
8423 clauses = gimple_omp_target_clauses (entry_stmt);
8425 if (kind == GF_OMP_TARGET_KIND_REGION)
8426 start_ix = BUILT_IN_GOMP_TARGET;
8427 else if (kind == GF_OMP_TARGET_KIND_DATA)
8428 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8429 else
8430 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8432 /* By default, the value of DEVICE is -1 (let runtime library choose)
8433 and there is no conditional. */
8434 cond = NULL_TREE;
8435 device = build_int_cst (integer_type_node, -1);
8437 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8438 if (c)
8439 cond = OMP_CLAUSE_IF_EXPR (c);
8441 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8442 if (c)
8444 device = OMP_CLAUSE_DEVICE_ID (c);
8445 clause_loc = OMP_CLAUSE_LOCATION (c);
8447 else
8448 clause_loc = gimple_location (entry_stmt);
8450 /* Ensure 'device' is of the correct type. */
8451 device = fold_convert_loc (clause_loc, integer_type_node, device);
8453 /* If we found the clause 'if (cond)', build
8454 (cond ? device : -2). */
8455 if (cond)
8457 cond = gimple_boolify (cond);
8459 basic_block cond_bb, then_bb, else_bb;
8460 edge e;
8461 tree tmp_var;
8463 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8464 if (kind != GF_OMP_TARGET_KIND_REGION)
8466 gsi = gsi_last_bb (new_bb);
8467 gsi_prev (&gsi);
8468 e = split_block (new_bb, gsi_stmt (gsi));
8470 else
8471 e = split_block (new_bb, NULL);
8472 cond_bb = e->src;
8473 new_bb = e->dest;
8474 remove_edge (e);
8476 then_bb = create_empty_bb (cond_bb);
8477 else_bb = create_empty_bb (then_bb);
8478 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8479 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8481 stmt = gimple_build_cond_empty (cond);
8482 gsi = gsi_last_bb (cond_bb);
8483 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8485 gsi = gsi_start_bb (then_bb);
8486 stmt = gimple_build_assign (tmp_var, device);
8487 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8489 gsi = gsi_start_bb (else_bb);
8490 stmt = gimple_build_assign (tmp_var,
8491 build_int_cst (integer_type_node, -2));
8492 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8494 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8495 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8496 add_bb_to_loop (then_bb, cond_bb->loop_father);
8497 add_bb_to_loop (else_bb, cond_bb->loop_father);
8498 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8499 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8501 device = tmp_var;
8504 gsi = gsi_last_bb (new_bb);
8505 t = gimple_omp_target_data_arg (entry_stmt);
8506 if (t == NULL)
8508 t1 = size_zero_node;
8509 t2 = build_zero_cst (ptr_type_node);
8510 t3 = t2;
8511 t4 = t2;
8513 else
8515 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8516 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8517 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8518 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8519 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8522 gimple g;
8523 /* FIXME: This will be address of
8524 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8525 symbol, as soon as the linker plugin is able to create it for us. */
8526 tree openmp_target = build_zero_cst (ptr_type_node);
8527 if (kind == GF_OMP_TARGET_KIND_REGION)
8529 tree fnaddr = build_fold_addr_expr (child_fn);
8530 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8531 device, fnaddr, openmp_target, t1, t2, t3, t4);
8533 else
8534 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8535 device, openmp_target, t1, t2, t3, t4);
8536 gimple_set_location (g, gimple_location (entry_stmt));
8537 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8538 if (kind != GF_OMP_TARGET_KIND_REGION)
8540 g = gsi_stmt (gsi);
8541 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8542 gsi_remove (&gsi, true);
8544 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8546 gsi = gsi_last_bb (region->exit);
8547 g = gsi_stmt (gsi);
8548 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8549 gsi_remove (&gsi, true);
8554 /* Expand the parallel region tree rooted at REGION. Expansion
8555 proceeds in depth-first order. Innermost regions are expanded
8556 first. This way, parallel regions that require a new function to
8557 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8558 internal dependencies in their body. */
8560 static void
8561 expand_omp (struct omp_region *region)
8563 while (region)
8565 location_t saved_location;
8566 gimple inner_stmt = NULL;
8568 /* First, determine whether this is a combined parallel+workshare
8569 region. */
8570 if (region->type == GIMPLE_OMP_PARALLEL)
8571 determine_parallel_type (region);
8573 if (region->type == GIMPLE_OMP_FOR
8574 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8575 inner_stmt = last_stmt (region->inner->entry);
8577 if (region->inner)
8578 expand_omp (region->inner);
8580 saved_location = input_location;
8581 if (gimple_has_location (last_stmt (region->entry)))
8582 input_location = gimple_location (last_stmt (region->entry));
8584 switch (region->type)
8586 case GIMPLE_OMP_PARALLEL:
8587 case GIMPLE_OMP_TASK:
8588 expand_omp_taskreg (region);
8589 break;
8591 case GIMPLE_OMP_FOR:
8592 expand_omp_for (region, inner_stmt);
8593 break;
8595 case GIMPLE_OMP_SECTIONS:
8596 expand_omp_sections (region);
8597 break;
8599 case GIMPLE_OMP_SECTION:
8600 /* Individual omp sections are handled together with their
8601 parent GIMPLE_OMP_SECTIONS region. */
8602 break;
8604 case GIMPLE_OMP_SINGLE:
8605 expand_omp_single (region);
8606 break;
8608 case GIMPLE_OMP_MASTER:
8609 case GIMPLE_OMP_TASKGROUP:
8610 case GIMPLE_OMP_ORDERED:
8611 case GIMPLE_OMP_CRITICAL:
8612 case GIMPLE_OMP_TEAMS:
8613 expand_omp_synch (region);
8614 break;
8616 case GIMPLE_OMP_ATOMIC_LOAD:
8617 expand_omp_atomic (region);
8618 break;
8620 case GIMPLE_OMP_TARGET:
8621 expand_omp_target (region);
8622 break;
8624 default:
8625 gcc_unreachable ();
8628 input_location = saved_location;
8629 region = region->next;
8634 /* Helper for build_omp_regions. Scan the dominator tree starting at
8635 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8636 true, the function ends once a single tree is built (otherwise, whole
8637 forest of OMP constructs may be built). */
8639 static void
8640 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8641 bool single_tree)
8643 gimple_stmt_iterator gsi;
8644 gimple stmt;
8645 basic_block son;
8647 gsi = gsi_last_bb (bb);
8648 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8650 struct omp_region *region;
8651 enum gimple_code code;
8653 stmt = gsi_stmt (gsi);
8654 code = gimple_code (stmt);
8655 if (code == GIMPLE_OMP_RETURN)
8657 /* STMT is the return point out of region PARENT. Mark it
8658 as the exit point and make PARENT the immediately
8659 enclosing region. */
8660 gcc_assert (parent);
8661 region = parent;
8662 region->exit = bb;
8663 parent = parent->outer;
8665 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8667 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8668 GIMPLE_OMP_RETURN, but matches with
8669 GIMPLE_OMP_ATOMIC_LOAD. */
8670 gcc_assert (parent);
8671 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8672 region = parent;
8673 region->exit = bb;
8674 parent = parent->outer;
8677 else if (code == GIMPLE_OMP_CONTINUE)
8679 gcc_assert (parent);
8680 parent->cont = bb;
8682 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8684 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8685 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8688 else if (code == GIMPLE_OMP_TARGET
8689 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8690 new_omp_region (bb, code, parent);
8691 else
8693 /* Otherwise, this directive becomes the parent for a new
8694 region. */
8695 region = new_omp_region (bb, code, parent);
8696 parent = region;
8700 if (single_tree && !parent)
8701 return;
8703 for (son = first_dom_son (CDI_DOMINATORS, bb);
8704 son;
8705 son = next_dom_son (CDI_DOMINATORS, son))
8706 build_omp_regions_1 (son, parent, single_tree);
8709 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8710 root_omp_region. */
8712 static void
8713 build_omp_regions_root (basic_block root)
8715 gcc_assert (root_omp_region == NULL);
8716 build_omp_regions_1 (root, NULL, true);
8717 gcc_assert (root_omp_region != NULL);
8720 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8722 void
8723 omp_expand_local (basic_block head)
8725 build_omp_regions_root (head);
8726 if (dump_file && (dump_flags & TDF_DETAILS))
8728 fprintf (dump_file, "\nOMP region tree\n\n");
8729 dump_omp_region (dump_file, root_omp_region, 0);
8730 fprintf (dump_file, "\n");
8733 remove_exit_barriers (root_omp_region);
8734 expand_omp (root_omp_region);
8736 free_omp_regions ();
8739 /* Scan the CFG and build a tree of OMP regions. Return the root of
8740 the OMP region tree. */
8742 static void
8743 build_omp_regions (void)
8745 gcc_assert (root_omp_region == NULL);
8746 calculate_dominance_info (CDI_DOMINATORS);
8747 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8750 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8752 static unsigned int
8753 execute_expand_omp (void)
8755 build_omp_regions ();
8757 if (!root_omp_region)
8758 return 0;
8760 if (dump_file)
8762 fprintf (dump_file, "\nOMP region tree\n\n");
8763 dump_omp_region (dump_file, root_omp_region, 0);
8764 fprintf (dump_file, "\n");
8767 remove_exit_barriers (root_omp_region);
8769 expand_omp (root_omp_region);
8771 cleanup_tree_cfg ();
8773 free_omp_regions ();
8775 return 0;
8778 /* OMP expansion -- the default pass, run before creation of SSA form. */
8780 namespace {
8782 const pass_data pass_data_expand_omp =
8784 GIMPLE_PASS, /* type */
8785 "ompexp", /* name */
8786 OPTGROUP_NONE, /* optinfo_flags */
8787 TV_NONE, /* tv_id */
8788 PROP_gimple_any, /* properties_required */
8789 0, /* properties_provided */
8790 0, /* properties_destroyed */
8791 0, /* todo_flags_start */
8792 0, /* todo_flags_finish */
8795 class pass_expand_omp : public gimple_opt_pass
8797 public:
8798 pass_expand_omp (gcc::context *ctxt)
8799 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8802 /* opt_pass methods: */
8803 virtual bool gate (function *)
8805 return ((flag_openmp != 0 || flag_openmp_simd != 0
8806 || flag_cilkplus != 0) && !seen_error ());
8809 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8811 }; // class pass_expand_omp
8813 } // anon namespace
8815 gimple_opt_pass *
8816 make_pass_expand_omp (gcc::context *ctxt)
8818 return new pass_expand_omp (ctxt);
8821 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8823 /* If ctx is a worksharing context inside of a cancellable parallel
8824 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8825 and conditional branch to parallel's cancel_label to handle
8826 cancellation in the implicit barrier. */
8828 static void
8829 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8831 gimple omp_return = gimple_seq_last_stmt (*body);
8832 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8833 if (gimple_omp_return_nowait_p (omp_return))
8834 return;
8835 if (ctx->outer
8836 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8837 && ctx->outer->cancellable)
8839 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8840 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8841 tree lhs = create_tmp_var (c_bool_type, NULL);
8842 gimple_omp_return_set_lhs (omp_return, lhs);
8843 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8844 gimple g = gimple_build_cond (NE_EXPR, lhs,
8845 fold_convert (c_bool_type,
8846 boolean_false_node),
8847 ctx->outer->cancel_label, fallthru_label);
8848 gimple_seq_add_stmt (body, g);
8849 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8853 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8854 CTX is the enclosing OMP context for the current statement. */
8856 static void
8857 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8859 tree block, control;
8860 gimple_stmt_iterator tgsi;
8861 gimple stmt, new_stmt, bind, t;
8862 gimple_seq ilist, dlist, olist, new_body;
8864 stmt = gsi_stmt (*gsi_p);
8866 push_gimplify_context ();
8868 dlist = NULL;
8869 ilist = NULL;
8870 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8871 &ilist, &dlist, ctx, NULL);
8873 new_body = gimple_omp_body (stmt);
8874 gimple_omp_set_body (stmt, NULL);
8875 tgsi = gsi_start (new_body);
8876 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8878 omp_context *sctx;
8879 gimple sec_start;
8881 sec_start = gsi_stmt (tgsi);
8882 sctx = maybe_lookup_ctx (sec_start);
8883 gcc_assert (sctx);
8885 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8886 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8887 GSI_CONTINUE_LINKING);
8888 gimple_omp_set_body (sec_start, NULL);
8890 if (gsi_one_before_end_p (tgsi))
8892 gimple_seq l = NULL;
8893 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8894 &l, ctx);
8895 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8896 gimple_omp_section_set_last (sec_start);
8899 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8900 GSI_CONTINUE_LINKING);
8903 block = make_node (BLOCK);
8904 bind = gimple_build_bind (NULL, new_body, block);
8906 olist = NULL;
8907 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8909 block = make_node (BLOCK);
8910 new_stmt = gimple_build_bind (NULL, NULL, block);
8911 gsi_replace (gsi_p, new_stmt, true);
8913 pop_gimplify_context (new_stmt);
8914 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8915 BLOCK_VARS (block) = gimple_bind_vars (bind);
8916 if (BLOCK_VARS (block))
8917 TREE_USED (block) = 1;
8919 new_body = NULL;
8920 gimple_seq_add_seq (&new_body, ilist);
8921 gimple_seq_add_stmt (&new_body, stmt);
8922 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8923 gimple_seq_add_stmt (&new_body, bind);
8925 control = create_tmp_var (unsigned_type_node, ".section");
8926 t = gimple_build_omp_continue (control, control);
8927 gimple_omp_sections_set_control (stmt, control);
8928 gimple_seq_add_stmt (&new_body, t);
8930 gimple_seq_add_seq (&new_body, olist);
8931 if (ctx->cancellable)
8932 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8933 gimple_seq_add_seq (&new_body, dlist);
8935 new_body = maybe_catch_exception (new_body);
8937 t = gimple_build_omp_return
8938 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8939 OMP_CLAUSE_NOWAIT));
8940 gimple_seq_add_stmt (&new_body, t);
8941 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8943 gimple_bind_set_body (new_stmt, new_body);
8947 /* A subroutine of lower_omp_single. Expand the simple form of
8948 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8950 if (GOMP_single_start ())
8951 BODY;
8952 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8954 FIXME. It may be better to delay expanding the logic of this until
8955 pass_expand_omp. The expanded logic may make the job more difficult
8956 to a synchronization analysis pass. */
8958 static void
8959 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8961 location_t loc = gimple_location (single_stmt);
8962 tree tlabel = create_artificial_label (loc);
8963 tree flabel = create_artificial_label (loc);
8964 gimple call, cond;
8965 tree lhs, decl;
8967 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8968 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8969 call = gimple_build_call (decl, 0);
8970 gimple_call_set_lhs (call, lhs);
8971 gimple_seq_add_stmt (pre_p, call);
8973 cond = gimple_build_cond (EQ_EXPR, lhs,
8974 fold_convert_loc (loc, TREE_TYPE (lhs),
8975 boolean_true_node),
8976 tlabel, flabel);
8977 gimple_seq_add_stmt (pre_p, cond);
8978 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8979 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8980 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8984 /* A subroutine of lower_omp_single. Expand the simple form of
8985 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8987 #pragma omp single copyprivate (a, b, c)
8989 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8992 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8994 BODY;
8995 copyout.a = a;
8996 copyout.b = b;
8997 copyout.c = c;
8998 GOMP_single_copy_end (&copyout);
9000 else
9002 a = copyout_p->a;
9003 b = copyout_p->b;
9004 c = copyout_p->c;
9006 GOMP_barrier ();
9009 FIXME. It may be better to delay expanding the logic of this until
9010 pass_expand_omp. The expanded logic may make the job more difficult
9011 to a synchronization analysis pass. */
9013 static void
9014 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
9016 tree ptr_type, t, l0, l1, l2, bfn_decl;
9017 gimple_seq copyin_seq;
9018 location_t loc = gimple_location (single_stmt);
9020 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
9022 ptr_type = build_pointer_type (ctx->record_type);
9023 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
9025 l0 = create_artificial_label (loc);
9026 l1 = create_artificial_label (loc);
9027 l2 = create_artificial_label (loc);
9029 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
9030 t = build_call_expr_loc (loc, bfn_decl, 0);
9031 t = fold_convert_loc (loc, ptr_type, t);
9032 gimplify_assign (ctx->receiver_decl, t, pre_p);
9034 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
9035 build_int_cst (ptr_type, 0));
9036 t = build3 (COND_EXPR, void_type_node, t,
9037 build_and_jump (&l0), build_and_jump (&l1));
9038 gimplify_and_add (t, pre_p);
9040 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
9042 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9044 copyin_seq = NULL;
9045 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
9046 &copyin_seq, ctx);
9048 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9049 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
9050 t = build_call_expr_loc (loc, bfn_decl, 1, t);
9051 gimplify_and_add (t, pre_p);
9053 t = build_and_jump (&l2);
9054 gimplify_and_add (t, pre_p);
9056 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
9058 gimple_seq_add_seq (pre_p, copyin_seq);
9060 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
9064 /* Expand code for an OpenMP single directive. */
9066 static void
9067 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9069 tree block;
9070 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
9071 gimple_seq bind_body, bind_body_tail = NULL, dlist;
9073 push_gimplify_context ();
9075 block = make_node (BLOCK);
9076 bind = gimple_build_bind (NULL, NULL, block);
9077 gsi_replace (gsi_p, bind, true);
9078 bind_body = NULL;
9079 dlist = NULL;
9080 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
9081 &bind_body, &dlist, ctx, NULL);
9082 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
9084 gimple_seq_add_stmt (&bind_body, single_stmt);
9086 if (ctx->record_type)
9087 lower_omp_single_copy (single_stmt, &bind_body, ctx);
9088 else
9089 lower_omp_single_simple (single_stmt, &bind_body);
9091 gimple_omp_set_body (single_stmt, NULL);
9093 gimple_seq_add_seq (&bind_body, dlist);
9095 bind_body = maybe_catch_exception (bind_body);
9097 t = gimple_build_omp_return
9098 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
9099 OMP_CLAUSE_NOWAIT));
9100 gimple_seq_add_stmt (&bind_body_tail, t);
9101 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
9102 if (ctx->record_type)
9104 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9105 tree clobber = build_constructor (ctx->record_type, NULL);
9106 TREE_THIS_VOLATILE (clobber) = 1;
9107 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9108 clobber), GSI_SAME_STMT);
9110 gimple_seq_add_seq (&bind_body, bind_body_tail);
9111 gimple_bind_set_body (bind, bind_body);
9113 pop_gimplify_context (bind);
9115 gimple_bind_append_vars (bind, ctx->block_vars);
9116 BLOCK_VARS (block) = ctx->block_vars;
9117 if (BLOCK_VARS (block))
9118 TREE_USED (block) = 1;
9122 /* Expand code for an OpenMP master directive. */
9124 static void
9125 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9127 tree block, lab = NULL, x, bfn_decl;
9128 gimple stmt = gsi_stmt (*gsi_p), bind;
9129 location_t loc = gimple_location (stmt);
9130 gimple_seq tseq;
9132 push_gimplify_context ();
9134 block = make_node (BLOCK);
9135 bind = gimple_build_bind (NULL, NULL, block);
9136 gsi_replace (gsi_p, bind, true);
9137 gimple_bind_add_stmt (bind, stmt);
9139 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9140 x = build_call_expr_loc (loc, bfn_decl, 0);
9141 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
9142 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9143 tseq = NULL;
9144 gimplify_and_add (x, &tseq);
9145 gimple_bind_add_seq (bind, tseq);
9147 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9148 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9149 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9150 gimple_omp_set_body (stmt, NULL);
9152 gimple_bind_add_stmt (bind, gimple_build_label (lab));
9154 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9156 pop_gimplify_context (bind);
9158 gimple_bind_append_vars (bind, ctx->block_vars);
9159 BLOCK_VARS (block) = ctx->block_vars;
9163 /* Expand code for an OpenMP taskgroup directive. */
9165 static void
9166 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9168 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9169 tree block = make_node (BLOCK);
9171 bind = gimple_build_bind (NULL, NULL, block);
9172 gsi_replace (gsi_p, bind, true);
9173 gimple_bind_add_stmt (bind, stmt);
9175 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9177 gimple_bind_add_stmt (bind, x);
9179 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9180 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9181 gimple_omp_set_body (stmt, NULL);
9183 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9185 gimple_bind_append_vars (bind, ctx->block_vars);
9186 BLOCK_VARS (block) = ctx->block_vars;
9190 /* Expand code for an OpenMP ordered directive. */
9192 static void
9193 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9195 tree block;
9196 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9198 push_gimplify_context ();
9200 block = make_node (BLOCK);
9201 bind = gimple_build_bind (NULL, NULL, block);
9202 gsi_replace (gsi_p, bind, true);
9203 gimple_bind_add_stmt (bind, stmt);
9205 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
9207 gimple_bind_add_stmt (bind, x);
9209 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9210 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9211 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9212 gimple_omp_set_body (stmt, NULL);
9214 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
9215 gimple_bind_add_stmt (bind, x);
9217 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9219 pop_gimplify_context (bind);
9221 gimple_bind_append_vars (bind, ctx->block_vars);
9222 BLOCK_VARS (block) = gimple_bind_vars (bind);
9226 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9227 substitution of a couple of function calls. But in the NAMED case,
9228 requires that languages coordinate a symbol name. It is therefore
9229 best put here in common code. */
9231 static GTY((param1_is (tree), param2_is (tree)))
9232 splay_tree critical_name_mutexes;
9234 static void
9235 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9237 tree block;
9238 tree name, lock, unlock;
9239 gimple stmt = gsi_stmt (*gsi_p), bind;
9240 location_t loc = gimple_location (stmt);
9241 gimple_seq tbody;
9243 name = gimple_omp_critical_name (stmt);
9244 if (name)
9246 tree decl;
9247 splay_tree_node n;
9249 if (!critical_name_mutexes)
9250 critical_name_mutexes
9251 = splay_tree_new_ggc (splay_tree_compare_pointers,
9252 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
9253 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
9255 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
9256 if (n == NULL)
9258 char *new_str;
9260 decl = create_tmp_var_raw (ptr_type_node, NULL);
9262 new_str = ACONCAT ((".gomp_critical_user_",
9263 IDENTIFIER_POINTER (name), NULL));
9264 DECL_NAME (decl) = get_identifier (new_str);
9265 TREE_PUBLIC (decl) = 1;
9266 TREE_STATIC (decl) = 1;
9267 DECL_COMMON (decl) = 1;
9268 DECL_ARTIFICIAL (decl) = 1;
9269 DECL_IGNORED_P (decl) = 1;
9270 varpool_node::finalize_decl (decl);
9272 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
9273 (splay_tree_value) decl);
9275 else
9276 decl = (tree) n->value;
9278 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
9279 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
9281 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
9282 unlock = build_call_expr_loc (loc, unlock, 1,
9283 build_fold_addr_expr_loc (loc, decl));
9285 else
9287 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
9288 lock = build_call_expr_loc (loc, lock, 0);
9290 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
9291 unlock = build_call_expr_loc (loc, unlock, 0);
9294 push_gimplify_context ();
9296 block = make_node (BLOCK);
9297 bind = gimple_build_bind (NULL, NULL, block);
9298 gsi_replace (gsi_p, bind, true);
9299 gimple_bind_add_stmt (bind, stmt);
9301 tbody = gimple_bind_body (bind);
9302 gimplify_and_add (lock, &tbody);
9303 gimple_bind_set_body (bind, tbody);
9305 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9306 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9307 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9308 gimple_omp_set_body (stmt, NULL);
9310 tbody = gimple_bind_body (bind);
9311 gimplify_and_add (unlock, &tbody);
9312 gimple_bind_set_body (bind, tbody);
9314 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9316 pop_gimplify_context (bind);
9317 gimple_bind_append_vars (bind, ctx->block_vars);
9318 BLOCK_VARS (block) = gimple_bind_vars (bind);
9322 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9323 for a lastprivate clause. Given a loop control predicate of (V
9324 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9325 is appended to *DLIST, iterator initialization is appended to
9326 *BODY_P. */
9328 static void
9329 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
9330 gimple_seq *dlist, struct omp_context *ctx)
9332 tree clauses, cond, vinit;
9333 enum tree_code cond_code;
9334 gimple_seq stmts;
9336 cond_code = fd->loop.cond_code;
9337 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
9339 /* When possible, use a strict equality expression. This can let VRP
9340 type optimizations deduce the value and remove a copy. */
9341 if (tree_fits_shwi_p (fd->loop.step))
9343 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
9344 if (step == 1 || step == -1)
9345 cond_code = EQ_EXPR;
9348 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
9350 clauses = gimple_omp_for_clauses (fd->for_stmt);
9351 stmts = NULL;
9352 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
9353 if (!gimple_seq_empty_p (stmts))
9355 gimple_seq_add_seq (&stmts, *dlist);
9356 *dlist = stmts;
9358 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9359 vinit = fd->loop.n1;
9360 if (cond_code == EQ_EXPR
9361 && tree_fits_shwi_p (fd->loop.n2)
9362 && ! integer_zerop (fd->loop.n2))
9363 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
9364 else
9365 vinit = unshare_expr (vinit);
9367 /* Initialize the iterator variable, so that threads that don't execute
9368 any iterations don't execute the lastprivate clauses by accident. */
9369 gimplify_assign (fd->loop.v, vinit, body_p);
9374 /* Lower code for an OpenMP loop directive. */
9376 static void
9377 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9379 tree *rhs_p, block;
9380 struct omp_for_data fd, *fdp = NULL;
9381 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
9382 gimple_seq omp_for_body, body, dlist;
9383 size_t i;
9385 push_gimplify_context ();
9387 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
9389 block = make_node (BLOCK);
9390 new_stmt = gimple_build_bind (NULL, NULL, block);
9391 /* Replace at gsi right away, so that 'stmt' is no member
9392 of a sequence anymore as we're going to add to to a different
9393 one below. */
9394 gsi_replace (gsi_p, new_stmt, true);
9396 /* Move declaration of temporaries in the loop body before we make
9397 it go away. */
9398 omp_for_body = gimple_omp_body (stmt);
9399 if (!gimple_seq_empty_p (omp_for_body)
9400 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9402 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
9403 tree vars = gimple_bind_vars (inner_bind);
9404 gimple_bind_append_vars (new_stmt, vars);
9405 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9406 keep them on the inner_bind and it's block. */
9407 gimple_bind_set_vars (inner_bind, NULL_TREE);
9408 if (gimple_bind_block (inner_bind))
9409 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9412 if (gimple_omp_for_combined_into_p (stmt))
9414 extract_omp_for_data (stmt, &fd, NULL);
9415 fdp = &fd;
9417 /* We need two temporaries with fd.loop.v type (istart/iend)
9418 and then (fd.collapse - 1) temporaries with the same
9419 type for count2 ... countN-1 vars if not constant. */
9420 size_t count = 2;
9421 tree type = fd.iter_type;
9422 if (fd.collapse > 1
9423 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9424 count += fd.collapse - 1;
9425 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9426 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9427 tree clauses = *pc;
9428 if (parallel_for)
9429 outerc
9430 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9431 OMP_CLAUSE__LOOPTEMP_);
9432 for (i = 0; i < count; i++)
9434 tree temp;
9435 if (parallel_for)
9437 gcc_assert (outerc);
9438 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9439 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9440 OMP_CLAUSE__LOOPTEMP_);
9442 else
9444 temp = create_tmp_var (type, NULL);
9445 insert_decl_map (&ctx->outer->cb, temp, temp);
9447 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9448 OMP_CLAUSE_DECL (*pc) = temp;
9449 pc = &OMP_CLAUSE_CHAIN (*pc);
9451 *pc = clauses;
9454 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9455 dlist = NULL;
9456 body = NULL;
9457 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9458 fdp);
9459 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9461 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9463 /* Lower the header expressions. At this point, we can assume that
9464 the header is of the form:
9466 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9468 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9469 using the .omp_data_s mapping, if needed. */
9470 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9472 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9473 if (!is_gimple_min_invariant (*rhs_p))
9474 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9476 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9477 if (!is_gimple_min_invariant (*rhs_p))
9478 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9480 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9481 if (!is_gimple_min_invariant (*rhs_p))
9482 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9485 /* Once lowered, extract the bounds and clauses. */
9486 extract_omp_for_data (stmt, &fd, NULL);
9488 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9490 gimple_seq_add_stmt (&body, stmt);
9491 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9493 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9494 fd.loop.v));
9496 /* After the loop, add exit clauses. */
9497 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9499 if (ctx->cancellable)
9500 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9502 gimple_seq_add_seq (&body, dlist);
9504 body = maybe_catch_exception (body);
9506 /* Region exit marker goes at the end of the loop body. */
9507 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9508 maybe_add_implicit_barrier_cancel (ctx, &body);
9509 pop_gimplify_context (new_stmt);
9511 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9512 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9513 if (BLOCK_VARS (block))
9514 TREE_USED (block) = 1;
9516 gimple_bind_set_body (new_stmt, body);
9517 gimple_omp_set_body (stmt, NULL);
9518 gimple_omp_for_set_pre_body (stmt, NULL);
9521 /* Callback for walk_stmts. Check if the current statement only contains
9522 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9524 static tree
9525 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9526 bool *handled_ops_p,
9527 struct walk_stmt_info *wi)
9529 int *info = (int *) wi->info;
9530 gimple stmt = gsi_stmt (*gsi_p);
9532 *handled_ops_p = true;
9533 switch (gimple_code (stmt))
9535 WALK_SUBSTMTS;
9537 case GIMPLE_OMP_FOR:
9538 case GIMPLE_OMP_SECTIONS:
9539 *info = *info == 0 ? 1 : -1;
9540 break;
9541 default:
9542 *info = -1;
9543 break;
9545 return NULL;
9548 struct omp_taskcopy_context
9550 /* This field must be at the beginning, as we do "inheritance": Some
9551 callback functions for tree-inline.c (e.g., omp_copy_decl)
9552 receive a copy_body_data pointer that is up-casted to an
9553 omp_context pointer. */
9554 copy_body_data cb;
9555 omp_context *ctx;
9558 static tree
9559 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9561 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9563 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9564 return create_tmp_var (TREE_TYPE (var), NULL);
9566 return var;
9569 static tree
9570 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9572 tree name, new_fields = NULL, type, f;
9574 type = lang_hooks.types.make_type (RECORD_TYPE);
9575 name = DECL_NAME (TYPE_NAME (orig_type));
9576 name = build_decl (gimple_location (tcctx->ctx->stmt),
9577 TYPE_DECL, name, type);
9578 TYPE_NAME (type) = name;
9580 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9582 tree new_f = copy_node (f);
9583 DECL_CONTEXT (new_f) = type;
9584 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9585 TREE_CHAIN (new_f) = new_fields;
9586 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9587 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9588 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9589 &tcctx->cb, NULL);
9590 new_fields = new_f;
9591 tcctx->cb.decl_map->put (f, new_f);
9593 TYPE_FIELDS (type) = nreverse (new_fields);
9594 layout_type (type);
9595 return type;
9598 /* Create task copyfn. */
9600 static void
9601 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9603 struct function *child_cfun;
9604 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9605 tree record_type, srecord_type, bind, list;
9606 bool record_needs_remap = false, srecord_needs_remap = false;
9607 splay_tree_node n;
9608 struct omp_taskcopy_context tcctx;
9609 location_t loc = gimple_location (task_stmt);
9611 child_fn = gimple_omp_task_copy_fn (task_stmt);
9612 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9613 gcc_assert (child_cfun->cfg == NULL);
9614 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9616 /* Reset DECL_CONTEXT on function arguments. */
9617 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9618 DECL_CONTEXT (t) = child_fn;
9620 /* Populate the function. */
9621 push_gimplify_context ();
9622 push_cfun (child_cfun);
9624 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9625 TREE_SIDE_EFFECTS (bind) = 1;
9626 list = NULL;
9627 DECL_SAVED_TREE (child_fn) = bind;
9628 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9630 /* Remap src and dst argument types if needed. */
9631 record_type = ctx->record_type;
9632 srecord_type = ctx->srecord_type;
9633 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9634 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9636 record_needs_remap = true;
9637 break;
9639 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9640 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9642 srecord_needs_remap = true;
9643 break;
9646 if (record_needs_remap || srecord_needs_remap)
9648 memset (&tcctx, '\0', sizeof (tcctx));
9649 tcctx.cb.src_fn = ctx->cb.src_fn;
9650 tcctx.cb.dst_fn = child_fn;
9651 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
9652 gcc_checking_assert (tcctx.cb.src_node);
9653 tcctx.cb.dst_node = tcctx.cb.src_node;
9654 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9655 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9656 tcctx.cb.eh_lp_nr = 0;
9657 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9658 tcctx.cb.decl_map = new hash_map<tree, tree>;
9659 tcctx.ctx = ctx;
9661 if (record_needs_remap)
9662 record_type = task_copyfn_remap_type (&tcctx, record_type);
9663 if (srecord_needs_remap)
9664 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9666 else
9667 tcctx.cb.decl_map = NULL;
9669 arg = DECL_ARGUMENTS (child_fn);
9670 TREE_TYPE (arg) = build_pointer_type (record_type);
9671 sarg = DECL_CHAIN (arg);
9672 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9674 /* First pass: initialize temporaries used in record_type and srecord_type
9675 sizes and field offsets. */
9676 if (tcctx.cb.decl_map)
9677 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9678 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9680 tree *p;
9682 decl = OMP_CLAUSE_DECL (c);
9683 p = tcctx.cb.decl_map->get (decl);
9684 if (p == NULL)
9685 continue;
9686 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9687 sf = (tree) n->value;
9688 sf = *tcctx.cb.decl_map->get (sf);
9689 src = build_simple_mem_ref_loc (loc, sarg);
9690 src = omp_build_component_ref (src, sf);
9691 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9692 append_to_statement_list (t, &list);
9695 /* Second pass: copy shared var pointers and copy construct non-VLA
9696 firstprivate vars. */
9697 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9698 switch (OMP_CLAUSE_CODE (c))
9700 case OMP_CLAUSE_SHARED:
9701 decl = OMP_CLAUSE_DECL (c);
9702 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9703 if (n == NULL)
9704 break;
9705 f = (tree) n->value;
9706 if (tcctx.cb.decl_map)
9707 f = *tcctx.cb.decl_map->get (f);
9708 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9709 sf = (tree) n->value;
9710 if (tcctx.cb.decl_map)
9711 sf = *tcctx.cb.decl_map->get (sf);
9712 src = build_simple_mem_ref_loc (loc, sarg);
9713 src = omp_build_component_ref (src, sf);
9714 dst = build_simple_mem_ref_loc (loc, arg);
9715 dst = omp_build_component_ref (dst, f);
9716 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9717 append_to_statement_list (t, &list);
9718 break;
9719 case OMP_CLAUSE_FIRSTPRIVATE:
9720 decl = OMP_CLAUSE_DECL (c);
9721 if (is_variable_sized (decl))
9722 break;
9723 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9724 if (n == NULL)
9725 break;
9726 f = (tree) n->value;
9727 if (tcctx.cb.decl_map)
9728 f = *tcctx.cb.decl_map->get (f);
9729 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9730 if (n != NULL)
9732 sf = (tree) n->value;
9733 if (tcctx.cb.decl_map)
9734 sf = *tcctx.cb.decl_map->get (sf);
9735 src = build_simple_mem_ref_loc (loc, sarg);
9736 src = omp_build_component_ref (src, sf);
9737 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9738 src = build_simple_mem_ref_loc (loc, src);
9740 else
9741 src = decl;
9742 dst = build_simple_mem_ref_loc (loc, arg);
9743 dst = omp_build_component_ref (dst, f);
9744 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9745 append_to_statement_list (t, &list);
9746 break;
9747 case OMP_CLAUSE_PRIVATE:
9748 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9749 break;
9750 decl = OMP_CLAUSE_DECL (c);
9751 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9752 f = (tree) n->value;
9753 if (tcctx.cb.decl_map)
9754 f = *tcctx.cb.decl_map->get (f);
9755 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9756 if (n != NULL)
9758 sf = (tree) n->value;
9759 if (tcctx.cb.decl_map)
9760 sf = *tcctx.cb.decl_map->get (sf);
9761 src = build_simple_mem_ref_loc (loc, sarg);
9762 src = omp_build_component_ref (src, sf);
9763 if (use_pointer_for_field (decl, NULL))
9764 src = build_simple_mem_ref_loc (loc, src);
9766 else
9767 src = decl;
9768 dst = build_simple_mem_ref_loc (loc, arg);
9769 dst = omp_build_component_ref (dst, f);
9770 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9771 append_to_statement_list (t, &list);
9772 break;
9773 default:
9774 break;
9777 /* Last pass: handle VLA firstprivates. */
9778 if (tcctx.cb.decl_map)
9779 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9780 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9782 tree ind, ptr, df;
9784 decl = OMP_CLAUSE_DECL (c);
9785 if (!is_variable_sized (decl))
9786 continue;
9787 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9788 if (n == NULL)
9789 continue;
9790 f = (tree) n->value;
9791 f = *tcctx.cb.decl_map->get (f);
9792 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9793 ind = DECL_VALUE_EXPR (decl);
9794 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9795 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9796 n = splay_tree_lookup (ctx->sfield_map,
9797 (splay_tree_key) TREE_OPERAND (ind, 0));
9798 sf = (tree) n->value;
9799 sf = *tcctx.cb.decl_map->get (sf);
9800 src = build_simple_mem_ref_loc (loc, sarg);
9801 src = omp_build_component_ref (src, sf);
9802 src = build_simple_mem_ref_loc (loc, src);
9803 dst = build_simple_mem_ref_loc (loc, arg);
9804 dst = omp_build_component_ref (dst, f);
9805 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9806 append_to_statement_list (t, &list);
9807 n = splay_tree_lookup (ctx->field_map,
9808 (splay_tree_key) TREE_OPERAND (ind, 0));
9809 df = (tree) n->value;
9810 df = *tcctx.cb.decl_map->get (df);
9811 ptr = build_simple_mem_ref_loc (loc, arg);
9812 ptr = omp_build_component_ref (ptr, df);
9813 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9814 build_fold_addr_expr_loc (loc, dst));
9815 append_to_statement_list (t, &list);
9818 t = build1 (RETURN_EXPR, void_type_node, NULL);
9819 append_to_statement_list (t, &list);
9821 if (tcctx.cb.decl_map)
9822 delete tcctx.cb.decl_map;
9823 pop_gimplify_context (NULL);
9824 BIND_EXPR_BODY (bind) = list;
9825 pop_cfun ();
9828 static void
9829 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9831 tree c, clauses;
9832 gimple g;
9833 size_t n_in = 0, n_out = 0, idx = 2, i;
9835 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9836 OMP_CLAUSE_DEPEND);
9837 gcc_assert (clauses);
9838 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9839 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9840 switch (OMP_CLAUSE_DEPEND_KIND (c))
9842 case OMP_CLAUSE_DEPEND_IN:
9843 n_in++;
9844 break;
9845 case OMP_CLAUSE_DEPEND_OUT:
9846 case OMP_CLAUSE_DEPEND_INOUT:
9847 n_out++;
9848 break;
9849 default:
9850 gcc_unreachable ();
9852 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9853 tree array = create_tmp_var (type, NULL);
9854 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9855 NULL_TREE);
9856 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9857 gimple_seq_add_stmt (iseq, g);
9858 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9859 NULL_TREE);
9860 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9861 gimple_seq_add_stmt (iseq, g);
9862 for (i = 0; i < 2; i++)
9864 if ((i ? n_in : n_out) == 0)
9865 continue;
9866 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9867 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9868 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9870 tree t = OMP_CLAUSE_DECL (c);
9871 t = fold_convert (ptr_type_node, t);
9872 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9873 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9874 NULL_TREE, NULL_TREE);
9875 g = gimple_build_assign (r, t);
9876 gimple_seq_add_stmt (iseq, g);
9879 tree *p = gimple_omp_task_clauses_ptr (stmt);
9880 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9881 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9882 OMP_CLAUSE_CHAIN (c) = *p;
9883 *p = c;
9884 tree clobber = build_constructor (type, NULL);
9885 TREE_THIS_VOLATILE (clobber) = 1;
9886 g = gimple_build_assign (array, clobber);
9887 gimple_seq_add_stmt (oseq, g);
9890 /* Lower the OpenMP parallel or task directive in the current statement
9891 in GSI_P. CTX holds context information for the directive. */
9893 static void
9894 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9896 tree clauses;
9897 tree child_fn, t;
9898 gimple stmt = gsi_stmt (*gsi_p);
9899 gimple par_bind, bind, dep_bind = NULL;
9900 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9901 location_t loc = gimple_location (stmt);
9903 clauses = gimple_omp_taskreg_clauses (stmt);
9904 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9905 par_body = gimple_bind_body (par_bind);
9906 child_fn = ctx->cb.dst_fn;
9907 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9908 && !gimple_omp_parallel_combined_p (stmt))
9910 struct walk_stmt_info wi;
9911 int ws_num = 0;
9913 memset (&wi, 0, sizeof (wi));
9914 wi.info = &ws_num;
9915 wi.val_only = true;
9916 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9917 if (ws_num == 1)
9918 gimple_omp_parallel_set_combined_p (stmt, true);
9920 gimple_seq dep_ilist = NULL;
9921 gimple_seq dep_olist = NULL;
9922 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9923 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9925 push_gimplify_context ();
9926 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9927 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9930 if (ctx->srecord_type)
9931 create_task_copyfn (stmt, ctx);
9933 push_gimplify_context ();
9935 par_olist = NULL;
9936 par_ilist = NULL;
9937 par_rlist = NULL;
9938 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9939 lower_omp (&par_body, ctx);
9940 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9941 lower_reduction_clauses (clauses, &par_rlist, ctx);
9943 /* Declare all the variables created by mapping and the variables
9944 declared in the scope of the parallel body. */
9945 record_vars_into (ctx->block_vars, child_fn);
9946 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9948 if (ctx->record_type)
9950 ctx->sender_decl
9951 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9952 : ctx->record_type, ".omp_data_o");
9953 DECL_NAMELESS (ctx->sender_decl) = 1;
9954 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9955 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9958 olist = NULL;
9959 ilist = NULL;
9960 lower_send_clauses (clauses, &ilist, &olist, ctx);
9961 lower_send_shared_vars (&ilist, &olist, ctx);
9963 if (ctx->record_type)
9965 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9966 TREE_THIS_VOLATILE (clobber) = 1;
9967 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9968 clobber));
9971 /* Once all the expansions are done, sequence all the different
9972 fragments inside gimple_omp_body. */
9974 new_body = NULL;
9976 if (ctx->record_type)
9978 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9979 /* fixup_child_record_type might have changed receiver_decl's type. */
9980 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9981 gimple_seq_add_stmt (&new_body,
9982 gimple_build_assign (ctx->receiver_decl, t));
9985 gimple_seq_add_seq (&new_body, par_ilist);
9986 gimple_seq_add_seq (&new_body, par_body);
9987 gimple_seq_add_seq (&new_body, par_rlist);
9988 if (ctx->cancellable)
9989 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9990 gimple_seq_add_seq (&new_body, par_olist);
9991 new_body = maybe_catch_exception (new_body);
9992 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9993 gimple_omp_set_body (stmt, new_body);
9995 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9996 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
9997 gimple_bind_add_seq (bind, ilist);
9998 gimple_bind_add_stmt (bind, stmt);
9999 gimple_bind_add_seq (bind, olist);
10001 pop_gimplify_context (NULL);
10003 if (dep_bind)
10005 gimple_bind_add_seq (dep_bind, dep_ilist);
10006 gimple_bind_add_stmt (dep_bind, bind);
10007 gimple_bind_add_seq (dep_bind, dep_olist);
10008 pop_gimplify_context (dep_bind);
10012 /* Lower the OpenMP target directive in the current statement
10013 in GSI_P. CTX holds context information for the directive. */
10015 static void
10016 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10018 tree clauses;
10019 tree child_fn, t, c;
10020 gimple stmt = gsi_stmt (*gsi_p);
10021 gimple tgt_bind = NULL, bind;
10022 gimple_seq tgt_body = NULL, olist, ilist, new_body;
10023 location_t loc = gimple_location (stmt);
10024 int kind = gimple_omp_target_kind (stmt);
10025 unsigned int map_cnt = 0;
10027 clauses = gimple_omp_target_clauses (stmt);
10028 if (kind == GF_OMP_TARGET_KIND_REGION)
10030 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
10031 tgt_body = gimple_bind_body (tgt_bind);
10033 else if (kind == GF_OMP_TARGET_KIND_DATA)
10034 tgt_body = gimple_omp_body (stmt);
10035 child_fn = ctx->cb.dst_fn;
10037 push_gimplify_context ();
10039 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10040 switch (OMP_CLAUSE_CODE (c))
10042 tree var, x;
10044 default:
10045 break;
10046 case OMP_CLAUSE_MAP:
10047 case OMP_CLAUSE_TO:
10048 case OMP_CLAUSE_FROM:
10049 var = OMP_CLAUSE_DECL (c);
10050 if (!DECL_P (var))
10052 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10053 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10054 map_cnt++;
10055 continue;
10058 if (DECL_SIZE (var)
10059 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
10061 tree var2 = DECL_VALUE_EXPR (var);
10062 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
10063 var2 = TREE_OPERAND (var2, 0);
10064 gcc_assert (DECL_P (var2));
10065 var = var2;
10068 if (!maybe_lookup_field (var, ctx))
10069 continue;
10071 if (kind == GF_OMP_TARGET_KIND_REGION)
10073 x = build_receiver_ref (var, true, ctx);
10074 tree new_var = lookup_decl (var, ctx);
10075 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10076 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10077 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10078 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
10079 x = build_simple_mem_ref (x);
10080 SET_DECL_VALUE_EXPR (new_var, x);
10081 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
10083 map_cnt++;
10086 if (kind == GF_OMP_TARGET_KIND_REGION)
10088 target_nesting_level++;
10089 lower_omp (&tgt_body, ctx);
10090 target_nesting_level--;
10092 else if (kind == GF_OMP_TARGET_KIND_DATA)
10093 lower_omp (&tgt_body, ctx);
10095 if (kind == GF_OMP_TARGET_KIND_REGION)
10097 /* Declare all the variables created by mapping and the variables
10098 declared in the scope of the target body. */
10099 record_vars_into (ctx->block_vars, child_fn);
10100 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
10103 olist = NULL;
10104 ilist = NULL;
10105 if (ctx->record_type)
10107 ctx->sender_decl
10108 = create_tmp_var (ctx->record_type, ".omp_data_arr");
10109 DECL_NAMELESS (ctx->sender_decl) = 1;
10110 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10111 t = make_tree_vec (3);
10112 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
10113 TREE_VEC_ELT (t, 1)
10114 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
10115 ".omp_data_sizes");
10116 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
10117 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
10118 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
10119 TREE_VEC_ELT (t, 2)
10120 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
10121 map_cnt),
10122 ".omp_data_kinds");
10123 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
10124 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
10125 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
10126 gimple_omp_target_set_data_arg (stmt, t);
10128 vec<constructor_elt, va_gc> *vsize;
10129 vec<constructor_elt, va_gc> *vkind;
10130 vec_alloc (vsize, map_cnt);
10131 vec_alloc (vkind, map_cnt);
10132 unsigned int map_idx = 0;
10134 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10135 switch (OMP_CLAUSE_CODE (c))
10137 tree ovar, nc;
10139 default:
10140 break;
10141 case OMP_CLAUSE_MAP:
10142 case OMP_CLAUSE_TO:
10143 case OMP_CLAUSE_FROM:
10144 nc = c;
10145 ovar = OMP_CLAUSE_DECL (c);
10146 if (!DECL_P (ovar))
10148 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10149 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10151 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
10152 == get_base_address (ovar));
10153 nc = OMP_CLAUSE_CHAIN (c);
10154 ovar = OMP_CLAUSE_DECL (nc);
10156 else
10158 tree x = build_sender_ref (ovar, ctx);
10159 tree v
10160 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
10161 gimplify_assign (x, v, &ilist);
10162 nc = NULL_TREE;
10165 else
10167 if (DECL_SIZE (ovar)
10168 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
10170 tree ovar2 = DECL_VALUE_EXPR (ovar);
10171 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
10172 ovar2 = TREE_OPERAND (ovar2, 0);
10173 gcc_assert (DECL_P (ovar2));
10174 ovar = ovar2;
10176 if (!maybe_lookup_field (ovar, ctx))
10177 continue;
10180 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
10181 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
10182 talign = DECL_ALIGN_UNIT (ovar);
10183 if (nc)
10185 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
10186 tree x = build_sender_ref (ovar, ctx);
10187 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10188 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10189 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10190 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
10192 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10193 tree avar
10194 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
10195 mark_addressable (avar);
10196 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
10197 talign = DECL_ALIGN_UNIT (avar);
10198 avar = build_fold_addr_expr (avar);
10199 gimplify_assign (x, avar, &ilist);
10201 else if (is_gimple_reg (var))
10203 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10204 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
10205 mark_addressable (avar);
10206 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
10207 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
10208 gimplify_assign (avar, var, &ilist);
10209 avar = build_fold_addr_expr (avar);
10210 gimplify_assign (x, avar, &ilist);
10211 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
10212 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
10213 && !TYPE_READONLY (TREE_TYPE (var)))
10215 x = build_sender_ref (ovar, ctx);
10216 x = build_simple_mem_ref (x);
10217 gimplify_assign (var, x, &olist);
10220 else
10222 var = build_fold_addr_expr (var);
10223 gimplify_assign (x, var, &ilist);
10226 tree s = OMP_CLAUSE_SIZE (c);
10227 if (s == NULL_TREE)
10228 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
10229 s = fold_convert (size_type_node, s);
10230 tree purpose = size_int (map_idx++);
10231 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
10232 if (TREE_CODE (s) != INTEGER_CST)
10233 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
10235 unsigned char tkind = 0;
10236 switch (OMP_CLAUSE_CODE (c))
10238 case OMP_CLAUSE_MAP:
10239 tkind = OMP_CLAUSE_MAP_KIND (c);
10240 break;
10241 case OMP_CLAUSE_TO:
10242 tkind = OMP_CLAUSE_MAP_TO;
10243 break;
10244 case OMP_CLAUSE_FROM:
10245 tkind = OMP_CLAUSE_MAP_FROM;
10246 break;
10247 default:
10248 gcc_unreachable ();
10250 talign = ceil_log2 (talign);
10251 tkind |= talign << 3;
10252 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
10253 build_int_cst (unsigned_char_type_node,
10254 tkind));
10255 if (nc && nc != c)
10256 c = nc;
10259 gcc_assert (map_idx == map_cnt);
10261 DECL_INITIAL (TREE_VEC_ELT (t, 1))
10262 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
10263 DECL_INITIAL (TREE_VEC_ELT (t, 2))
10264 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
10265 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
10267 gimple_seq initlist = NULL;
10268 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
10269 TREE_VEC_ELT (t, 1)),
10270 &initlist, true, NULL_TREE);
10271 gimple_seq_add_seq (&ilist, initlist);
10273 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
10274 NULL);
10275 TREE_THIS_VOLATILE (clobber) = 1;
10276 gimple_seq_add_stmt (&olist,
10277 gimple_build_assign (TREE_VEC_ELT (t, 1),
10278 clobber));
10281 tree clobber = build_constructor (ctx->record_type, NULL);
10282 TREE_THIS_VOLATILE (clobber) = 1;
10283 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10284 clobber));
10287 /* Once all the expansions are done, sequence all the different
10288 fragments inside gimple_omp_body. */
10290 new_body = NULL;
10292 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
10294 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10295 /* fixup_child_record_type might have changed receiver_decl's type. */
10296 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10297 gimple_seq_add_stmt (&new_body,
10298 gimple_build_assign (ctx->receiver_decl, t));
10301 if (kind == GF_OMP_TARGET_KIND_REGION)
10303 gimple_seq_add_seq (&new_body, tgt_body);
10304 new_body = maybe_catch_exception (new_body);
10306 else if (kind == GF_OMP_TARGET_KIND_DATA)
10307 new_body = tgt_body;
10308 if (kind != GF_OMP_TARGET_KIND_UPDATE)
10310 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10311 gimple_omp_set_body (stmt, new_body);
10314 bind = gimple_build_bind (NULL, NULL,
10315 tgt_bind ? gimple_bind_block (tgt_bind)
10316 : NULL_TREE);
10317 gsi_replace (gsi_p, bind, true);
10318 gimple_bind_add_seq (bind, ilist);
10319 gimple_bind_add_stmt (bind, stmt);
10320 gimple_bind_add_seq (bind, olist);
10322 pop_gimplify_context (NULL);
10325 /* Expand code for an OpenMP teams directive. */
10327 static void
10328 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10330 gimple teams_stmt = gsi_stmt (*gsi_p);
10331 push_gimplify_context ();
10333 tree block = make_node (BLOCK);
10334 gimple bind = gimple_build_bind (NULL, NULL, block);
10335 gsi_replace (gsi_p, bind, true);
10336 gimple_seq bind_body = NULL;
10337 gimple_seq dlist = NULL;
10338 gimple_seq olist = NULL;
10340 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10341 OMP_CLAUSE_NUM_TEAMS);
10342 if (num_teams == NULL_TREE)
10343 num_teams = build_int_cst (unsigned_type_node, 0);
10344 else
10346 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
10347 num_teams = fold_convert (unsigned_type_node, num_teams);
10348 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
10350 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10351 OMP_CLAUSE_THREAD_LIMIT);
10352 if (thread_limit == NULL_TREE)
10353 thread_limit = build_int_cst (unsigned_type_node, 0);
10354 else
10356 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10357 thread_limit = fold_convert (unsigned_type_node, thread_limit);
10358 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
10359 fb_rvalue);
10362 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
10363 &bind_body, &dlist, ctx, NULL);
10364 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
10365 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
10366 gimple_seq_add_stmt (&bind_body, teams_stmt);
10368 location_t loc = gimple_location (teams_stmt);
10369 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
10370 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10371 gimple_set_location (call, loc);
10372 gimple_seq_add_stmt (&bind_body, call);
10374 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10375 gimple_omp_set_body (teams_stmt, NULL);
10376 gimple_seq_add_seq (&bind_body, olist);
10377 gimple_seq_add_seq (&bind_body, dlist);
10378 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10379 gimple_bind_set_body (bind, bind_body);
10381 pop_gimplify_context (bind);
10383 gimple_bind_append_vars (bind, ctx->block_vars);
10384 BLOCK_VARS (block) = ctx->block_vars;
10385 if (BLOCK_VARS (block))
10386 TREE_USED (block) = 1;
10390 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10391 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10392 of OpenMP context, but with task_shared_vars set. */
10394 static tree
10395 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10396 void *data)
10398 tree t = *tp;
10400 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10401 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
10402 return t;
10404 if (task_shared_vars
10405 && DECL_P (t)
10406 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10407 return t;
10409 /* If a global variable has been privatized, TREE_CONSTANT on
10410 ADDR_EXPR might be wrong. */
10411 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10412 recompute_tree_invariant_for_addr_expr (t);
10414 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10415 return NULL_TREE;
10418 static void
10419 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10421 gimple stmt = gsi_stmt (*gsi_p);
10422 struct walk_stmt_info wi;
10424 if (gimple_has_location (stmt))
10425 input_location = gimple_location (stmt);
10427 if (task_shared_vars)
10428 memset (&wi, '\0', sizeof (wi));
10430 /* If we have issued syntax errors, avoid doing any heavy lifting.
10431 Just replace the OpenMP directives with a NOP to avoid
10432 confusing RTL expansion. */
10433 if (seen_error () && is_gimple_omp (stmt))
10435 gsi_replace (gsi_p, gimple_build_nop (), true);
10436 return;
10439 switch (gimple_code (stmt))
10441 case GIMPLE_COND:
10442 if ((ctx || task_shared_vars)
10443 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
10444 ctx ? NULL : &wi, NULL)
10445 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
10446 ctx ? NULL : &wi, NULL)))
10447 gimple_regimplify_operands (stmt, gsi_p);
10448 break;
10449 case GIMPLE_CATCH:
10450 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
10451 break;
10452 case GIMPLE_EH_FILTER:
10453 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10454 break;
10455 case GIMPLE_TRY:
10456 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10457 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10458 break;
10459 case GIMPLE_TRANSACTION:
10460 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
10461 break;
10462 case GIMPLE_BIND:
10463 lower_omp (gimple_bind_body_ptr (stmt), ctx);
10464 break;
10465 case GIMPLE_OMP_PARALLEL:
10466 case GIMPLE_OMP_TASK:
10467 ctx = maybe_lookup_ctx (stmt);
10468 gcc_assert (ctx);
10469 if (ctx->cancellable)
10470 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10471 lower_omp_taskreg (gsi_p, ctx);
10472 break;
10473 case GIMPLE_OMP_FOR:
10474 ctx = maybe_lookup_ctx (stmt);
10475 gcc_assert (ctx);
10476 if (ctx->cancellable)
10477 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10478 lower_omp_for (gsi_p, ctx);
10479 break;
10480 case GIMPLE_OMP_SECTIONS:
10481 ctx = maybe_lookup_ctx (stmt);
10482 gcc_assert (ctx);
10483 if (ctx->cancellable)
10484 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10485 lower_omp_sections (gsi_p, ctx);
10486 break;
10487 case GIMPLE_OMP_SINGLE:
10488 ctx = maybe_lookup_ctx (stmt);
10489 gcc_assert (ctx);
10490 lower_omp_single (gsi_p, ctx);
10491 break;
10492 case GIMPLE_OMP_MASTER:
10493 ctx = maybe_lookup_ctx (stmt);
10494 gcc_assert (ctx);
10495 lower_omp_master (gsi_p, ctx);
10496 break;
10497 case GIMPLE_OMP_TASKGROUP:
10498 ctx = maybe_lookup_ctx (stmt);
10499 gcc_assert (ctx);
10500 lower_omp_taskgroup (gsi_p, ctx);
10501 break;
10502 case GIMPLE_OMP_ORDERED:
10503 ctx = maybe_lookup_ctx (stmt);
10504 gcc_assert (ctx);
10505 lower_omp_ordered (gsi_p, ctx);
10506 break;
10507 case GIMPLE_OMP_CRITICAL:
10508 ctx = maybe_lookup_ctx (stmt);
10509 gcc_assert (ctx);
10510 lower_omp_critical (gsi_p, ctx);
10511 break;
10512 case GIMPLE_OMP_ATOMIC_LOAD:
10513 if ((ctx || task_shared_vars)
10514 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
10515 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10516 gimple_regimplify_operands (stmt, gsi_p);
10517 break;
10518 case GIMPLE_OMP_TARGET:
10519 ctx = maybe_lookup_ctx (stmt);
10520 gcc_assert (ctx);
10521 lower_omp_target (gsi_p, ctx);
10522 break;
10523 case GIMPLE_OMP_TEAMS:
10524 ctx = maybe_lookup_ctx (stmt);
10525 gcc_assert (ctx);
10526 lower_omp_teams (gsi_p, ctx);
10527 break;
10528 case GIMPLE_CALL:
10529 tree fndecl;
10530 fndecl = gimple_call_fndecl (stmt);
10531 if (fndecl
10532 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10533 switch (DECL_FUNCTION_CODE (fndecl))
10535 case BUILT_IN_GOMP_BARRIER:
10536 if (ctx == NULL)
10537 break;
10538 /* FALLTHRU */
10539 case BUILT_IN_GOMP_CANCEL:
10540 case BUILT_IN_GOMP_CANCELLATION_POINT:
10541 omp_context *cctx;
10542 cctx = ctx;
10543 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10544 cctx = cctx->outer;
10545 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10546 if (!cctx->cancellable)
10548 if (DECL_FUNCTION_CODE (fndecl)
10549 == BUILT_IN_GOMP_CANCELLATION_POINT)
10551 stmt = gimple_build_nop ();
10552 gsi_replace (gsi_p, stmt, false);
10554 break;
10556 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10558 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10559 gimple_call_set_fndecl (stmt, fndecl);
10560 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10562 tree lhs;
10563 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
10564 gimple_call_set_lhs (stmt, lhs);
10565 tree fallthru_label;
10566 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10567 gimple g;
10568 g = gimple_build_label (fallthru_label);
10569 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10570 g = gimple_build_cond (NE_EXPR, lhs,
10571 fold_convert (TREE_TYPE (lhs),
10572 boolean_false_node),
10573 cctx->cancel_label, fallthru_label);
10574 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10575 break;
10576 default:
10577 break;
10579 /* FALLTHRU */
10580 default:
10581 if ((ctx || task_shared_vars)
10582 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10583 ctx ? NULL : &wi))
10585 /* Just remove clobbers, this should happen only if we have
10586 "privatized" local addressable variables in SIMD regions,
10587 the clobber isn't needed in that case and gimplifying address
10588 of the ARRAY_REF into a pointer and creating MEM_REF based
10589 clobber would create worse code than we get with the clobber
10590 dropped. */
10591 if (gimple_clobber_p (stmt))
10593 gsi_replace (gsi_p, gimple_build_nop (), true);
10594 break;
10596 gimple_regimplify_operands (stmt, gsi_p);
10598 break;
10602 static void
10603 lower_omp (gimple_seq *body, omp_context *ctx)
10605 location_t saved_location = input_location;
10606 gimple_stmt_iterator gsi;
10607 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10608 lower_omp_1 (&gsi, ctx);
10609 /* During gimplification, we have not always invoked fold_stmt
10610 (gimplify.c:maybe_fold_stmt); call it now. */
10611 if (target_nesting_level)
10612 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10613 fold_stmt (&gsi);
10614 input_location = saved_location;
10617 /* Main entry point. */
10619 static unsigned int
10620 execute_lower_omp (void)
10622 gimple_seq body;
10623 int i;
10624 omp_context *ctx;
10626 /* This pass always runs, to provide PROP_gimple_lomp.
10627 But there is nothing to do unless -fopenmp is given. */
10628 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10629 return 0;
10631 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10632 delete_omp_context);
10634 body = gimple_body (current_function_decl);
10635 scan_omp (&body, NULL);
10636 gcc_assert (taskreg_nesting_level == 0);
10637 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
10638 finish_taskreg_scan (ctx);
10639 taskreg_contexts.release ();
10641 if (all_contexts->root)
10643 if (task_shared_vars)
10644 push_gimplify_context ();
10645 lower_omp (&body, NULL);
10646 if (task_shared_vars)
10647 pop_gimplify_context (NULL);
10650 if (all_contexts)
10652 splay_tree_delete (all_contexts);
10653 all_contexts = NULL;
10655 BITMAP_FREE (task_shared_vars);
10656 return 0;
10659 namespace {
10661 const pass_data pass_data_lower_omp =
10663 GIMPLE_PASS, /* type */
10664 "omplower", /* name */
10665 OPTGROUP_NONE, /* optinfo_flags */
10666 TV_NONE, /* tv_id */
10667 PROP_gimple_any, /* properties_required */
10668 PROP_gimple_lomp, /* properties_provided */
10669 0, /* properties_destroyed */
10670 0, /* todo_flags_start */
10671 0, /* todo_flags_finish */
10674 class pass_lower_omp : public gimple_opt_pass
10676 public:
10677 pass_lower_omp (gcc::context *ctxt)
10678 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10681 /* opt_pass methods: */
10682 virtual unsigned int execute (function *) { return execute_lower_omp (); }
10684 }; // class pass_lower_omp
10686 } // anon namespace
10688 gimple_opt_pass *
10689 make_pass_lower_omp (gcc::context *ctxt)
10691 return new pass_lower_omp (ctxt);
10694 /* The following is a utility to diagnose OpenMP structured block violations.
10695 It is not part of the "omplower" pass, as that's invoked too late. It
10696 should be invoked by the respective front ends after gimplification. */
10698 static splay_tree all_labels;
10700 /* Check for mismatched contexts and generate an error if needed. Return
10701 true if an error is detected. */
10703 static bool
10704 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10705 gimple branch_ctx, gimple label_ctx)
10707 if (label_ctx == branch_ctx)
10708 return false;
10712 Previously we kept track of the label's entire context in diagnose_sb_[12]
10713 so we could traverse it and issue a correct "exit" or "enter" error
10714 message upon a structured block violation.
10716 We built the context by building a list with tree_cons'ing, but there is
10717 no easy counterpart in gimple tuples. It seems like far too much work
10718 for issuing exit/enter error messages. If someone really misses the
10719 distinct error message... patches welcome.
10722 #if 0
10723 /* Try to avoid confusing the user by producing and error message
10724 with correct "exit" or "enter" verbiage. We prefer "exit"
10725 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10726 if (branch_ctx == NULL)
10727 exit_p = false;
10728 else
10730 while (label_ctx)
10732 if (TREE_VALUE (label_ctx) == branch_ctx)
10734 exit_p = false;
10735 break;
10737 label_ctx = TREE_CHAIN (label_ctx);
10741 if (exit_p)
10742 error ("invalid exit from OpenMP structured block");
10743 else
10744 error ("invalid entry to OpenMP structured block");
10745 #endif
10747 bool cilkplus_block = false;
10748 if (flag_cilkplus)
10750 if ((branch_ctx
10751 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10752 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10753 || (label_ctx
10754 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10755 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10756 cilkplus_block = true;
10759 /* If it's obvious we have an invalid entry, be specific about the error. */
10760 if (branch_ctx == NULL)
10762 if (cilkplus_block)
10763 error ("invalid entry to Cilk Plus structured block");
10764 else
10765 error ("invalid entry to OpenMP structured block");
10767 else
10769 /* Otherwise, be vague and lazy, but efficient. */
10770 if (cilkplus_block)
10771 error ("invalid branch to/from a Cilk Plus structured block");
10772 else
10773 error ("invalid branch to/from an OpenMP structured block");
10776 gsi_replace (gsi_p, gimple_build_nop (), false);
10777 return true;
10780 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10781 where each label is found. */
10783 static tree
10784 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10785 struct walk_stmt_info *wi)
10787 gimple context = (gimple) wi->info;
10788 gimple inner_context;
10789 gimple stmt = gsi_stmt (*gsi_p);
10791 *handled_ops_p = true;
10793 switch (gimple_code (stmt))
10795 WALK_SUBSTMTS;
10797 case GIMPLE_OMP_PARALLEL:
10798 case GIMPLE_OMP_TASK:
10799 case GIMPLE_OMP_SECTIONS:
10800 case GIMPLE_OMP_SINGLE:
10801 case GIMPLE_OMP_SECTION:
10802 case GIMPLE_OMP_MASTER:
10803 case GIMPLE_OMP_ORDERED:
10804 case GIMPLE_OMP_CRITICAL:
10805 case GIMPLE_OMP_TARGET:
10806 case GIMPLE_OMP_TEAMS:
10807 case GIMPLE_OMP_TASKGROUP:
10808 /* The minimal context here is just the current OMP construct. */
10809 inner_context = stmt;
10810 wi->info = inner_context;
10811 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10812 wi->info = context;
10813 break;
10815 case GIMPLE_OMP_FOR:
10816 inner_context = stmt;
10817 wi->info = inner_context;
10818 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10819 walk them. */
10820 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10821 diagnose_sb_1, NULL, wi);
10822 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10823 wi->info = context;
10824 break;
10826 case GIMPLE_LABEL:
10827 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10828 (splay_tree_value) context);
10829 break;
10831 default:
10832 break;
10835 return NULL_TREE;
10838 /* Pass 2: Check each branch and see if its context differs from that of
10839 the destination label's context. */
10841 static tree
10842 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10843 struct walk_stmt_info *wi)
10845 gimple context = (gimple) wi->info;
10846 splay_tree_node n;
10847 gimple stmt = gsi_stmt (*gsi_p);
10849 *handled_ops_p = true;
10851 switch (gimple_code (stmt))
10853 WALK_SUBSTMTS;
10855 case GIMPLE_OMP_PARALLEL:
10856 case GIMPLE_OMP_TASK:
10857 case GIMPLE_OMP_SECTIONS:
10858 case GIMPLE_OMP_SINGLE:
10859 case GIMPLE_OMP_SECTION:
10860 case GIMPLE_OMP_MASTER:
10861 case GIMPLE_OMP_ORDERED:
10862 case GIMPLE_OMP_CRITICAL:
10863 case GIMPLE_OMP_TARGET:
10864 case GIMPLE_OMP_TEAMS:
10865 case GIMPLE_OMP_TASKGROUP:
10866 wi->info = stmt;
10867 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10868 wi->info = context;
10869 break;
10871 case GIMPLE_OMP_FOR:
10872 wi->info = stmt;
10873 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10874 walk them. */
10875 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10876 diagnose_sb_2, NULL, wi);
10877 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10878 wi->info = context;
10879 break;
10881 case GIMPLE_COND:
10883 tree lab = gimple_cond_true_label (stmt);
10884 if (lab)
10886 n = splay_tree_lookup (all_labels,
10887 (splay_tree_key) lab);
10888 diagnose_sb_0 (gsi_p, context,
10889 n ? (gimple) n->value : NULL);
10891 lab = gimple_cond_false_label (stmt);
10892 if (lab)
10894 n = splay_tree_lookup (all_labels,
10895 (splay_tree_key) lab);
10896 diagnose_sb_0 (gsi_p, context,
10897 n ? (gimple) n->value : NULL);
10900 break;
10902 case GIMPLE_GOTO:
10904 tree lab = gimple_goto_dest (stmt);
10905 if (TREE_CODE (lab) != LABEL_DECL)
10906 break;
10908 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10909 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10911 break;
10913 case GIMPLE_SWITCH:
10915 unsigned int i;
10916 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10918 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10919 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10920 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10921 break;
10924 break;
10926 case GIMPLE_RETURN:
10927 diagnose_sb_0 (gsi_p, context, NULL);
10928 break;
10930 default:
10931 break;
10934 return NULL_TREE;
10937 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10938 codes. */
10939 bool
10940 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
10941 int *region_idx)
10943 gimple last = last_stmt (bb);
10944 enum gimple_code code = gimple_code (last);
10945 struct omp_region *cur_region = *region;
10946 bool fallthru = false;
10948 switch (code)
10950 case GIMPLE_OMP_PARALLEL:
10951 case GIMPLE_OMP_TASK:
10952 case GIMPLE_OMP_FOR:
10953 case GIMPLE_OMP_SINGLE:
10954 case GIMPLE_OMP_TEAMS:
10955 case GIMPLE_OMP_MASTER:
10956 case GIMPLE_OMP_TASKGROUP:
10957 case GIMPLE_OMP_ORDERED:
10958 case GIMPLE_OMP_CRITICAL:
10959 case GIMPLE_OMP_SECTION:
10960 cur_region = new_omp_region (bb, code, cur_region);
10961 fallthru = true;
10962 break;
10964 case GIMPLE_OMP_TARGET:
10965 cur_region = new_omp_region (bb, code, cur_region);
10966 fallthru = true;
10967 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10968 cur_region = cur_region->outer;
10969 break;
10971 case GIMPLE_OMP_SECTIONS:
10972 cur_region = new_omp_region (bb, code, cur_region);
10973 fallthru = true;
10974 break;
10976 case GIMPLE_OMP_SECTIONS_SWITCH:
10977 fallthru = false;
10978 break;
10980 case GIMPLE_OMP_ATOMIC_LOAD:
10981 case GIMPLE_OMP_ATOMIC_STORE:
10982 fallthru = true;
10983 break;
10985 case GIMPLE_OMP_RETURN:
10986 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10987 somewhere other than the next block. This will be
10988 created later. */
10989 cur_region->exit = bb;
10990 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
10991 cur_region = cur_region->outer;
10992 break;
10994 case GIMPLE_OMP_CONTINUE:
10995 cur_region->cont = bb;
10996 switch (cur_region->type)
10998 case GIMPLE_OMP_FOR:
10999 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11000 succs edges as abnormal to prevent splitting
11001 them. */
11002 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
11003 /* Make the loopback edge. */
11004 make_edge (bb, single_succ (cur_region->entry),
11005 EDGE_ABNORMAL);
11007 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11008 corresponds to the case that the body of the loop
11009 is not executed at all. */
11010 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
11011 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
11012 fallthru = false;
11013 break;
11015 case GIMPLE_OMP_SECTIONS:
11016 /* Wire up the edges into and out of the nested sections. */
11018 basic_block switch_bb = single_succ (cur_region->entry);
11020 struct omp_region *i;
11021 for (i = cur_region->inner; i ; i = i->next)
11023 gcc_assert (i->type == GIMPLE_OMP_SECTION);
11024 make_edge (switch_bb, i->entry, 0);
11025 make_edge (i->exit, bb, EDGE_FALLTHRU);
11028 /* Make the loopback edge to the block with
11029 GIMPLE_OMP_SECTIONS_SWITCH. */
11030 make_edge (bb, switch_bb, 0);
11032 /* Make the edge from the switch to exit. */
11033 make_edge (switch_bb, bb->next_bb, 0);
11034 fallthru = false;
11036 break;
11038 default:
11039 gcc_unreachable ();
11041 break;
11043 default:
11044 gcc_unreachable ();
11047 if (*region != cur_region)
11049 *region = cur_region;
11050 if (cur_region)
11051 *region_idx = cur_region->entry->index;
11052 else
11053 *region_idx = 0;
11056 return fallthru;
11059 static unsigned int
11060 diagnose_omp_structured_block_errors (void)
11062 struct walk_stmt_info wi;
11063 gimple_seq body = gimple_body (current_function_decl);
11065 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
11067 memset (&wi, 0, sizeof (wi));
11068 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
11070 memset (&wi, 0, sizeof (wi));
11071 wi.want_locations = true;
11072 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
11074 gimple_set_body (current_function_decl, body);
11076 splay_tree_delete (all_labels);
11077 all_labels = NULL;
11079 return 0;
11082 namespace {
11084 const pass_data pass_data_diagnose_omp_blocks =
11086 GIMPLE_PASS, /* type */
11087 "*diagnose_omp_blocks", /* name */
11088 OPTGROUP_NONE, /* optinfo_flags */
11089 TV_NONE, /* tv_id */
11090 PROP_gimple_any, /* properties_required */
11091 0, /* properties_provided */
11092 0, /* properties_destroyed */
11093 0, /* todo_flags_start */
11094 0, /* todo_flags_finish */
11097 class pass_diagnose_omp_blocks : public gimple_opt_pass
11099 public:
11100 pass_diagnose_omp_blocks (gcc::context *ctxt)
11101 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
11104 /* opt_pass methods: */
11105 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
11106 virtual unsigned int execute (function *)
11108 return diagnose_omp_structured_block_errors ();
11111 }; // class pass_diagnose_omp_blocks
11113 } // anon namespace
11115 gimple_opt_pass *
11116 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
11118 return new pass_diagnose_omp_blocks (ctxt);
11121 /* SIMD clone supporting code. */
11123 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11124 of arguments to reserve space for. */
11126 static struct cgraph_simd_clone *
11127 simd_clone_struct_alloc (int nargs)
11129 struct cgraph_simd_clone *clone_info;
11130 size_t len = (sizeof (struct cgraph_simd_clone)
11131 + nargs * sizeof (struct cgraph_simd_clone_arg));
11132 clone_info = (struct cgraph_simd_clone *)
11133 ggc_internal_cleared_alloc (len);
11134 return clone_info;
11137 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11139 static inline void
11140 simd_clone_struct_copy (struct cgraph_simd_clone *to,
11141 struct cgraph_simd_clone *from)
11143 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
11144 + ((from->nargs - from->inbranch)
11145 * sizeof (struct cgraph_simd_clone_arg))));
11148 /* Return vector of parameter types of function FNDECL. This uses
11149 TYPE_ARG_TYPES if available, otherwise falls back to types of
11150 DECL_ARGUMENTS types. */
11152 vec<tree>
11153 simd_clone_vector_of_formal_parm_types (tree fndecl)
11155 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
11156 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
11157 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
11158 unsigned int i;
11159 tree arg;
11160 FOR_EACH_VEC_ELT (args, i, arg)
11161 args[i] = TREE_TYPE (args[i]);
11162 return args;
11165 /* Given a simd function in NODE, extract the simd specific
11166 information from the OMP clauses passed in CLAUSES, and return
11167 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11168 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11169 otherwise set to FALSE. */
11171 static struct cgraph_simd_clone *
11172 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
11173 bool *inbranch_specified)
11175 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
11176 tree t;
11177 int n;
11178 *inbranch_specified = false;
11180 n = args.length ();
11181 if (n > 0 && args.last () == void_type_node)
11182 n--;
11184 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11185 be cloned have a distinctive artificial label in addition to "omp
11186 declare simd". */
11187 bool cilk_clone
11188 = (flag_cilkplus
11189 && lookup_attribute ("cilk simd function",
11190 DECL_ATTRIBUTES (node->decl)));
11192 /* Allocate one more than needed just in case this is an in-branch
11193 clone which will require a mask argument. */
11194 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
11195 clone_info->nargs = n;
11196 clone_info->cilk_elemental = cilk_clone;
11198 if (!clauses)
11200 args.release ();
11201 return clone_info;
11203 clauses = TREE_VALUE (clauses);
11204 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
11205 return clone_info;
11207 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
11209 switch (OMP_CLAUSE_CODE (t))
11211 case OMP_CLAUSE_INBRANCH:
11212 clone_info->inbranch = 1;
11213 *inbranch_specified = true;
11214 break;
11215 case OMP_CLAUSE_NOTINBRANCH:
11216 clone_info->inbranch = 0;
11217 *inbranch_specified = true;
11218 break;
11219 case OMP_CLAUSE_SIMDLEN:
11220 clone_info->simdlen
11221 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
11222 break;
11223 case OMP_CLAUSE_LINEAR:
11225 tree decl = OMP_CLAUSE_DECL (t);
11226 tree step = OMP_CLAUSE_LINEAR_STEP (t);
11227 int argno = TREE_INT_CST_LOW (decl);
11228 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
11230 clone_info->args[argno].arg_type
11231 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
11232 clone_info->args[argno].linear_step = tree_to_shwi (step);
11233 gcc_assert (clone_info->args[argno].linear_step >= 0
11234 && clone_info->args[argno].linear_step < n);
11236 else
11238 if (POINTER_TYPE_P (args[argno]))
11239 step = fold_convert (ssizetype, step);
11240 if (!tree_fits_shwi_p (step))
11242 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11243 "ignoring large linear step");
11244 args.release ();
11245 return NULL;
11247 else if (integer_zerop (step))
11249 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11250 "ignoring zero linear step");
11251 args.release ();
11252 return NULL;
11254 else
11256 clone_info->args[argno].arg_type
11257 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
11258 clone_info->args[argno].linear_step = tree_to_shwi (step);
11261 break;
11263 case OMP_CLAUSE_UNIFORM:
11265 tree decl = OMP_CLAUSE_DECL (t);
11266 int argno = tree_to_uhwi (decl);
11267 clone_info->args[argno].arg_type
11268 = SIMD_CLONE_ARG_TYPE_UNIFORM;
11269 break;
11271 case OMP_CLAUSE_ALIGNED:
11273 tree decl = OMP_CLAUSE_DECL (t);
11274 int argno = tree_to_uhwi (decl);
11275 clone_info->args[argno].alignment
11276 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
11277 break;
11279 default:
11280 break;
11283 args.release ();
11284 return clone_info;
11287 /* Given a SIMD clone in NODE, calculate the characteristic data
11288 type and return the coresponding type. The characteristic data
11289 type is computed as described in the Intel Vector ABI. */
11291 static tree
11292 simd_clone_compute_base_data_type (struct cgraph_node *node,
11293 struct cgraph_simd_clone *clone_info)
11295 tree type = integer_type_node;
11296 tree fndecl = node->decl;
11298 /* a) For non-void function, the characteristic data type is the
11299 return type. */
11300 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
11301 type = TREE_TYPE (TREE_TYPE (fndecl));
11303 /* b) If the function has any non-uniform, non-linear parameters,
11304 then the characteristic data type is the type of the first
11305 such parameter. */
11306 else
11308 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
11309 for (unsigned int i = 0; i < clone_info->nargs; ++i)
11310 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
11312 type = map[i];
11313 break;
11315 map.release ();
11318 /* c) If the characteristic data type determined by a) or b) above
11319 is struct, union, or class type which is pass-by-value (except
11320 for the type that maps to the built-in complex data type), the
11321 characteristic data type is int. */
11322 if (RECORD_OR_UNION_TYPE_P (type)
11323 && !aggregate_value_p (type, NULL)
11324 && TREE_CODE (type) != COMPLEX_TYPE)
11325 return integer_type_node;
11327 /* d) If none of the above three classes is applicable, the
11328 characteristic data type is int. */
11330 return type;
11332 /* e) For Intel Xeon Phi native and offload compilation, if the
11333 resulting characteristic data type is 8-bit or 16-bit integer
11334 data type, the characteristic data type is int. */
11335 /* Well, we don't handle Xeon Phi yet. */
11338 static tree
11339 simd_clone_mangle (struct cgraph_node *node,
11340 struct cgraph_simd_clone *clone_info)
11342 char vecsize_mangle = clone_info->vecsize_mangle;
11343 char mask = clone_info->inbranch ? 'M' : 'N';
11344 unsigned int simdlen = clone_info->simdlen;
11345 unsigned int n;
11346 pretty_printer pp;
11348 gcc_assert (vecsize_mangle && simdlen);
11350 pp_string (&pp, "_ZGV");
11351 pp_character (&pp, vecsize_mangle);
11352 pp_character (&pp, mask);
11353 pp_decimal_int (&pp, simdlen);
11355 for (n = 0; n < clone_info->nargs; ++n)
11357 struct cgraph_simd_clone_arg arg = clone_info->args[n];
11359 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
11360 pp_character (&pp, 'u');
11361 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11363 gcc_assert (arg.linear_step != 0);
11364 pp_character (&pp, 'l');
11365 if (arg.linear_step > 1)
11366 pp_unsigned_wide_integer (&pp, arg.linear_step);
11367 else if (arg.linear_step < 0)
11369 pp_character (&pp, 'n');
11370 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
11371 arg.linear_step));
11374 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11376 pp_character (&pp, 's');
11377 pp_unsigned_wide_integer (&pp, arg.linear_step);
11379 else
11380 pp_character (&pp, 'v');
11381 if (arg.alignment)
11383 pp_character (&pp, 'a');
11384 pp_decimal_int (&pp, arg.alignment);
11388 pp_underscore (&pp);
11389 pp_string (&pp,
11390 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11391 const char *str = pp_formatted_text (&pp);
11393 /* If there already is a SIMD clone with the same mangled name, don't
11394 add another one. This can happen e.g. for
11395 #pragma omp declare simd
11396 #pragma omp declare simd simdlen(8)
11397 int foo (int, int);
11398 if the simdlen is assumed to be 8 for the first one, etc. */
11399 for (struct cgraph_node *clone = node->simd_clones; clone;
11400 clone = clone->simdclone->next_clone)
11401 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11402 str) == 0)
11403 return NULL_TREE;
11405 return get_identifier (str);
11408 /* Create a simd clone of OLD_NODE and return it. */
11410 static struct cgraph_node *
11411 simd_clone_create (struct cgraph_node *old_node)
11413 struct cgraph_node *new_node;
11414 if (old_node->definition)
11416 if (!old_node->has_gimple_body_p ())
11417 return NULL;
11418 old_node->get_body ();
11419 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
11420 false, NULL, NULL,
11421 "simdclone");
11423 else
11425 tree old_decl = old_node->decl;
11426 tree new_decl = copy_node (old_node->decl);
11427 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11428 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11429 SET_DECL_RTL (new_decl, NULL);
11430 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11431 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11432 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
11433 symtab->call_cgraph_insertion_hooks (new_node);
11435 if (new_node == NULL)
11436 return new_node;
11438 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11440 /* The function cgraph_function_versioning () will force the new
11441 symbol local. Undo this, and inherit external visability from
11442 the old node. */
11443 new_node->local.local = old_node->local.local;
11444 new_node->externally_visible = old_node->externally_visible;
11446 return new_node;
11449 /* Adjust the return type of the given function to its appropriate
11450 vector counterpart. Returns a simd array to be used throughout the
11451 function as a return value. */
11453 static tree
11454 simd_clone_adjust_return_type (struct cgraph_node *node)
11456 tree fndecl = node->decl;
11457 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11458 unsigned int veclen;
11459 tree t;
11461 /* Adjust the function return type. */
11462 if (orig_rettype == void_type_node)
11463 return NULL_TREE;
11464 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11465 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11466 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11467 veclen = node->simdclone->vecsize_int;
11468 else
11469 veclen = node->simdclone->vecsize_float;
11470 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11471 if (veclen > node->simdclone->simdlen)
11472 veclen = node->simdclone->simdlen;
11473 if (veclen == node->simdclone->simdlen)
11474 TREE_TYPE (TREE_TYPE (fndecl))
11475 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11476 node->simdclone->simdlen);
11477 else
11479 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11480 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11481 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11483 if (!node->definition)
11484 return NULL_TREE;
11486 t = DECL_RESULT (fndecl);
11487 /* Adjust the DECL_RESULT. */
11488 gcc_assert (TREE_TYPE (t) != void_type_node);
11489 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11490 relayout_decl (t);
11492 tree atype = build_array_type_nelts (orig_rettype,
11493 node->simdclone->simdlen);
11494 if (veclen != node->simdclone->simdlen)
11495 return build1 (VIEW_CONVERT_EXPR, atype, t);
11497 /* Set up a SIMD array to use as the return value. */
11498 tree retval = create_tmp_var_raw (atype, "retval");
11499 gimple_add_tmp_var (retval);
11500 return retval;
11503 /* Each vector argument has a corresponding array to be used locally
11504 as part of the eventual loop. Create such temporary array and
11505 return it.
11507 PREFIX is the prefix to be used for the temporary.
11509 TYPE is the inner element type.
11511 SIMDLEN is the number of elements. */
11513 static tree
11514 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11516 tree atype = build_array_type_nelts (type, simdlen);
11517 tree avar = create_tmp_var_raw (atype, prefix);
11518 gimple_add_tmp_var (avar);
11519 return avar;
11522 /* Modify the function argument types to their corresponding vector
11523 counterparts if appropriate. Also, create one array for each simd
11524 argument to be used locally when using the function arguments as
11525 part of the loop.
11527 NODE is the function whose arguments are to be adjusted.
11529 Returns an adjustment vector that will be filled describing how the
11530 argument types will be adjusted. */
11532 static ipa_parm_adjustment_vec
11533 simd_clone_adjust_argument_types (struct cgraph_node *node)
11535 vec<tree> args;
11536 ipa_parm_adjustment_vec adjustments;
11538 if (node->definition)
11539 args = ipa_get_vector_of_formal_parms (node->decl);
11540 else
11541 args = simd_clone_vector_of_formal_parm_types (node->decl);
11542 adjustments.create (args.length ());
11543 unsigned i, j, veclen;
11544 struct ipa_parm_adjustment adj;
11545 for (i = 0; i < node->simdclone->nargs; ++i)
11547 memset (&adj, 0, sizeof (adj));
11548 tree parm = args[i];
11549 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11550 adj.base_index = i;
11551 adj.base = parm;
11553 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11554 node->simdclone->args[i].orig_type = parm_type;
11556 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11558 /* No adjustment necessary for scalar arguments. */
11559 adj.op = IPA_PARM_OP_COPY;
11561 else
11563 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11564 veclen = node->simdclone->vecsize_int;
11565 else
11566 veclen = node->simdclone->vecsize_float;
11567 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11568 if (veclen > node->simdclone->simdlen)
11569 veclen = node->simdclone->simdlen;
11570 adj.arg_prefix = "simd";
11571 adj.type = build_vector_type (parm_type, veclen);
11572 node->simdclone->args[i].vector_type = adj.type;
11573 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11575 adjustments.safe_push (adj);
11576 if (j == veclen)
11578 memset (&adj, 0, sizeof (adj));
11579 adj.op = IPA_PARM_OP_NEW;
11580 adj.arg_prefix = "simd";
11581 adj.base_index = i;
11582 adj.type = node->simdclone->args[i].vector_type;
11586 if (node->definition)
11587 node->simdclone->args[i].simd_array
11588 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11589 parm_type, node->simdclone->simdlen);
11591 adjustments.safe_push (adj);
11594 if (node->simdclone->inbranch)
11596 tree base_type
11597 = simd_clone_compute_base_data_type (node->simdclone->origin,
11598 node->simdclone);
11600 memset (&adj, 0, sizeof (adj));
11601 adj.op = IPA_PARM_OP_NEW;
11602 adj.arg_prefix = "mask";
11604 adj.base_index = i;
11605 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11606 veclen = node->simdclone->vecsize_int;
11607 else
11608 veclen = node->simdclone->vecsize_float;
11609 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11610 if (veclen > node->simdclone->simdlen)
11611 veclen = node->simdclone->simdlen;
11612 adj.type = build_vector_type (base_type, veclen);
11613 adjustments.safe_push (adj);
11615 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11616 adjustments.safe_push (adj);
11618 /* We have previously allocated one extra entry for the mask. Use
11619 it and fill it. */
11620 struct cgraph_simd_clone *sc = node->simdclone;
11621 sc->nargs++;
11622 if (node->definition)
11624 sc->args[i].orig_arg
11625 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11626 sc->args[i].simd_array
11627 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11629 sc->args[i].orig_type = base_type;
11630 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11633 if (node->definition)
11634 ipa_modify_formal_parameters (node->decl, adjustments);
11635 else
11637 tree new_arg_types = NULL_TREE, new_reversed;
11638 bool last_parm_void = false;
11639 if (args.length () > 0 && args.last () == void_type_node)
11640 last_parm_void = true;
11642 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11643 j = adjustments.length ();
11644 for (i = 0; i < j; i++)
11646 struct ipa_parm_adjustment *adj = &adjustments[i];
11647 tree ptype;
11648 if (adj->op == IPA_PARM_OP_COPY)
11649 ptype = args[adj->base_index];
11650 else
11651 ptype = adj->type;
11652 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11654 new_reversed = nreverse (new_arg_types);
11655 if (last_parm_void)
11657 if (new_reversed)
11658 TREE_CHAIN (new_arg_types) = void_list_node;
11659 else
11660 new_reversed = void_list_node;
11663 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11664 TYPE_ARG_TYPES (new_type) = new_reversed;
11665 TREE_TYPE (node->decl) = new_type;
11667 adjustments.release ();
11669 args.release ();
11670 return adjustments;
11673 /* Initialize and copy the function arguments in NODE to their
11674 corresponding local simd arrays. Returns a fresh gimple_seq with
11675 the instruction sequence generated. */
11677 static gimple_seq
11678 simd_clone_init_simd_arrays (struct cgraph_node *node,
11679 ipa_parm_adjustment_vec adjustments)
11681 gimple_seq seq = NULL;
11682 unsigned i = 0, j = 0, k;
11684 for (tree arg = DECL_ARGUMENTS (node->decl);
11685 arg;
11686 arg = DECL_CHAIN (arg), i++, j++)
11688 if (adjustments[j].op == IPA_PARM_OP_COPY)
11689 continue;
11691 node->simdclone->args[i].vector_arg = arg;
11693 tree array = node->simdclone->args[i].simd_array;
11694 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11696 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11697 tree ptr = build_fold_addr_expr (array);
11698 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11699 build_int_cst (ptype, 0));
11700 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11701 gimplify_and_add (t, &seq);
11703 else
11705 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11706 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11707 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11709 tree ptr = build_fold_addr_expr (array);
11710 int elemsize;
11711 if (k)
11713 arg = DECL_CHAIN (arg);
11714 j++;
11716 elemsize
11717 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11718 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11719 build_int_cst (ptype, k * elemsize));
11720 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11721 gimplify_and_add (t, &seq);
11725 return seq;
11728 /* Callback info for ipa_simd_modify_stmt_ops below. */
11730 struct modify_stmt_info {
11731 ipa_parm_adjustment_vec adjustments;
11732 gimple stmt;
11733 /* True if the parent statement was modified by
11734 ipa_simd_modify_stmt_ops. */
11735 bool modified;
11738 /* Callback for walk_gimple_op.
11740 Adjust operands from a given statement as specified in the
11741 adjustments vector in the callback data. */
11743 static tree
11744 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11746 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11747 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11748 tree *orig_tp = tp;
11749 if (TREE_CODE (*tp) == ADDR_EXPR)
11750 tp = &TREE_OPERAND (*tp, 0);
11751 struct ipa_parm_adjustment *cand = NULL;
11752 if (TREE_CODE (*tp) == PARM_DECL)
11753 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11754 else
11756 if (TYPE_P (*tp))
11757 *walk_subtrees = 0;
11760 tree repl = NULL_TREE;
11761 if (cand)
11762 repl = unshare_expr (cand->new_decl);
11763 else
11765 if (tp != orig_tp)
11767 *walk_subtrees = 0;
11768 bool modified = info->modified;
11769 info->modified = false;
11770 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11771 if (!info->modified)
11773 info->modified = modified;
11774 return NULL_TREE;
11776 info->modified = modified;
11777 repl = *tp;
11779 else
11780 return NULL_TREE;
11783 if (tp != orig_tp)
11785 repl = build_fold_addr_expr (repl);
11786 gimple stmt;
11787 if (is_gimple_debug (info->stmt))
11789 tree vexpr = make_node (DEBUG_EXPR_DECL);
11790 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
11791 DECL_ARTIFICIAL (vexpr) = 1;
11792 TREE_TYPE (vexpr) = TREE_TYPE (repl);
11793 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
11794 repl = vexpr;
11796 else
11798 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl),
11799 NULL), repl);
11800 repl = gimple_assign_lhs (stmt);
11802 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11803 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11804 *orig_tp = repl;
11806 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11808 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11809 *tp = vce;
11811 else
11812 *tp = repl;
11814 info->modified = true;
11815 return NULL_TREE;
11818 /* Traverse the function body and perform all modifications as
11819 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11820 modified such that the replacement/reduction value will now be an
11821 offset into the corresponding simd_array.
11823 This function will replace all function argument uses with their
11824 corresponding simd array elements, and ajust the return values
11825 accordingly. */
11827 static void
11828 ipa_simd_modify_function_body (struct cgraph_node *node,
11829 ipa_parm_adjustment_vec adjustments,
11830 tree retval_array, tree iter)
11832 basic_block bb;
11833 unsigned int i, j, l;
11835 /* Re-use the adjustments array, but this time use it to replace
11836 every function argument use to an offset into the corresponding
11837 simd_array. */
11838 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11840 if (!node->simdclone->args[i].vector_arg)
11841 continue;
11843 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11844 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11845 adjustments[j].new_decl
11846 = build4 (ARRAY_REF,
11847 basetype,
11848 node->simdclone->args[i].simd_array,
11849 iter,
11850 NULL_TREE, NULL_TREE);
11851 if (adjustments[j].op == IPA_PARM_OP_NONE
11852 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11853 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11856 l = adjustments.length ();
11857 for (i = 1; i < num_ssa_names; i++)
11859 tree name = ssa_name (i);
11860 if (name
11861 && SSA_NAME_VAR (name)
11862 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11864 for (j = 0; j < l; j++)
11865 if (SSA_NAME_VAR (name) == adjustments[j].base
11866 && adjustments[j].new_decl)
11868 tree base_var;
11869 if (adjustments[j].new_ssa_base == NULL_TREE)
11871 base_var
11872 = copy_var_decl (adjustments[j].base,
11873 DECL_NAME (adjustments[j].base),
11874 TREE_TYPE (adjustments[j].base));
11875 adjustments[j].new_ssa_base = base_var;
11877 else
11878 base_var = adjustments[j].new_ssa_base;
11879 if (SSA_NAME_IS_DEFAULT_DEF (name))
11881 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11882 gimple_stmt_iterator gsi = gsi_after_labels (bb);
11883 tree new_decl = unshare_expr (adjustments[j].new_decl);
11884 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
11885 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11886 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
11887 gimple stmt = gimple_build_assign (name, new_decl);
11888 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11890 else
11891 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11896 struct modify_stmt_info info;
11897 info.adjustments = adjustments;
11899 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
11901 gimple_stmt_iterator gsi;
11903 gsi = gsi_start_bb (bb);
11904 while (!gsi_end_p (gsi))
11906 gimple stmt = gsi_stmt (gsi);
11907 info.stmt = stmt;
11908 struct walk_stmt_info wi;
11910 memset (&wi, 0, sizeof (wi));
11911 info.modified = false;
11912 wi.info = &info;
11913 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
11915 if (gimple_code (stmt) == GIMPLE_RETURN)
11917 tree retval = gimple_return_retval (stmt);
11918 if (!retval)
11920 gsi_remove (&gsi, true);
11921 continue;
11924 /* Replace `return foo' with `retval_array[iter] = foo'. */
11925 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
11926 retval_array, iter, NULL, NULL);
11927 stmt = gimple_build_assign (ref, retval);
11928 gsi_replace (&gsi, stmt, true);
11929 info.modified = true;
11932 if (info.modified)
11934 update_stmt (stmt);
11935 if (maybe_clean_eh_stmt (stmt))
11936 gimple_purge_dead_eh_edges (gimple_bb (stmt));
11938 gsi_next (&gsi);
11943 /* Adjust the argument types in NODE to their appropriate vector
11944 counterparts. */
11946 static void
11947 simd_clone_adjust (struct cgraph_node *node)
11949 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
11951 targetm.simd_clone.adjust (node);
11953 tree retval = simd_clone_adjust_return_type (node);
11954 ipa_parm_adjustment_vec adjustments
11955 = simd_clone_adjust_argument_types (node);
11957 push_gimplify_context ();
11959 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
11961 /* Adjust all uses of vector arguments accordingly. Adjust all
11962 return values accordingly. */
11963 tree iter = create_tmp_var (unsigned_type_node, "iter");
11964 tree iter1 = make_ssa_name (iter, NULL);
11965 tree iter2 = make_ssa_name (iter, NULL);
11966 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
11968 /* Initialize the iteration variable. */
11969 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11970 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
11971 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
11972 /* Insert the SIMD array and iv initialization at function
11973 entry. */
11974 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
11976 pop_gimplify_context (NULL);
11978 /* Create a new BB right before the original exit BB, to hold the
11979 iteration increment and the condition/branch. */
11980 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
11981 basic_block incr_bb = create_empty_bb (orig_exit);
11982 add_bb_to_loop (incr_bb, body_bb->loop_father);
11983 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11984 flag. Set it now to be a FALLTHRU_EDGE. */
11985 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
11986 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
11987 for (unsigned i = 0;
11988 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
11990 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
11991 redirect_edge_succ (e, incr_bb);
11993 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
11994 e->probability = REG_BR_PROB_BASE;
11995 gsi = gsi_last_bb (incr_bb);
11996 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
11997 build_int_cst (unsigned_type_node,
11998 1));
11999 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12001 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12002 struct loop *loop = alloc_loop ();
12003 cfun->has_force_vectorize_loops = true;
12004 loop->safelen = node->simdclone->simdlen;
12005 loop->force_vectorize = true;
12006 loop->header = body_bb;
12008 /* Branch around the body if the mask applies. */
12009 if (node->simdclone->inbranch)
12011 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
12012 tree mask_array
12013 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
12014 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
12015 tree aref = build4 (ARRAY_REF,
12016 TREE_TYPE (TREE_TYPE (mask_array)),
12017 mask_array, iter1,
12018 NULL, NULL);
12019 g = gimple_build_assign (mask, aref);
12020 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12021 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
12022 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
12024 aref = build1 (VIEW_CONVERT_EXPR,
12025 build_nonstandard_integer_type (bitsize, 0), mask);
12026 mask = make_ssa_name (TREE_TYPE (aref), NULL);
12027 g = gimple_build_assign (mask, aref);
12028 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12031 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
12032 NULL, NULL);
12033 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12034 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
12035 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
12038 /* Generate the condition. */
12039 g = gimple_build_cond (LT_EXPR,
12040 iter2,
12041 build_int_cst (unsigned_type_node,
12042 node->simdclone->simdlen),
12043 NULL, NULL);
12044 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12045 e = split_block (incr_bb, gsi_stmt (gsi));
12046 basic_block latch_bb = e->dest;
12047 basic_block new_exit_bb;
12048 new_exit_bb = split_block (latch_bb, NULL)->dest;
12049 loop->latch = latch_bb;
12051 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
12053 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
12054 /* The successor of incr_bb is already pointing to latch_bb; just
12055 change the flags.
12056 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12057 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
12059 gimple phi = create_phi_node (iter1, body_bb);
12060 edge preheader_edge = find_edge (entry_bb, body_bb);
12061 edge latch_edge = single_succ_edge (latch_bb);
12062 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
12063 UNKNOWN_LOCATION);
12064 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12066 /* Generate the new return. */
12067 gsi = gsi_last_bb (new_exit_bb);
12068 if (retval
12069 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
12070 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
12071 retval = TREE_OPERAND (retval, 0);
12072 else if (retval)
12074 retval = build1 (VIEW_CONVERT_EXPR,
12075 TREE_TYPE (TREE_TYPE (node->decl)),
12076 retval);
12077 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
12078 false, GSI_CONTINUE_LINKING);
12080 g = gimple_build_return (retval);
12081 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12083 /* Handle aligned clauses by replacing default defs of the aligned
12084 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12085 lhs. Handle linear by adding PHIs. */
12086 for (unsigned i = 0; i < node->simdclone->nargs; i++)
12087 if (node->simdclone->args[i].alignment
12088 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
12089 && (node->simdclone->args[i].alignment
12090 & (node->simdclone->args[i].alignment - 1)) == 0
12091 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
12092 == POINTER_TYPE)
12094 unsigned int alignment = node->simdclone->args[i].alignment;
12095 tree orig_arg = node->simdclone->args[i].orig_arg;
12096 tree def = ssa_default_def (cfun, orig_arg);
12097 if (def && !has_zero_uses (def))
12099 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
12100 gimple_seq seq = NULL;
12101 bool need_cvt = false;
12102 gimple call
12103 = gimple_build_call (fn, 2, def, size_int (alignment));
12104 g = call;
12105 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
12106 ptr_type_node))
12107 need_cvt = true;
12108 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
12109 gimple_call_set_lhs (g, t);
12110 gimple_seq_add_stmt_without_update (&seq, g);
12111 if (need_cvt)
12113 t = make_ssa_name (orig_arg, NULL);
12114 g = gimple_build_assign_with_ops (NOP_EXPR, t,
12115 gimple_call_lhs (g),
12116 NULL_TREE);
12117 gimple_seq_add_stmt_without_update (&seq, g);
12119 gsi_insert_seq_on_edge_immediate
12120 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
12122 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12123 int freq = compute_call_stmt_bb_frequency (current_function_decl,
12124 entry_bb);
12125 node->create_edge (cgraph_node::get_create (fn),
12126 call, entry_bb->count, freq);
12128 imm_use_iterator iter;
12129 use_operand_p use_p;
12130 gimple use_stmt;
12131 tree repl = gimple_get_lhs (g);
12132 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12133 if (is_gimple_debug (use_stmt) || use_stmt == call)
12134 continue;
12135 else
12136 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12137 SET_USE (use_p, repl);
12140 else if (node->simdclone->args[i].arg_type
12141 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12143 tree orig_arg = node->simdclone->args[i].orig_arg;
12144 tree def = ssa_default_def (cfun, orig_arg);
12145 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12146 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
12147 if (def && !has_zero_uses (def))
12149 iter1 = make_ssa_name (orig_arg, NULL);
12150 iter2 = make_ssa_name (orig_arg, NULL);
12151 phi = create_phi_node (iter1, body_bb);
12152 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
12153 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12154 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12155 ? PLUS_EXPR : POINTER_PLUS_EXPR;
12156 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12157 ? TREE_TYPE (orig_arg) : sizetype;
12158 tree addcst
12159 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
12160 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
12161 gsi = gsi_last_bb (incr_bb);
12162 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12164 imm_use_iterator iter;
12165 use_operand_p use_p;
12166 gimple use_stmt;
12167 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12168 if (use_stmt == phi)
12169 continue;
12170 else
12171 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12172 SET_USE (use_p, iter1);
12176 calculate_dominance_info (CDI_DOMINATORS);
12177 add_loop (loop, loop->header->loop_father);
12178 update_ssa (TODO_update_ssa);
12180 pop_cfun ();
12183 /* If the function in NODE is tagged as an elemental SIMD function,
12184 create the appropriate SIMD clones. */
12186 static void
12187 expand_simd_clones (struct cgraph_node *node)
12189 tree attr = lookup_attribute ("omp declare simd",
12190 DECL_ATTRIBUTES (node->decl));
12191 if (attr == NULL_TREE
12192 || node->global.inlined_to
12193 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
12194 return;
12196 /* Ignore
12197 #pragma omp declare simd
12198 extern int foo ();
12199 in C, there we don't know the argument types at all. */
12200 if (!node->definition
12201 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
12202 return;
12206 /* Start with parsing the "omp declare simd" attribute(s). */
12207 bool inbranch_clause_specified;
12208 struct cgraph_simd_clone *clone_info
12209 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
12210 &inbranch_clause_specified);
12211 if (clone_info == NULL)
12212 continue;
12214 int orig_simdlen = clone_info->simdlen;
12215 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
12216 /* The target can return 0 (no simd clones should be created),
12217 1 (just one ISA of simd clones should be created) or higher
12218 count of ISA variants. In that case, clone_info is initialized
12219 for the first ISA variant. */
12220 int count
12221 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
12222 base_type, 0);
12223 if (count == 0)
12224 continue;
12226 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12227 also create one inbranch and one !inbranch clone of it. */
12228 for (int i = 0; i < count * 2; i++)
12230 struct cgraph_simd_clone *clone = clone_info;
12231 if (inbranch_clause_specified && (i & 1) != 0)
12232 continue;
12234 if (i != 0)
12236 clone = simd_clone_struct_alloc (clone_info->nargs
12237 + ((i & 1) != 0));
12238 simd_clone_struct_copy (clone, clone_info);
12239 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12240 and simd_clone_adjust_argument_types did to the first
12241 clone's info. */
12242 clone->nargs -= clone_info->inbranch;
12243 clone->simdlen = orig_simdlen;
12244 /* And call the target hook again to get the right ISA. */
12245 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
12246 base_type,
12247 i / 2);
12248 if ((i & 1) != 0)
12249 clone->inbranch = 1;
12252 /* simd_clone_mangle might fail if such a clone has been created
12253 already. */
12254 tree id = simd_clone_mangle (node, clone);
12255 if (id == NULL_TREE)
12256 continue;
12258 /* Only when we are sure we want to create the clone actually
12259 clone the function (or definitions) or create another
12260 extern FUNCTION_DECL (for prototypes without definitions). */
12261 struct cgraph_node *n = simd_clone_create (node);
12262 if (n == NULL)
12263 continue;
12265 n->simdclone = clone;
12266 clone->origin = node;
12267 clone->next_clone = NULL;
12268 if (node->simd_clones == NULL)
12270 clone->prev_clone = n;
12271 node->simd_clones = n;
12273 else
12275 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
12276 clone->prev_clone->simdclone->next_clone = n;
12277 node->simd_clones->simdclone->prev_clone = n;
12279 symtab->change_decl_assembler_name (n->decl, id);
12280 /* And finally adjust the return type, parameters and for
12281 definitions also function body. */
12282 if (node->definition)
12283 simd_clone_adjust (n);
12284 else
12286 simd_clone_adjust_return_type (n);
12287 simd_clone_adjust_argument_types (n);
12291 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
12294 /* Entry point for IPA simd clone creation pass. */
12296 static unsigned int
12297 ipa_omp_simd_clone (void)
12299 struct cgraph_node *node;
12300 FOR_EACH_FUNCTION (node)
12301 expand_simd_clones (node);
12302 return 0;
12305 namespace {
12307 const pass_data pass_data_omp_simd_clone =
12309 SIMPLE_IPA_PASS, /* type */
12310 "simdclone", /* name */
12311 OPTGROUP_NONE, /* optinfo_flags */
12312 TV_NONE, /* tv_id */
12313 ( PROP_ssa | PROP_cfg ), /* properties_required */
12314 0, /* properties_provided */
12315 0, /* properties_destroyed */
12316 0, /* todo_flags_start */
12317 0, /* todo_flags_finish */
12320 class pass_omp_simd_clone : public simple_ipa_opt_pass
12322 public:
12323 pass_omp_simd_clone(gcc::context *ctxt)
12324 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
12327 /* opt_pass methods: */
12328 virtual bool gate (function *);
12329 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
12332 bool
12333 pass_omp_simd_clone::gate (function *)
12335 return ((flag_openmp || flag_openmp_simd
12336 || flag_cilkplus
12337 || (in_lto_p && !flag_wpa))
12338 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
12341 } // anon namespace
12343 simple_ipa_opt_pass *
12344 make_pass_omp_simd_clone (gcc::context *ctxt)
12346 return new pass_omp_simd_clone (ctxt);
12349 #include "gt-omp-low.h"