* gcc.dg/store-motion-fgcse-sm.c (dg-final): Cleanup
[official-gcc.git] / gcc / omp-low.c
blob3924282cae248b4490f1f5f284bbf5c004c6dc5e
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 "predict.h"
33 #include "vec.h"
34 #include "hashtab.h"
35 #include "hash-set.h"
36 #include "machmode.h"
37 #include "hard-reg-set.h"
38 #include "input.h"
39 #include "function.h"
40 #include "dominance.h"
41 #include "cfg.h"
42 #include "cfganal.h"
43 #include "basic-block.h"
44 #include "tree-ssa-alias.h"
45 #include "internal-fn.h"
46 #include "gimple-fold.h"
47 #include "gimple-expr.h"
48 #include "is-a.h"
49 #include "gimple.h"
50 #include "gimplify.h"
51 #include "gimple-iterator.h"
52 #include "gimplify-me.h"
53 #include "gimple-walk.h"
54 #include "tree-iterator.h"
55 #include "tree-inline.h"
56 #include "langhooks.h"
57 #include "diagnostic-core.h"
58 #include "gimple-ssa.h"
59 #include "hash-map.h"
60 #include "plugin-api.h"
61 #include "ipa-ref.h"
62 #include "cgraph.h"
63 #include "tree-cfg.h"
64 #include "tree-phinodes.h"
65 #include "ssa-iterators.h"
66 #include "tree-ssanames.h"
67 #include "tree-into-ssa.h"
68 #include "expr.h"
69 #include "tree-dfa.h"
70 #include "tree-ssa.h"
71 #include "flags.h"
72 #include "expr.h"
73 #include "tree-pass.h"
74 #include "except.h"
75 #include "splay-tree.h"
76 #include "insn-codes.h"
77 #include "optabs.h"
78 #include "cfgloop.h"
79 #include "target.h"
80 #include "common/common-target.h"
81 #include "omp-low.h"
82 #include "gimple-low.h"
83 #include "tree-cfgcleanup.h"
84 #include "pretty-print.h"
85 #include "alloc-pool.h"
86 #include "ipa-prop.h"
87 #include "tree-nested.h"
88 #include "tree-eh.h"
89 #include "cilk.h"
90 #include "context.h"
91 #include "lto-section-names.h"
94 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
95 phases. The first phase scans the function looking for OMP statements
96 and then for variables that must be replaced to satisfy data sharing
97 clauses. The second phase expands code for the constructs, as well as
98 re-gimplifying things when variables have been replaced with complex
99 expressions.
101 Final code generation is done by pass_expand_omp. The flowgraph is
102 scanned for parallel regions which are then moved to a new
103 function, to be invoked by the thread library. */
105 /* Parallel region information. Every parallel and workshare
106 directive is enclosed between two markers, the OMP_* directive
107 and a corresponding OMP_RETURN statement. */
109 struct omp_region
111 /* The enclosing region. */
112 struct omp_region *outer;
114 /* First child region. */
115 struct omp_region *inner;
117 /* Next peer region. */
118 struct omp_region *next;
120 /* Block containing the omp directive as its last stmt. */
121 basic_block entry;
123 /* Block containing the OMP_RETURN as its last stmt. */
124 basic_block exit;
126 /* Block containing the OMP_CONTINUE as its last stmt. */
127 basic_block cont;
129 /* If this is a combined parallel+workshare region, this is a list
130 of additional arguments needed by the combined parallel+workshare
131 library call. */
132 vec<tree, va_gc> *ws_args;
134 /* The code for the omp directive of this region. */
135 enum gimple_code type;
137 /* Schedule kind, only used for OMP_FOR type regions. */
138 enum omp_clause_schedule_kind sched_kind;
140 /* True if this is a combined parallel+workshare region. */
141 bool is_combined_parallel;
144 /* Context structure. Used to store information about each parallel
145 directive in the code. */
147 typedef struct omp_context
149 /* This field must be at the beginning, as we do "inheritance": Some
150 callback functions for tree-inline.c (e.g., omp_copy_decl)
151 receive a copy_body_data pointer that is up-casted to an
152 omp_context pointer. */
153 copy_body_data cb;
155 /* The tree of contexts corresponding to the encountered constructs. */
156 struct omp_context *outer;
157 gimple stmt;
159 /* Map variables to fields in a structure that allows communication
160 between sending and receiving threads. */
161 splay_tree field_map;
162 tree record_type;
163 tree sender_decl;
164 tree receiver_decl;
166 /* These are used just by task contexts, if task firstprivate fn is
167 needed. srecord_type is used to communicate from the thread
168 that encountered the task construct to task firstprivate fn,
169 record_type is allocated by GOMP_task, initialized by task firstprivate
170 fn and passed to the task body fn. */
171 splay_tree sfield_map;
172 tree srecord_type;
174 /* A chain of variables to add to the top-level block surrounding the
175 construct. In the case of a parallel, this is in the child function. */
176 tree block_vars;
178 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
179 barriers should jump to during omplower pass. */
180 tree cancel_label;
182 /* What to do with variables with implicitly determined sharing
183 attributes. */
184 enum omp_clause_default_kind default_kind;
186 /* Nesting depth of this context. Used to beautify error messages re
187 invalid gotos. The outermost ctx is depth 1, with depth 0 being
188 reserved for the main body of the function. */
189 int depth;
191 /* True if this parallel directive is nested within another. */
192 bool is_nested;
194 /* True if this construct can be cancelled. */
195 bool cancellable;
196 } omp_context;
199 struct omp_for_data_loop
201 tree v, n1, n2, step;
202 enum tree_code cond_code;
205 /* A structure describing the main elements of a parallel loop. */
207 struct omp_for_data
209 struct omp_for_data_loop loop;
210 tree chunk_size;
211 gomp_for *for_stmt;
212 tree pre, iter_type;
213 int collapse;
214 bool have_nowait, have_ordered;
215 enum omp_clause_schedule_kind sched_kind;
216 struct omp_for_data_loop *loops;
220 static splay_tree all_contexts;
221 static int taskreg_nesting_level;
222 static int target_nesting_level;
223 static struct omp_region *root_omp_region;
224 static bitmap task_shared_vars;
225 static vec<omp_context *> taskreg_contexts;
227 static void scan_omp (gimple_seq *, omp_context *);
228 static tree scan_omp_1_op (tree *, int *, void *);
230 #define WALK_SUBSTMTS \
231 case GIMPLE_BIND: \
232 case GIMPLE_TRY: \
233 case GIMPLE_CATCH: \
234 case GIMPLE_EH_FILTER: \
235 case GIMPLE_TRANSACTION: \
236 /* The sub-statements for these should be walked. */ \
237 *handled_ops_p = false; \
238 break;
240 /* Holds offload tables with decls. */
241 vec<tree, va_gc> *offload_funcs, *offload_vars;
243 /* Convenience function for calling scan_omp_1_op on tree operands. */
245 static inline tree
246 scan_omp_op (tree *tp, omp_context *ctx)
248 struct walk_stmt_info wi;
250 memset (&wi, 0, sizeof (wi));
251 wi.info = ctx;
252 wi.want_locations = true;
254 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
257 static void lower_omp (gimple_seq *, omp_context *);
258 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
259 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
261 /* Find an OpenMP clause of type KIND within CLAUSES. */
263 tree
264 find_omp_clause (tree clauses, enum omp_clause_code kind)
266 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
267 if (OMP_CLAUSE_CODE (clauses) == kind)
268 return clauses;
270 return NULL_TREE;
273 /* Return true if CTX is for an omp parallel. */
275 static inline bool
276 is_parallel_ctx (omp_context *ctx)
278 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
282 /* Return true if CTX is for an omp target region. */
284 static inline bool
285 is_targetreg_ctx (omp_context *ctx)
287 return gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
288 && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION;
292 /* Return true if CTX is for an omp task. */
294 static inline bool
295 is_task_ctx (omp_context *ctx)
297 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
301 /* Return true if CTX is for an omp parallel or omp task. */
303 static inline bool
304 is_taskreg_ctx (omp_context *ctx)
306 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
307 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
311 /* Return true if REGION is a combined parallel+workshare region. */
313 static inline bool
314 is_combined_parallel (struct omp_region *region)
316 return region->is_combined_parallel;
320 /* Extract the header elements of parallel loop FOR_STMT and store
321 them into *FD. */
323 static void
324 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
325 struct omp_for_data_loop *loops)
327 tree t, var, *collapse_iter, *collapse_count;
328 tree count = NULL_TREE, iter_type = long_integer_type_node;
329 struct omp_for_data_loop *loop;
330 int i;
331 struct omp_for_data_loop dummy_loop;
332 location_t loc = gimple_location (for_stmt);
333 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
334 bool distribute = gimple_omp_for_kind (for_stmt)
335 == GF_OMP_FOR_KIND_DISTRIBUTE;
337 fd->for_stmt = for_stmt;
338 fd->pre = NULL;
339 fd->collapse = gimple_omp_for_collapse (for_stmt);
340 if (fd->collapse > 1)
341 fd->loops = loops;
342 else
343 fd->loops = &fd->loop;
345 fd->have_nowait = distribute || simd;
346 fd->have_ordered = false;
347 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
348 fd->chunk_size = NULL_TREE;
349 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
350 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
351 collapse_iter = NULL;
352 collapse_count = NULL;
354 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
355 switch (OMP_CLAUSE_CODE (t))
357 case OMP_CLAUSE_NOWAIT:
358 fd->have_nowait = true;
359 break;
360 case OMP_CLAUSE_ORDERED:
361 fd->have_ordered = true;
362 break;
363 case OMP_CLAUSE_SCHEDULE:
364 gcc_assert (!distribute);
365 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
366 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
367 break;
368 case OMP_CLAUSE_DIST_SCHEDULE:
369 gcc_assert (distribute);
370 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
371 break;
372 case OMP_CLAUSE_COLLAPSE:
373 if (fd->collapse > 1)
375 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
376 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
378 break;
379 default:
380 break;
383 /* FIXME: for now map schedule(auto) to schedule(static).
384 There should be analysis to determine whether all iterations
385 are approximately the same amount of work (then schedule(static)
386 is best) or if it varies (then schedule(dynamic,N) is better). */
387 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
389 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
390 gcc_assert (fd->chunk_size == NULL);
392 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
393 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
394 gcc_assert (fd->chunk_size == NULL);
395 else if (fd->chunk_size == NULL)
397 /* We only need to compute a default chunk size for ordered
398 static loops and dynamic loops. */
399 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
400 || fd->have_ordered)
401 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
402 ? integer_zero_node : integer_one_node;
405 for (i = 0; i < fd->collapse; i++)
407 if (fd->collapse == 1)
408 loop = &fd->loop;
409 else if (loops != NULL)
410 loop = loops + i;
411 else
412 loop = &dummy_loop;
414 loop->v = gimple_omp_for_index (for_stmt, i);
415 gcc_assert (SSA_VAR_P (loop->v));
416 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
417 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
418 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
419 loop->n1 = gimple_omp_for_initial (for_stmt, i);
421 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
422 loop->n2 = gimple_omp_for_final (for_stmt, i);
423 switch (loop->cond_code)
425 case LT_EXPR:
426 case GT_EXPR:
427 break;
428 case NE_EXPR:
429 gcc_assert (gimple_omp_for_kind (for_stmt)
430 == GF_OMP_FOR_KIND_CILKSIMD
431 || (gimple_omp_for_kind (for_stmt)
432 == GF_OMP_FOR_KIND_CILKFOR));
433 break;
434 case LE_EXPR:
435 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
436 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
437 else
438 loop->n2 = fold_build2_loc (loc,
439 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
440 build_int_cst (TREE_TYPE (loop->n2), 1));
441 loop->cond_code = LT_EXPR;
442 break;
443 case GE_EXPR:
444 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
445 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
446 else
447 loop->n2 = fold_build2_loc (loc,
448 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
449 build_int_cst (TREE_TYPE (loop->n2), 1));
450 loop->cond_code = GT_EXPR;
451 break;
452 default:
453 gcc_unreachable ();
456 t = gimple_omp_for_incr (for_stmt, i);
457 gcc_assert (TREE_OPERAND (t, 0) == var);
458 switch (TREE_CODE (t))
460 case PLUS_EXPR:
461 loop->step = TREE_OPERAND (t, 1);
462 break;
463 case POINTER_PLUS_EXPR:
464 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
465 break;
466 case MINUS_EXPR:
467 loop->step = TREE_OPERAND (t, 1);
468 loop->step = fold_build1_loc (loc,
469 NEGATE_EXPR, TREE_TYPE (loop->step),
470 loop->step);
471 break;
472 default:
473 gcc_unreachable ();
476 if (simd
477 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
478 && !fd->have_ordered))
480 if (fd->collapse == 1)
481 iter_type = TREE_TYPE (loop->v);
482 else if (i == 0
483 || TYPE_PRECISION (iter_type)
484 < TYPE_PRECISION (TREE_TYPE (loop->v)))
485 iter_type
486 = build_nonstandard_integer_type
487 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
489 else if (iter_type != long_long_unsigned_type_node)
491 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
492 iter_type = long_long_unsigned_type_node;
493 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
494 && TYPE_PRECISION (TREE_TYPE (loop->v))
495 >= TYPE_PRECISION (iter_type))
497 tree n;
499 if (loop->cond_code == LT_EXPR)
500 n = fold_build2_loc (loc,
501 PLUS_EXPR, TREE_TYPE (loop->v),
502 loop->n2, loop->step);
503 else
504 n = loop->n1;
505 if (TREE_CODE (n) != INTEGER_CST
506 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
507 iter_type = long_long_unsigned_type_node;
509 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
510 > TYPE_PRECISION (iter_type))
512 tree n1, n2;
514 if (loop->cond_code == LT_EXPR)
516 n1 = loop->n1;
517 n2 = fold_build2_loc (loc,
518 PLUS_EXPR, TREE_TYPE (loop->v),
519 loop->n2, loop->step);
521 else
523 n1 = fold_build2_loc (loc,
524 MINUS_EXPR, TREE_TYPE (loop->v),
525 loop->n2, loop->step);
526 n2 = loop->n1;
528 if (TREE_CODE (n1) != INTEGER_CST
529 || TREE_CODE (n2) != INTEGER_CST
530 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
531 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
532 iter_type = long_long_unsigned_type_node;
536 if (collapse_count && *collapse_count == NULL)
538 t = fold_binary (loop->cond_code, boolean_type_node,
539 fold_convert (TREE_TYPE (loop->v), loop->n1),
540 fold_convert (TREE_TYPE (loop->v), loop->n2));
541 if (t && integer_zerop (t))
542 count = build_zero_cst (long_long_unsigned_type_node);
543 else if ((i == 0 || count != NULL_TREE)
544 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
545 && TREE_CONSTANT (loop->n1)
546 && TREE_CONSTANT (loop->n2)
547 && TREE_CODE (loop->step) == INTEGER_CST)
549 tree itype = TREE_TYPE (loop->v);
551 if (POINTER_TYPE_P (itype))
552 itype = signed_type_for (itype);
553 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
554 t = fold_build2_loc (loc,
555 PLUS_EXPR, itype,
556 fold_convert_loc (loc, itype, loop->step), t);
557 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
558 fold_convert_loc (loc, itype, loop->n2));
559 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
560 fold_convert_loc (loc, itype, loop->n1));
561 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
562 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
563 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
564 fold_build1_loc (loc, NEGATE_EXPR, itype,
565 fold_convert_loc (loc, itype,
566 loop->step)));
567 else
568 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
569 fold_convert_loc (loc, itype, loop->step));
570 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
571 if (count != NULL_TREE)
572 count = fold_build2_loc (loc,
573 MULT_EXPR, long_long_unsigned_type_node,
574 count, t);
575 else
576 count = t;
577 if (TREE_CODE (count) != INTEGER_CST)
578 count = NULL_TREE;
580 else if (count && !integer_zerop (count))
581 count = NULL_TREE;
585 if (count
586 && !simd
587 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
588 || fd->have_ordered))
590 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
591 iter_type = long_long_unsigned_type_node;
592 else
593 iter_type = long_integer_type_node;
595 else if (collapse_iter && *collapse_iter != NULL)
596 iter_type = TREE_TYPE (*collapse_iter);
597 fd->iter_type = iter_type;
598 if (collapse_iter && *collapse_iter == NULL)
599 *collapse_iter = create_tmp_var (iter_type, ".iter");
600 if (collapse_count && *collapse_count == NULL)
602 if (count)
603 *collapse_count = fold_convert_loc (loc, iter_type, count);
604 else
605 *collapse_count = create_tmp_var (iter_type, ".count");
608 if (fd->collapse > 1)
610 fd->loop.v = *collapse_iter;
611 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
612 fd->loop.n2 = *collapse_count;
613 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
614 fd->loop.cond_code = LT_EXPR;
619 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
620 is the immediate dominator of PAR_ENTRY_BB, return true if there
621 are no data dependencies that would prevent expanding the parallel
622 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
624 When expanding a combined parallel+workshare region, the call to
625 the child function may need additional arguments in the case of
626 GIMPLE_OMP_FOR regions. In some cases, these arguments are
627 computed out of variables passed in from the parent to the child
628 via 'struct .omp_data_s'. For instance:
630 #pragma omp parallel for schedule (guided, i * 4)
631 for (j ...)
633 Is lowered into:
635 # BLOCK 2 (PAR_ENTRY_BB)
636 .omp_data_o.i = i;
637 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
639 # BLOCK 3 (WS_ENTRY_BB)
640 .omp_data_i = &.omp_data_o;
641 D.1667 = .omp_data_i->i;
642 D.1598 = D.1667 * 4;
643 #pragma omp for schedule (guided, D.1598)
645 When we outline the parallel region, the call to the child function
646 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
647 that value is computed *after* the call site. So, in principle we
648 cannot do the transformation.
650 To see whether the code in WS_ENTRY_BB blocks the combined
651 parallel+workshare call, we collect all the variables used in the
652 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
653 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
654 call.
656 FIXME. If we had the SSA form built at this point, we could merely
657 hoist the code in block 3 into block 2 and be done with it. But at
658 this point we don't have dataflow information and though we could
659 hack something up here, it is really not worth the aggravation. */
661 static bool
662 workshare_safe_to_combine_p (basic_block ws_entry_bb)
664 struct omp_for_data fd;
665 gimple ws_stmt = last_stmt (ws_entry_bb);
667 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
668 return true;
670 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
672 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
674 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
675 return false;
676 if (fd.iter_type != long_integer_type_node)
677 return false;
679 /* FIXME. We give up too easily here. If any of these arguments
680 are not constants, they will likely involve variables that have
681 been mapped into fields of .omp_data_s for sharing with the child
682 function. With appropriate data flow, it would be possible to
683 see through this. */
684 if (!is_gimple_min_invariant (fd.loop.n1)
685 || !is_gimple_min_invariant (fd.loop.n2)
686 || !is_gimple_min_invariant (fd.loop.step)
687 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
688 return false;
690 return true;
694 /* Collect additional arguments needed to emit a combined
695 parallel+workshare call. WS_STMT is the workshare directive being
696 expanded. */
698 static vec<tree, va_gc> *
699 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
701 tree t;
702 location_t loc = gimple_location (ws_stmt);
703 vec<tree, va_gc> *ws_args;
705 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
707 struct omp_for_data fd;
708 tree n1, n2;
710 extract_omp_for_data (for_stmt, &fd, NULL);
711 n1 = fd.loop.n1;
712 n2 = fd.loop.n2;
714 if (gimple_omp_for_combined_into_p (for_stmt))
716 tree innerc
717 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
718 OMP_CLAUSE__LOOPTEMP_);
719 gcc_assert (innerc);
720 n1 = OMP_CLAUSE_DECL (innerc);
721 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
722 OMP_CLAUSE__LOOPTEMP_);
723 gcc_assert (innerc);
724 n2 = OMP_CLAUSE_DECL (innerc);
727 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
729 t = fold_convert_loc (loc, long_integer_type_node, n1);
730 ws_args->quick_push (t);
732 t = fold_convert_loc (loc, long_integer_type_node, n2);
733 ws_args->quick_push (t);
735 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
736 ws_args->quick_push (t);
738 if (fd.chunk_size)
740 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
741 ws_args->quick_push (t);
744 return ws_args;
746 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
748 /* Number of sections is equal to the number of edges from the
749 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
750 the exit of the sections region. */
751 basic_block bb = single_succ (gimple_bb (ws_stmt));
752 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
753 vec_alloc (ws_args, 1);
754 ws_args->quick_push (t);
755 return ws_args;
758 gcc_unreachable ();
762 /* Discover whether REGION is a combined parallel+workshare region. */
764 static void
765 determine_parallel_type (struct omp_region *region)
767 basic_block par_entry_bb, par_exit_bb;
768 basic_block ws_entry_bb, ws_exit_bb;
770 if (region == NULL || region->inner == NULL
771 || region->exit == NULL || region->inner->exit == NULL
772 || region->inner->cont == NULL)
773 return;
775 /* We only support parallel+for and parallel+sections. */
776 if (region->type != GIMPLE_OMP_PARALLEL
777 || (region->inner->type != GIMPLE_OMP_FOR
778 && region->inner->type != GIMPLE_OMP_SECTIONS))
779 return;
781 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
782 WS_EXIT_BB -> PAR_EXIT_BB. */
783 par_entry_bb = region->entry;
784 par_exit_bb = region->exit;
785 ws_entry_bb = region->inner->entry;
786 ws_exit_bb = region->inner->exit;
788 if (single_succ (par_entry_bb) == ws_entry_bb
789 && single_succ (ws_exit_bb) == par_exit_bb
790 && workshare_safe_to_combine_p (ws_entry_bb)
791 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
792 || (last_and_only_stmt (ws_entry_bb)
793 && last_and_only_stmt (par_exit_bb))))
795 gimple par_stmt = last_stmt (par_entry_bb);
796 gimple ws_stmt = last_stmt (ws_entry_bb);
798 if (region->inner->type == GIMPLE_OMP_FOR)
800 /* If this is a combined parallel loop, we need to determine
801 whether or not to use the combined library calls. There
802 are two cases where we do not apply the transformation:
803 static loops and any kind of ordered loop. In the first
804 case, we already open code the loop so there is no need
805 to do anything else. In the latter case, the combined
806 parallel loop call would still need extra synchronization
807 to implement ordered semantics, so there would not be any
808 gain in using the combined call. */
809 tree clauses = gimple_omp_for_clauses (ws_stmt);
810 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
811 if (c == NULL
812 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
813 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
815 region->is_combined_parallel = false;
816 region->inner->is_combined_parallel = false;
817 return;
821 region->is_combined_parallel = true;
822 region->inner->is_combined_parallel = true;
823 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
828 /* Return true if EXPR is variable sized. */
830 static inline bool
831 is_variable_sized (const_tree expr)
833 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
836 /* Return true if DECL is a reference type. */
838 static inline bool
839 is_reference (tree decl)
841 return lang_hooks.decls.omp_privatize_by_reference (decl);
844 /* Lookup variables in the decl or field splay trees. The "maybe" form
845 allows for the variable form to not have been entered, otherwise we
846 assert that the variable must have been entered. */
848 static inline tree
849 lookup_decl (tree var, omp_context *ctx)
851 tree *n = ctx->cb.decl_map->get (var);
852 return *n;
855 static inline tree
856 maybe_lookup_decl (const_tree var, omp_context *ctx)
858 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
859 return n ? *n : NULL_TREE;
862 static inline tree
863 lookup_field (tree var, omp_context *ctx)
865 splay_tree_node n;
866 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
867 return (tree) n->value;
870 static inline tree
871 lookup_sfield (tree var, omp_context *ctx)
873 splay_tree_node n;
874 n = splay_tree_lookup (ctx->sfield_map
875 ? ctx->sfield_map : ctx->field_map,
876 (splay_tree_key) var);
877 return (tree) n->value;
880 static inline tree
881 maybe_lookup_field (tree var, omp_context *ctx)
883 splay_tree_node n;
884 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
885 return n ? (tree) n->value : NULL_TREE;
888 /* Return true if DECL should be copied by pointer. SHARED_CTX is
889 the parallel context if DECL is to be shared. */
891 static bool
892 use_pointer_for_field (tree decl, omp_context *shared_ctx)
894 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
895 return true;
897 /* We can only use copy-in/copy-out semantics for shared variables
898 when we know the value is not accessible from an outer scope. */
899 if (shared_ctx)
901 /* ??? Trivially accessible from anywhere. But why would we even
902 be passing an address in this case? Should we simply assert
903 this to be false, or should we have a cleanup pass that removes
904 these from the list of mappings? */
905 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
906 return true;
908 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
909 without analyzing the expression whether or not its location
910 is accessible to anyone else. In the case of nested parallel
911 regions it certainly may be. */
912 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
913 return true;
915 /* Do not use copy-in/copy-out for variables that have their
916 address taken. */
917 if (TREE_ADDRESSABLE (decl))
918 return true;
920 /* lower_send_shared_vars only uses copy-in, but not copy-out
921 for these. */
922 if (TREE_READONLY (decl)
923 || ((TREE_CODE (decl) == RESULT_DECL
924 || TREE_CODE (decl) == PARM_DECL)
925 && DECL_BY_REFERENCE (decl)))
926 return false;
928 /* Disallow copy-in/out in nested parallel if
929 decl is shared in outer parallel, otherwise
930 each thread could store the shared variable
931 in its own copy-in location, making the
932 variable no longer really shared. */
933 if (shared_ctx->is_nested)
935 omp_context *up;
937 for (up = shared_ctx->outer; up; up = up->outer)
938 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
939 break;
941 if (up)
943 tree c;
945 for (c = gimple_omp_taskreg_clauses (up->stmt);
946 c; c = OMP_CLAUSE_CHAIN (c))
947 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
948 && OMP_CLAUSE_DECL (c) == decl)
949 break;
951 if (c)
952 goto maybe_mark_addressable_and_ret;
956 /* For tasks avoid using copy-in/out. As tasks can be
957 deferred or executed in different thread, when GOMP_task
958 returns, the task hasn't necessarily terminated. */
959 if (is_task_ctx (shared_ctx))
961 tree outer;
962 maybe_mark_addressable_and_ret:
963 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
964 if (is_gimple_reg (outer))
966 /* Taking address of OUTER in lower_send_shared_vars
967 might need regimplification of everything that uses the
968 variable. */
969 if (!task_shared_vars)
970 task_shared_vars = BITMAP_ALLOC (NULL);
971 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
972 TREE_ADDRESSABLE (outer) = 1;
974 return true;
978 return false;
981 /* Construct a new automatic decl similar to VAR. */
983 static tree
984 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
986 tree copy = copy_var_decl (var, name, type);
988 DECL_CONTEXT (copy) = current_function_decl;
989 DECL_CHAIN (copy) = ctx->block_vars;
990 ctx->block_vars = copy;
992 return copy;
995 static tree
996 omp_copy_decl_1 (tree var, omp_context *ctx)
998 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1001 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1002 as appropriate. */
1003 static tree
1004 omp_build_component_ref (tree obj, tree field)
1006 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1007 if (TREE_THIS_VOLATILE (field))
1008 TREE_THIS_VOLATILE (ret) |= 1;
1009 if (TREE_READONLY (field))
1010 TREE_READONLY (ret) |= 1;
1011 return ret;
1014 /* Build tree nodes to access the field for VAR on the receiver side. */
1016 static tree
1017 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1019 tree x, field = lookup_field (var, ctx);
1021 /* If the receiver record type was remapped in the child function,
1022 remap the field into the new record type. */
1023 x = maybe_lookup_field (field, ctx);
1024 if (x != NULL)
1025 field = x;
1027 x = build_simple_mem_ref (ctx->receiver_decl);
1028 x = omp_build_component_ref (x, field);
1029 if (by_ref)
1030 x = build_simple_mem_ref (x);
1032 return x;
1035 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1036 of a parallel, this is a component reference; for workshare constructs
1037 this is some variable. */
1039 static tree
1040 build_outer_var_ref (tree var, omp_context *ctx)
1042 tree x;
1044 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1045 x = var;
1046 else if (is_variable_sized (var))
1048 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1049 x = build_outer_var_ref (x, ctx);
1050 x = build_simple_mem_ref (x);
1052 else if (is_taskreg_ctx (ctx))
1054 bool by_ref = use_pointer_for_field (var, NULL);
1055 x = build_receiver_ref (var, by_ref, ctx);
1057 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1058 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1060 /* #pragma omp simd isn't a worksharing construct, and can reference even
1061 private vars in its linear etc. clauses. */
1062 x = NULL_TREE;
1063 if (ctx->outer && is_taskreg_ctx (ctx))
1064 x = lookup_decl (var, ctx->outer);
1065 else if (ctx->outer)
1066 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1067 if (x == NULL_TREE)
1068 x = var;
1070 else if (ctx->outer)
1071 x = lookup_decl (var, ctx->outer);
1072 else if (is_reference (var))
1073 /* This can happen with orphaned constructs. If var is reference, it is
1074 possible it is shared and as such valid. */
1075 x = var;
1076 else
1077 gcc_unreachable ();
1079 if (is_reference (var))
1080 x = build_simple_mem_ref (x);
1082 return x;
1085 /* Build tree nodes to access the field for VAR on the sender side. */
1087 static tree
1088 build_sender_ref (tree var, omp_context *ctx)
1090 tree field = lookup_sfield (var, ctx);
1091 return omp_build_component_ref (ctx->sender_decl, field);
1094 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1096 static void
1097 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1099 tree field, type, sfield = NULL_TREE;
1101 gcc_assert ((mask & 1) == 0
1102 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1103 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1104 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1106 type = TREE_TYPE (var);
1107 if (mask & 4)
1109 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1110 type = build_pointer_type (build_pointer_type (type));
1112 else if (by_ref)
1113 type = build_pointer_type (type);
1114 else if ((mask & 3) == 1 && is_reference (var))
1115 type = TREE_TYPE (type);
1117 field = build_decl (DECL_SOURCE_LOCATION (var),
1118 FIELD_DECL, DECL_NAME (var), type);
1120 /* Remember what variable this field was created for. This does have a
1121 side effect of making dwarf2out ignore this member, so for helpful
1122 debugging we clear it later in delete_omp_context. */
1123 DECL_ABSTRACT_ORIGIN (field) = var;
1124 if (type == TREE_TYPE (var))
1126 DECL_ALIGN (field) = DECL_ALIGN (var);
1127 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1128 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1130 else
1131 DECL_ALIGN (field) = TYPE_ALIGN (type);
1133 if ((mask & 3) == 3)
1135 insert_field_into_struct (ctx->record_type, field);
1136 if (ctx->srecord_type)
1138 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1139 FIELD_DECL, DECL_NAME (var), type);
1140 DECL_ABSTRACT_ORIGIN (sfield) = var;
1141 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1142 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1143 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1144 insert_field_into_struct (ctx->srecord_type, sfield);
1147 else
1149 if (ctx->srecord_type == NULL_TREE)
1151 tree t;
1153 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1154 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1155 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1157 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1158 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1159 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1160 insert_field_into_struct (ctx->srecord_type, sfield);
1161 splay_tree_insert (ctx->sfield_map,
1162 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1163 (splay_tree_value) sfield);
1166 sfield = field;
1167 insert_field_into_struct ((mask & 1) ? ctx->record_type
1168 : ctx->srecord_type, field);
1171 if (mask & 1)
1172 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1173 (splay_tree_value) field);
1174 if ((mask & 2) && ctx->sfield_map)
1175 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1176 (splay_tree_value) sfield);
1179 static tree
1180 install_var_local (tree var, omp_context *ctx)
1182 tree new_var = omp_copy_decl_1 (var, ctx);
1183 insert_decl_map (&ctx->cb, var, new_var);
1184 return new_var;
1187 /* Adjust the replacement for DECL in CTX for the new context. This means
1188 copying the DECL_VALUE_EXPR, and fixing up the type. */
1190 static void
1191 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1193 tree new_decl, size;
1195 new_decl = lookup_decl (decl, ctx);
1197 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1199 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1200 && DECL_HAS_VALUE_EXPR_P (decl))
1202 tree ve = DECL_VALUE_EXPR (decl);
1203 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1204 SET_DECL_VALUE_EXPR (new_decl, ve);
1205 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1208 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1210 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1211 if (size == error_mark_node)
1212 size = TYPE_SIZE (TREE_TYPE (new_decl));
1213 DECL_SIZE (new_decl) = size;
1215 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1216 if (size == error_mark_node)
1217 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1218 DECL_SIZE_UNIT (new_decl) = size;
1222 /* The callback for remap_decl. Search all containing contexts for a
1223 mapping of the variable; this avoids having to duplicate the splay
1224 tree ahead of time. We know a mapping doesn't already exist in the
1225 given context. Create new mappings to implement default semantics. */
1227 static tree
1228 omp_copy_decl (tree var, copy_body_data *cb)
1230 omp_context *ctx = (omp_context *) cb;
1231 tree new_var;
1233 if (TREE_CODE (var) == LABEL_DECL)
1235 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1236 DECL_CONTEXT (new_var) = current_function_decl;
1237 insert_decl_map (&ctx->cb, var, new_var);
1238 return new_var;
1241 while (!is_taskreg_ctx (ctx))
1243 ctx = ctx->outer;
1244 if (ctx == NULL)
1245 return var;
1246 new_var = maybe_lookup_decl (var, ctx);
1247 if (new_var)
1248 return new_var;
1251 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1252 return var;
1254 return error_mark_node;
1258 /* Debugging dumps for parallel regions. */
1259 void dump_omp_region (FILE *, struct omp_region *, int);
1260 void debug_omp_region (struct omp_region *);
1261 void debug_all_omp_regions (void);
1263 /* Dump the parallel region tree rooted at REGION. */
1265 void
1266 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1268 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1269 gimple_code_name[region->type]);
1271 if (region->inner)
1272 dump_omp_region (file, region->inner, indent + 4);
1274 if (region->cont)
1276 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1277 region->cont->index);
1280 if (region->exit)
1281 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1282 region->exit->index);
1283 else
1284 fprintf (file, "%*s[no exit marker]\n", indent, "");
1286 if (region->next)
1287 dump_omp_region (file, region->next, indent);
1290 DEBUG_FUNCTION void
1291 debug_omp_region (struct omp_region *region)
1293 dump_omp_region (stderr, region, 0);
1296 DEBUG_FUNCTION void
1297 debug_all_omp_regions (void)
1299 dump_omp_region (stderr, root_omp_region, 0);
1303 /* Create a new parallel region starting at STMT inside region PARENT. */
1305 static struct omp_region *
1306 new_omp_region (basic_block bb, enum gimple_code type,
1307 struct omp_region *parent)
1309 struct omp_region *region = XCNEW (struct omp_region);
1311 region->outer = parent;
1312 region->entry = bb;
1313 region->type = type;
1315 if (parent)
1317 /* This is a nested region. Add it to the list of inner
1318 regions in PARENT. */
1319 region->next = parent->inner;
1320 parent->inner = region;
1322 else
1324 /* This is a toplevel region. Add it to the list of toplevel
1325 regions in ROOT_OMP_REGION. */
1326 region->next = root_omp_region;
1327 root_omp_region = region;
1330 return region;
1333 /* Release the memory associated with the region tree rooted at REGION. */
1335 static void
1336 free_omp_region_1 (struct omp_region *region)
1338 struct omp_region *i, *n;
1340 for (i = region->inner; i ; i = n)
1342 n = i->next;
1343 free_omp_region_1 (i);
1346 free (region);
1349 /* Release the memory for the entire omp region tree. */
1351 void
1352 free_omp_regions (void)
1354 struct omp_region *r, *n;
1355 for (r = root_omp_region; r ; r = n)
1357 n = r->next;
1358 free_omp_region_1 (r);
1360 root_omp_region = NULL;
1364 /* Create a new context, with OUTER_CTX being the surrounding context. */
1366 static omp_context *
1367 new_omp_context (gimple stmt, omp_context *outer_ctx)
1369 omp_context *ctx = XCNEW (omp_context);
1371 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1372 (splay_tree_value) ctx);
1373 ctx->stmt = stmt;
1375 if (outer_ctx)
1377 ctx->outer = outer_ctx;
1378 ctx->cb = outer_ctx->cb;
1379 ctx->cb.block = NULL;
1380 ctx->depth = outer_ctx->depth + 1;
1382 else
1384 ctx->cb.src_fn = current_function_decl;
1385 ctx->cb.dst_fn = current_function_decl;
1386 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1387 gcc_checking_assert (ctx->cb.src_node);
1388 ctx->cb.dst_node = ctx->cb.src_node;
1389 ctx->cb.src_cfun = cfun;
1390 ctx->cb.copy_decl = omp_copy_decl;
1391 ctx->cb.eh_lp_nr = 0;
1392 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1393 ctx->depth = 1;
1396 ctx->cb.decl_map = new hash_map<tree, tree>;
1398 return ctx;
1401 static gimple_seq maybe_catch_exception (gimple_seq);
1403 /* Finalize task copyfn. */
1405 static void
1406 finalize_task_copyfn (gomp_task *task_stmt)
1408 struct function *child_cfun;
1409 tree child_fn;
1410 gimple_seq seq = NULL, new_seq;
1411 gbind *bind;
1413 child_fn = gimple_omp_task_copy_fn (task_stmt);
1414 if (child_fn == NULL_TREE)
1415 return;
1417 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1418 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1420 push_cfun (child_cfun);
1421 bind = gimplify_body (child_fn, false);
1422 gimple_seq_add_stmt (&seq, bind);
1423 new_seq = maybe_catch_exception (seq);
1424 if (new_seq != seq)
1426 bind = gimple_build_bind (NULL, new_seq, NULL);
1427 seq = NULL;
1428 gimple_seq_add_stmt (&seq, bind);
1430 gimple_set_body (child_fn, seq);
1431 pop_cfun ();
1433 /* Inform the callgraph about the new function. */
1434 cgraph_node::add_new_function (child_fn, false);
1437 /* Destroy a omp_context data structures. Called through the splay tree
1438 value delete callback. */
1440 static void
1441 delete_omp_context (splay_tree_value value)
1443 omp_context *ctx = (omp_context *) value;
1445 delete ctx->cb.decl_map;
1447 if (ctx->field_map)
1448 splay_tree_delete (ctx->field_map);
1449 if (ctx->sfield_map)
1450 splay_tree_delete (ctx->sfield_map);
1452 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1453 it produces corrupt debug information. */
1454 if (ctx->record_type)
1456 tree t;
1457 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1458 DECL_ABSTRACT_ORIGIN (t) = NULL;
1460 if (ctx->srecord_type)
1462 tree t;
1463 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1464 DECL_ABSTRACT_ORIGIN (t) = NULL;
1467 if (is_task_ctx (ctx))
1468 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1470 XDELETE (ctx);
1473 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1474 context. */
1476 static void
1477 fixup_child_record_type (omp_context *ctx)
1479 tree f, type = ctx->record_type;
1481 /* ??? It isn't sufficient to just call remap_type here, because
1482 variably_modified_type_p doesn't work the way we expect for
1483 record types. Testing each field for whether it needs remapping
1484 and creating a new record by hand works, however. */
1485 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1486 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1487 break;
1488 if (f)
1490 tree name, new_fields = NULL;
1492 type = lang_hooks.types.make_type (RECORD_TYPE);
1493 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1494 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1495 TYPE_DECL, name, type);
1496 TYPE_NAME (type) = name;
1498 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1500 tree new_f = copy_node (f);
1501 DECL_CONTEXT (new_f) = type;
1502 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1503 DECL_CHAIN (new_f) = new_fields;
1504 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1505 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1506 &ctx->cb, NULL);
1507 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1508 &ctx->cb, NULL);
1509 new_fields = new_f;
1511 /* Arrange to be able to look up the receiver field
1512 given the sender field. */
1513 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1514 (splay_tree_value) new_f);
1516 TYPE_FIELDS (type) = nreverse (new_fields);
1517 layout_type (type);
1520 TREE_TYPE (ctx->receiver_decl)
1521 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1524 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1525 specified by CLAUSES. */
1527 static void
1528 scan_sharing_clauses (tree clauses, omp_context *ctx)
1530 tree c, decl;
1531 bool scan_array_reductions = false;
1533 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1535 bool by_ref;
1537 switch (OMP_CLAUSE_CODE (c))
1539 case OMP_CLAUSE_PRIVATE:
1540 decl = OMP_CLAUSE_DECL (c);
1541 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1542 goto do_private;
1543 else if (!is_variable_sized (decl))
1544 install_var_local (decl, ctx);
1545 break;
1547 case OMP_CLAUSE_SHARED:
1548 decl = OMP_CLAUSE_DECL (c);
1549 /* Ignore shared directives in teams construct. */
1550 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1552 /* Global variables don't need to be copied,
1553 the receiver side will use them directly. */
1554 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1555 if (is_global_var (odecl))
1556 break;
1557 insert_decl_map (&ctx->cb, decl, odecl);
1558 break;
1560 gcc_assert (is_taskreg_ctx (ctx));
1561 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1562 || !is_variable_sized (decl));
1563 /* Global variables don't need to be copied,
1564 the receiver side will use them directly. */
1565 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1566 break;
1567 by_ref = use_pointer_for_field (decl, ctx);
1568 if (! TREE_READONLY (decl)
1569 || TREE_ADDRESSABLE (decl)
1570 || by_ref
1571 || is_reference (decl))
1573 install_var_field (decl, by_ref, 3, ctx);
1574 install_var_local (decl, ctx);
1575 break;
1577 /* We don't need to copy const scalar vars back. */
1578 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1579 goto do_private;
1581 case OMP_CLAUSE_LASTPRIVATE:
1582 /* Let the corresponding firstprivate clause create
1583 the variable. */
1584 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1585 break;
1586 /* FALLTHRU */
1588 case OMP_CLAUSE_FIRSTPRIVATE:
1589 case OMP_CLAUSE_REDUCTION:
1590 case OMP_CLAUSE_LINEAR:
1591 decl = OMP_CLAUSE_DECL (c);
1592 do_private:
1593 if (is_variable_sized (decl))
1595 if (is_task_ctx (ctx))
1596 install_var_field (decl, false, 1, ctx);
1597 break;
1599 else if (is_taskreg_ctx (ctx))
1601 bool global
1602 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1603 by_ref = use_pointer_for_field (decl, NULL);
1605 if (is_task_ctx (ctx)
1606 && (global || by_ref || is_reference (decl)))
1608 install_var_field (decl, false, 1, ctx);
1609 if (!global)
1610 install_var_field (decl, by_ref, 2, ctx);
1612 else if (!global)
1613 install_var_field (decl, by_ref, 3, ctx);
1615 install_var_local (decl, ctx);
1616 break;
1618 case OMP_CLAUSE__LOOPTEMP_:
1619 gcc_assert (is_parallel_ctx (ctx));
1620 decl = OMP_CLAUSE_DECL (c);
1621 install_var_field (decl, false, 3, ctx);
1622 install_var_local (decl, ctx);
1623 break;
1625 case OMP_CLAUSE_COPYPRIVATE:
1626 case OMP_CLAUSE_COPYIN:
1627 decl = OMP_CLAUSE_DECL (c);
1628 by_ref = use_pointer_for_field (decl, NULL);
1629 install_var_field (decl, by_ref, 3, ctx);
1630 break;
1632 case OMP_CLAUSE_DEFAULT:
1633 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1634 break;
1636 case OMP_CLAUSE_FINAL:
1637 case OMP_CLAUSE_IF:
1638 case OMP_CLAUSE_NUM_THREADS:
1639 case OMP_CLAUSE_NUM_TEAMS:
1640 case OMP_CLAUSE_THREAD_LIMIT:
1641 case OMP_CLAUSE_DEVICE:
1642 case OMP_CLAUSE_SCHEDULE:
1643 case OMP_CLAUSE_DIST_SCHEDULE:
1644 case OMP_CLAUSE_DEPEND:
1645 case OMP_CLAUSE__CILK_FOR_COUNT_:
1646 if (ctx->outer)
1647 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1648 break;
1650 case OMP_CLAUSE_TO:
1651 case OMP_CLAUSE_FROM:
1652 case OMP_CLAUSE_MAP:
1653 if (ctx->outer)
1654 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1655 decl = OMP_CLAUSE_DECL (c);
1656 /* Global variables with "omp declare target" attribute
1657 don't need to be copied, the receiver side will use them
1658 directly. */
1659 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1660 && DECL_P (decl)
1661 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1662 && varpool_node::get_create (decl)->offloadable)
1663 break;
1664 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1665 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1667 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1668 #pragma omp target data, there is nothing to map for
1669 those. */
1670 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1671 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1672 break;
1674 if (DECL_P (decl))
1676 if (DECL_SIZE (decl)
1677 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1679 tree decl2 = DECL_VALUE_EXPR (decl);
1680 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1681 decl2 = TREE_OPERAND (decl2, 0);
1682 gcc_assert (DECL_P (decl2));
1683 install_var_field (decl2, true, 3, ctx);
1684 install_var_local (decl2, ctx);
1685 install_var_local (decl, ctx);
1687 else
1689 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1690 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1691 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1692 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1693 install_var_field (decl, true, 7, ctx);
1694 else
1695 install_var_field (decl, true, 3, ctx);
1696 if (gimple_omp_target_kind (ctx->stmt)
1697 == GF_OMP_TARGET_KIND_REGION)
1698 install_var_local (decl, ctx);
1701 else
1703 tree base = get_base_address (decl);
1704 tree nc = OMP_CLAUSE_CHAIN (c);
1705 if (DECL_P (base)
1706 && nc != NULL_TREE
1707 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1708 && OMP_CLAUSE_DECL (nc) == base
1709 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1710 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1712 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1713 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1715 else
1717 if (ctx->outer)
1719 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1720 decl = OMP_CLAUSE_DECL (c);
1722 gcc_assert (!splay_tree_lookup (ctx->field_map,
1723 (splay_tree_key) decl));
1724 tree field
1725 = build_decl (OMP_CLAUSE_LOCATION (c),
1726 FIELD_DECL, NULL_TREE, ptr_type_node);
1727 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1728 insert_field_into_struct (ctx->record_type, field);
1729 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1730 (splay_tree_value) field);
1733 break;
1735 case OMP_CLAUSE_NOWAIT:
1736 case OMP_CLAUSE_ORDERED:
1737 case OMP_CLAUSE_COLLAPSE:
1738 case OMP_CLAUSE_UNTIED:
1739 case OMP_CLAUSE_MERGEABLE:
1740 case OMP_CLAUSE_PROC_BIND:
1741 case OMP_CLAUSE_SAFELEN:
1742 break;
1744 case OMP_CLAUSE_ALIGNED:
1745 decl = OMP_CLAUSE_DECL (c);
1746 if (is_global_var (decl)
1747 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1748 install_var_local (decl, ctx);
1749 break;
1751 default:
1752 gcc_unreachable ();
1756 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1758 switch (OMP_CLAUSE_CODE (c))
1760 case OMP_CLAUSE_LASTPRIVATE:
1761 /* Let the corresponding firstprivate clause create
1762 the variable. */
1763 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1764 scan_array_reductions = true;
1765 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1766 break;
1767 /* FALLTHRU */
1769 case OMP_CLAUSE_PRIVATE:
1770 case OMP_CLAUSE_FIRSTPRIVATE:
1771 case OMP_CLAUSE_REDUCTION:
1772 case OMP_CLAUSE_LINEAR:
1773 decl = OMP_CLAUSE_DECL (c);
1774 if (is_variable_sized (decl))
1775 install_var_local (decl, ctx);
1776 fixup_remapped_decl (decl, ctx,
1777 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1778 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1779 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1780 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1781 scan_array_reductions = true;
1782 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1783 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1784 scan_array_reductions = true;
1785 break;
1787 case OMP_CLAUSE_SHARED:
1788 /* Ignore shared directives in teams construct. */
1789 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1790 break;
1791 decl = OMP_CLAUSE_DECL (c);
1792 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1793 fixup_remapped_decl (decl, ctx, false);
1794 break;
1796 case OMP_CLAUSE_MAP:
1797 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1798 break;
1799 decl = OMP_CLAUSE_DECL (c);
1800 if (DECL_P (decl)
1801 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1802 && varpool_node::get_create (decl)->offloadable)
1803 break;
1804 if (DECL_P (decl))
1806 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1807 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1808 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1810 tree new_decl = lookup_decl (decl, ctx);
1811 TREE_TYPE (new_decl)
1812 = remap_type (TREE_TYPE (decl), &ctx->cb);
1814 else if (DECL_SIZE (decl)
1815 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1817 tree decl2 = DECL_VALUE_EXPR (decl);
1818 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1819 decl2 = TREE_OPERAND (decl2, 0);
1820 gcc_assert (DECL_P (decl2));
1821 fixup_remapped_decl (decl2, ctx, false);
1822 fixup_remapped_decl (decl, ctx, true);
1824 else
1825 fixup_remapped_decl (decl, ctx, false);
1827 break;
1829 case OMP_CLAUSE_COPYPRIVATE:
1830 case OMP_CLAUSE_COPYIN:
1831 case OMP_CLAUSE_DEFAULT:
1832 case OMP_CLAUSE_IF:
1833 case OMP_CLAUSE_NUM_THREADS:
1834 case OMP_CLAUSE_NUM_TEAMS:
1835 case OMP_CLAUSE_THREAD_LIMIT:
1836 case OMP_CLAUSE_DEVICE:
1837 case OMP_CLAUSE_SCHEDULE:
1838 case OMP_CLAUSE_DIST_SCHEDULE:
1839 case OMP_CLAUSE_NOWAIT:
1840 case OMP_CLAUSE_ORDERED:
1841 case OMP_CLAUSE_COLLAPSE:
1842 case OMP_CLAUSE_UNTIED:
1843 case OMP_CLAUSE_FINAL:
1844 case OMP_CLAUSE_MERGEABLE:
1845 case OMP_CLAUSE_PROC_BIND:
1846 case OMP_CLAUSE_SAFELEN:
1847 case OMP_CLAUSE_ALIGNED:
1848 case OMP_CLAUSE_DEPEND:
1849 case OMP_CLAUSE__LOOPTEMP_:
1850 case OMP_CLAUSE_TO:
1851 case OMP_CLAUSE_FROM:
1852 case OMP_CLAUSE__CILK_FOR_COUNT_:
1853 break;
1855 default:
1856 gcc_unreachable ();
1860 if (scan_array_reductions)
1861 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1862 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1863 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1865 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1866 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1868 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1869 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1870 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1871 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1872 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1873 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1876 /* Create a new name for omp child function. Returns an identifier. If
1877 IS_CILK_FOR is true then the suffix for the child function is
1878 "_cilk_for_fn." */
1880 static tree
1881 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1883 if (is_cilk_for)
1884 return clone_function_name (current_function_decl, "_cilk_for_fn");
1885 return clone_function_name (current_function_decl,
1886 task_copy ? "_omp_cpyfn" : "_omp_fn");
1889 /* Returns the type of the induction variable for the child function for
1890 _Cilk_for and the types for _high and _low variables based on TYPE. */
1892 static tree
1893 cilk_for_check_loop_diff_type (tree type)
1895 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
1897 if (TYPE_UNSIGNED (type))
1898 return uint32_type_node;
1899 else
1900 return integer_type_node;
1902 else
1904 if (TYPE_UNSIGNED (type))
1905 return uint64_type_node;
1906 else
1907 return long_long_integer_type_node;
1911 /* Build a decl for the omp child function. It'll not contain a body
1912 yet, just the bare decl. */
1914 static void
1915 create_omp_child_function (omp_context *ctx, bool task_copy)
1917 tree decl, type, name, t;
1919 tree cilk_for_count
1920 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
1921 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1922 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
1923 tree cilk_var_type = NULL_TREE;
1925 name = create_omp_child_function_name (task_copy,
1926 cilk_for_count != NULL_TREE);
1927 if (task_copy)
1928 type = build_function_type_list (void_type_node, ptr_type_node,
1929 ptr_type_node, NULL_TREE);
1930 else if (cilk_for_count)
1932 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
1933 cilk_var_type = cilk_for_check_loop_diff_type (type);
1934 type = build_function_type_list (void_type_node, ptr_type_node,
1935 cilk_var_type, cilk_var_type, NULL_TREE);
1937 else
1938 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1940 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1942 if (!task_copy)
1943 ctx->cb.dst_fn = decl;
1944 else
1945 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1947 TREE_STATIC (decl) = 1;
1948 TREE_USED (decl) = 1;
1949 DECL_ARTIFICIAL (decl) = 1;
1950 DECL_IGNORED_P (decl) = 0;
1951 TREE_PUBLIC (decl) = 0;
1952 DECL_UNINLINABLE (decl) = 1;
1953 DECL_EXTERNAL (decl) = 0;
1954 DECL_CONTEXT (decl) = NULL_TREE;
1955 DECL_INITIAL (decl) = make_node (BLOCK);
1956 if (cgraph_node::get (current_function_decl)->offloadable)
1957 cgraph_node::get_create (decl)->offloadable = 1;
1958 else
1960 omp_context *octx;
1961 for (octx = ctx; octx; octx = octx->outer)
1962 if (is_targetreg_ctx (octx))
1964 cgraph_node::get_create (decl)->offloadable = 1;
1965 #ifdef ENABLE_OFFLOADING
1966 g->have_offload = true;
1967 #endif
1968 break;
1972 t = build_decl (DECL_SOURCE_LOCATION (decl),
1973 RESULT_DECL, NULL_TREE, void_type_node);
1974 DECL_ARTIFICIAL (t) = 1;
1975 DECL_IGNORED_P (t) = 1;
1976 DECL_CONTEXT (t) = decl;
1977 DECL_RESULT (decl) = t;
1979 /* _Cilk_for's child function requires two extra parameters called
1980 __low and __high that are set the by Cilk runtime when it calls this
1981 function. */
1982 if (cilk_for_count)
1984 t = build_decl (DECL_SOURCE_LOCATION (decl),
1985 PARM_DECL, get_identifier ("__high"), cilk_var_type);
1986 DECL_ARTIFICIAL (t) = 1;
1987 DECL_NAMELESS (t) = 1;
1988 DECL_ARG_TYPE (t) = ptr_type_node;
1989 DECL_CONTEXT (t) = current_function_decl;
1990 TREE_USED (t) = 1;
1991 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1992 DECL_ARGUMENTS (decl) = t;
1994 t = build_decl (DECL_SOURCE_LOCATION (decl),
1995 PARM_DECL, get_identifier ("__low"), cilk_var_type);
1996 DECL_ARTIFICIAL (t) = 1;
1997 DECL_NAMELESS (t) = 1;
1998 DECL_ARG_TYPE (t) = ptr_type_node;
1999 DECL_CONTEXT (t) = current_function_decl;
2000 TREE_USED (t) = 1;
2001 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2002 DECL_ARGUMENTS (decl) = t;
2005 tree data_name = get_identifier (".omp_data_i");
2006 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2007 ptr_type_node);
2008 DECL_ARTIFICIAL (t) = 1;
2009 DECL_NAMELESS (t) = 1;
2010 DECL_ARG_TYPE (t) = ptr_type_node;
2011 DECL_CONTEXT (t) = current_function_decl;
2012 TREE_USED (t) = 1;
2013 if (cilk_for_count)
2014 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2015 DECL_ARGUMENTS (decl) = t;
2016 if (!task_copy)
2017 ctx->receiver_decl = t;
2018 else
2020 t = build_decl (DECL_SOURCE_LOCATION (decl),
2021 PARM_DECL, get_identifier (".omp_data_o"),
2022 ptr_type_node);
2023 DECL_ARTIFICIAL (t) = 1;
2024 DECL_NAMELESS (t) = 1;
2025 DECL_ARG_TYPE (t) = ptr_type_node;
2026 DECL_CONTEXT (t) = current_function_decl;
2027 TREE_USED (t) = 1;
2028 TREE_ADDRESSABLE (t) = 1;
2029 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2030 DECL_ARGUMENTS (decl) = t;
2033 /* Allocate memory for the function structure. The call to
2034 allocate_struct_function clobbers CFUN, so we need to restore
2035 it afterward. */
2036 push_struct_function (decl);
2037 cfun->function_end_locus = gimple_location (ctx->stmt);
2038 pop_cfun ();
2041 /* Callback for walk_gimple_seq. Check if combined parallel
2042 contains gimple_omp_for_combined_into_p OMP_FOR. */
2044 static tree
2045 find_combined_for (gimple_stmt_iterator *gsi_p,
2046 bool *handled_ops_p,
2047 struct walk_stmt_info *wi)
2049 gimple stmt = gsi_stmt (*gsi_p);
2051 *handled_ops_p = true;
2052 switch (gimple_code (stmt))
2054 WALK_SUBSTMTS;
2056 case GIMPLE_OMP_FOR:
2057 if (gimple_omp_for_combined_into_p (stmt)
2058 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2060 wi->info = stmt;
2061 return integer_zero_node;
2063 break;
2064 default:
2065 break;
2067 return NULL;
2070 /* Scan an OpenMP parallel directive. */
2072 static void
2073 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2075 omp_context *ctx;
2076 tree name;
2077 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2079 /* Ignore parallel directives with empty bodies, unless there
2080 are copyin clauses. */
2081 if (optimize > 0
2082 && empty_body_p (gimple_omp_body (stmt))
2083 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2084 OMP_CLAUSE_COPYIN) == NULL)
2086 gsi_replace (gsi, gimple_build_nop (), false);
2087 return;
2090 if (gimple_omp_parallel_combined_p (stmt))
2092 struct walk_stmt_info wi;
2094 memset (&wi, 0, sizeof (wi));
2095 wi.val_only = true;
2096 walk_gimple_seq (gimple_omp_body (stmt),
2097 find_combined_for, NULL, &wi);
2098 if (wi.info)
2100 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2101 struct omp_for_data fd;
2102 extract_omp_for_data (for_stmt, &fd, NULL);
2103 /* We need two temporaries with fd.loop.v type (istart/iend)
2104 and then (fd.collapse - 1) temporaries with the same
2105 type for count2 ... countN-1 vars if not constant. */
2106 size_t count = 2, i;
2107 tree type = fd.iter_type;
2108 if (fd.collapse > 1
2109 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2110 count += fd.collapse - 1;
2111 for (i = 0; i < count; i++)
2113 tree temp = create_tmp_var (type, NULL);
2114 tree c = build_omp_clause (UNKNOWN_LOCATION,
2115 OMP_CLAUSE__LOOPTEMP_);
2116 insert_decl_map (&outer_ctx->cb, temp, temp);
2117 OMP_CLAUSE_DECL (c) = temp;
2118 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2119 gimple_omp_parallel_set_clauses (stmt, c);
2124 ctx = new_omp_context (stmt, outer_ctx);
2125 taskreg_contexts.safe_push (ctx);
2126 if (taskreg_nesting_level > 1)
2127 ctx->is_nested = true;
2128 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2129 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2130 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2131 name = create_tmp_var_name (".omp_data_s");
2132 name = build_decl (gimple_location (stmt),
2133 TYPE_DECL, name, ctx->record_type);
2134 DECL_ARTIFICIAL (name) = 1;
2135 DECL_NAMELESS (name) = 1;
2136 TYPE_NAME (ctx->record_type) = name;
2137 create_omp_child_function (ctx, false);
2138 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2140 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2141 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2143 if (TYPE_FIELDS (ctx->record_type) == NULL)
2144 ctx->record_type = ctx->receiver_decl = NULL;
2147 /* Scan an OpenMP task directive. */
2149 static void
2150 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2152 omp_context *ctx;
2153 tree name, t;
2154 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2156 /* Ignore task directives with empty bodies. */
2157 if (optimize > 0
2158 && empty_body_p (gimple_omp_body (stmt)))
2160 gsi_replace (gsi, gimple_build_nop (), false);
2161 return;
2164 ctx = new_omp_context (stmt, outer_ctx);
2165 taskreg_contexts.safe_push (ctx);
2166 if (taskreg_nesting_level > 1)
2167 ctx->is_nested = true;
2168 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2169 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2170 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2171 name = create_tmp_var_name (".omp_data_s");
2172 name = build_decl (gimple_location (stmt),
2173 TYPE_DECL, name, ctx->record_type);
2174 DECL_ARTIFICIAL (name) = 1;
2175 DECL_NAMELESS (name) = 1;
2176 TYPE_NAME (ctx->record_type) = name;
2177 create_omp_child_function (ctx, false);
2178 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2180 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2182 if (ctx->srecord_type)
2184 name = create_tmp_var_name (".omp_data_a");
2185 name = build_decl (gimple_location (stmt),
2186 TYPE_DECL, name, ctx->srecord_type);
2187 DECL_ARTIFICIAL (name) = 1;
2188 DECL_NAMELESS (name) = 1;
2189 TYPE_NAME (ctx->srecord_type) = name;
2190 create_omp_child_function (ctx, true);
2193 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2195 if (TYPE_FIELDS (ctx->record_type) == NULL)
2197 ctx->record_type = ctx->receiver_decl = NULL;
2198 t = build_int_cst (long_integer_type_node, 0);
2199 gimple_omp_task_set_arg_size (stmt, t);
2200 t = build_int_cst (long_integer_type_node, 1);
2201 gimple_omp_task_set_arg_align (stmt, t);
2206 /* If any decls have been made addressable during scan_omp,
2207 adjust their fields if needed, and layout record types
2208 of parallel/task constructs. */
2210 static void
2211 finish_taskreg_scan (omp_context *ctx)
2213 if (ctx->record_type == NULL_TREE)
2214 return;
2216 /* If any task_shared_vars were needed, verify all
2217 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2218 statements if use_pointer_for_field hasn't changed
2219 because of that. If it did, update field types now. */
2220 if (task_shared_vars)
2222 tree c;
2224 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2225 c; c = OMP_CLAUSE_CHAIN (c))
2226 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2228 tree decl = OMP_CLAUSE_DECL (c);
2230 /* Global variables don't need to be copied,
2231 the receiver side will use them directly. */
2232 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2233 continue;
2234 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2235 || !use_pointer_for_field (decl, ctx))
2236 continue;
2237 tree field = lookup_field (decl, ctx);
2238 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2239 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2240 continue;
2241 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2242 TREE_THIS_VOLATILE (field) = 0;
2243 DECL_USER_ALIGN (field) = 0;
2244 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2245 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2246 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2247 if (ctx->srecord_type)
2249 tree sfield = lookup_sfield (decl, ctx);
2250 TREE_TYPE (sfield) = TREE_TYPE (field);
2251 TREE_THIS_VOLATILE (sfield) = 0;
2252 DECL_USER_ALIGN (sfield) = 0;
2253 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2254 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2255 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2260 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2262 layout_type (ctx->record_type);
2263 fixup_child_record_type (ctx);
2265 else
2267 location_t loc = gimple_location (ctx->stmt);
2268 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2269 /* Move VLA fields to the end. */
2270 p = &TYPE_FIELDS (ctx->record_type);
2271 while (*p)
2272 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2273 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2275 *q = *p;
2276 *p = TREE_CHAIN (*p);
2277 TREE_CHAIN (*q) = NULL_TREE;
2278 q = &TREE_CHAIN (*q);
2280 else
2281 p = &DECL_CHAIN (*p);
2282 *p = vla_fields;
2283 layout_type (ctx->record_type);
2284 fixup_child_record_type (ctx);
2285 if (ctx->srecord_type)
2286 layout_type (ctx->srecord_type);
2287 tree t = fold_convert_loc (loc, long_integer_type_node,
2288 TYPE_SIZE_UNIT (ctx->record_type));
2289 gimple_omp_task_set_arg_size (ctx->stmt, t);
2290 t = build_int_cst (long_integer_type_node,
2291 TYPE_ALIGN_UNIT (ctx->record_type));
2292 gimple_omp_task_set_arg_align (ctx->stmt, t);
2297 /* Scan an OpenMP loop directive. */
2299 static void
2300 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2302 omp_context *ctx;
2303 size_t i;
2305 ctx = new_omp_context (stmt, outer_ctx);
2307 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2309 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2310 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2312 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2313 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2314 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2315 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2317 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2320 /* Scan an OpenMP sections directive. */
2322 static void
2323 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2325 omp_context *ctx;
2327 ctx = new_omp_context (stmt, outer_ctx);
2328 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2329 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2332 /* Scan an OpenMP single directive. */
2334 static void
2335 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2337 omp_context *ctx;
2338 tree name;
2340 ctx = new_omp_context (stmt, outer_ctx);
2341 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2342 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2343 name = create_tmp_var_name (".omp_copy_s");
2344 name = build_decl (gimple_location (stmt),
2345 TYPE_DECL, name, ctx->record_type);
2346 TYPE_NAME (ctx->record_type) = name;
2348 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2349 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2351 if (TYPE_FIELDS (ctx->record_type) == NULL)
2352 ctx->record_type = NULL;
2353 else
2354 layout_type (ctx->record_type);
2357 /* Scan an OpenMP target{, data, update} directive. */
2359 static void
2360 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2362 omp_context *ctx;
2363 tree name;
2364 int kind = gimple_omp_target_kind (stmt);
2366 ctx = new_omp_context (stmt, outer_ctx);
2367 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2368 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2369 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2370 name = create_tmp_var_name (".omp_data_t");
2371 name = build_decl (gimple_location (stmt),
2372 TYPE_DECL, name, ctx->record_type);
2373 DECL_ARTIFICIAL (name) = 1;
2374 DECL_NAMELESS (name) = 1;
2375 TYPE_NAME (ctx->record_type) = name;
2376 if (kind == GF_OMP_TARGET_KIND_REGION)
2378 create_omp_child_function (ctx, false);
2379 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2382 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2383 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2385 if (TYPE_FIELDS (ctx->record_type) == NULL)
2386 ctx->record_type = ctx->receiver_decl = NULL;
2387 else
2389 TYPE_FIELDS (ctx->record_type)
2390 = nreverse (TYPE_FIELDS (ctx->record_type));
2391 #ifdef ENABLE_CHECKING
2392 tree field;
2393 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2394 for (field = TYPE_FIELDS (ctx->record_type);
2395 field;
2396 field = DECL_CHAIN (field))
2397 gcc_assert (DECL_ALIGN (field) == align);
2398 #endif
2399 layout_type (ctx->record_type);
2400 if (kind == GF_OMP_TARGET_KIND_REGION)
2401 fixup_child_record_type (ctx);
2405 /* Scan an OpenMP teams directive. */
2407 static void
2408 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2410 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2411 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2412 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2415 /* Check OpenMP nesting restrictions. */
2416 static bool
2417 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2419 if (ctx != NULL)
2421 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2422 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2424 error_at (gimple_location (stmt),
2425 "OpenMP constructs may not be nested inside simd region");
2426 return false;
2428 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2430 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2431 || (gimple_omp_for_kind (stmt)
2432 != GF_OMP_FOR_KIND_DISTRIBUTE))
2433 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2435 error_at (gimple_location (stmt),
2436 "only distribute or parallel constructs are allowed to "
2437 "be closely nested inside teams construct");
2438 return false;
2442 switch (gimple_code (stmt))
2444 case GIMPLE_OMP_FOR:
2445 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2446 return true;
2447 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2449 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2451 error_at (gimple_location (stmt),
2452 "distribute construct must be closely nested inside "
2453 "teams construct");
2454 return false;
2456 return true;
2458 /* FALLTHRU */
2459 case GIMPLE_CALL:
2460 if (is_gimple_call (stmt)
2461 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2462 == BUILT_IN_GOMP_CANCEL
2463 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2464 == BUILT_IN_GOMP_CANCELLATION_POINT))
2466 const char *bad = NULL;
2467 const char *kind = NULL;
2468 if (ctx == NULL)
2470 error_at (gimple_location (stmt), "orphaned %qs construct",
2471 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2472 == BUILT_IN_GOMP_CANCEL
2473 ? "#pragma omp cancel"
2474 : "#pragma omp cancellation point");
2475 return false;
2477 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2478 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2479 : 0)
2481 case 1:
2482 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2483 bad = "#pragma omp parallel";
2484 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2485 == BUILT_IN_GOMP_CANCEL
2486 && !integer_zerop (gimple_call_arg (stmt, 1)))
2487 ctx->cancellable = true;
2488 kind = "parallel";
2489 break;
2490 case 2:
2491 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2492 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2493 bad = "#pragma omp for";
2494 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2495 == BUILT_IN_GOMP_CANCEL
2496 && !integer_zerop (gimple_call_arg (stmt, 1)))
2498 ctx->cancellable = true;
2499 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2500 OMP_CLAUSE_NOWAIT))
2501 warning_at (gimple_location (stmt), 0,
2502 "%<#pragma omp cancel for%> inside "
2503 "%<nowait%> for construct");
2504 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2505 OMP_CLAUSE_ORDERED))
2506 warning_at (gimple_location (stmt), 0,
2507 "%<#pragma omp cancel for%> inside "
2508 "%<ordered%> for construct");
2510 kind = "for";
2511 break;
2512 case 4:
2513 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2514 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2515 bad = "#pragma omp sections";
2516 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2517 == BUILT_IN_GOMP_CANCEL
2518 && !integer_zerop (gimple_call_arg (stmt, 1)))
2520 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2522 ctx->cancellable = true;
2523 if (find_omp_clause (gimple_omp_sections_clauses
2524 (ctx->stmt),
2525 OMP_CLAUSE_NOWAIT))
2526 warning_at (gimple_location (stmt), 0,
2527 "%<#pragma omp cancel sections%> inside "
2528 "%<nowait%> sections construct");
2530 else
2532 gcc_assert (ctx->outer
2533 && gimple_code (ctx->outer->stmt)
2534 == GIMPLE_OMP_SECTIONS);
2535 ctx->outer->cancellable = true;
2536 if (find_omp_clause (gimple_omp_sections_clauses
2537 (ctx->outer->stmt),
2538 OMP_CLAUSE_NOWAIT))
2539 warning_at (gimple_location (stmt), 0,
2540 "%<#pragma omp cancel sections%> inside "
2541 "%<nowait%> sections construct");
2544 kind = "sections";
2545 break;
2546 case 8:
2547 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2548 bad = "#pragma omp task";
2549 else
2550 ctx->cancellable = true;
2551 kind = "taskgroup";
2552 break;
2553 default:
2554 error_at (gimple_location (stmt), "invalid arguments");
2555 return false;
2557 if (bad)
2559 error_at (gimple_location (stmt),
2560 "%<%s %s%> construct not closely nested inside of %qs",
2561 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2562 == BUILT_IN_GOMP_CANCEL
2563 ? "#pragma omp cancel"
2564 : "#pragma omp cancellation point", kind, bad);
2565 return false;
2568 /* FALLTHRU */
2569 case GIMPLE_OMP_SECTIONS:
2570 case GIMPLE_OMP_SINGLE:
2571 for (; ctx != NULL; ctx = ctx->outer)
2572 switch (gimple_code (ctx->stmt))
2574 case GIMPLE_OMP_FOR:
2575 case GIMPLE_OMP_SECTIONS:
2576 case GIMPLE_OMP_SINGLE:
2577 case GIMPLE_OMP_ORDERED:
2578 case GIMPLE_OMP_MASTER:
2579 case GIMPLE_OMP_TASK:
2580 case GIMPLE_OMP_CRITICAL:
2581 if (is_gimple_call (stmt))
2583 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2584 != BUILT_IN_GOMP_BARRIER)
2585 return true;
2586 error_at (gimple_location (stmt),
2587 "barrier region may not be closely nested inside "
2588 "of work-sharing, critical, ordered, master or "
2589 "explicit task region");
2590 return false;
2592 error_at (gimple_location (stmt),
2593 "work-sharing region may not be closely nested inside "
2594 "of work-sharing, critical, ordered, master or explicit "
2595 "task region");
2596 return false;
2597 case GIMPLE_OMP_PARALLEL:
2598 return true;
2599 default:
2600 break;
2602 break;
2603 case GIMPLE_OMP_MASTER:
2604 for (; ctx != NULL; ctx = ctx->outer)
2605 switch (gimple_code (ctx->stmt))
2607 case GIMPLE_OMP_FOR:
2608 case GIMPLE_OMP_SECTIONS:
2609 case GIMPLE_OMP_SINGLE:
2610 case GIMPLE_OMP_TASK:
2611 error_at (gimple_location (stmt),
2612 "master region may not be closely nested inside "
2613 "of work-sharing or explicit task region");
2614 return false;
2615 case GIMPLE_OMP_PARALLEL:
2616 return true;
2617 default:
2618 break;
2620 break;
2621 case GIMPLE_OMP_ORDERED:
2622 for (; ctx != NULL; ctx = ctx->outer)
2623 switch (gimple_code (ctx->stmt))
2625 case GIMPLE_OMP_CRITICAL:
2626 case GIMPLE_OMP_TASK:
2627 error_at (gimple_location (stmt),
2628 "ordered region may not be closely nested inside "
2629 "of critical or explicit task region");
2630 return false;
2631 case GIMPLE_OMP_FOR:
2632 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2633 OMP_CLAUSE_ORDERED) == NULL)
2635 error_at (gimple_location (stmt),
2636 "ordered region must be closely nested inside "
2637 "a loop region with an ordered clause");
2638 return false;
2640 return true;
2641 case GIMPLE_OMP_PARALLEL:
2642 error_at (gimple_location (stmt),
2643 "ordered region must be closely nested inside "
2644 "a loop region with an ordered clause");
2645 return false;
2646 default:
2647 break;
2649 break;
2650 case GIMPLE_OMP_CRITICAL:
2652 tree this_stmt_name
2653 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2654 for (; ctx != NULL; ctx = ctx->outer)
2655 if (gomp_critical *other_crit
2656 = dyn_cast <gomp_critical *> (ctx->stmt))
2657 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2659 error_at (gimple_location (stmt),
2660 "critical region may not be nested inside a critical "
2661 "region with the same name");
2662 return false;
2665 break;
2666 case GIMPLE_OMP_TEAMS:
2667 if (ctx == NULL
2668 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2669 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2671 error_at (gimple_location (stmt),
2672 "teams construct not closely nested inside of target "
2673 "region");
2674 return false;
2676 break;
2677 case GIMPLE_OMP_TARGET:
2678 for (; ctx != NULL; ctx = ctx->outer)
2679 if (is_targetreg_ctx (ctx))
2681 const char *name;
2682 switch (gimple_omp_target_kind (stmt))
2684 case GF_OMP_TARGET_KIND_REGION: name = "target"; break;
2685 case GF_OMP_TARGET_KIND_DATA: name = "target data"; break;
2686 case GF_OMP_TARGET_KIND_UPDATE: name = "target update"; break;
2687 default: gcc_unreachable ();
2689 warning_at (gimple_location (stmt), 0,
2690 "%s construct inside of target region", name);
2692 break;
2693 default:
2694 break;
2696 return true;
2700 /* Helper function scan_omp.
2702 Callback for walk_tree or operators in walk_gimple_stmt used to
2703 scan for OpenMP directives in TP. */
2705 static tree
2706 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2708 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2709 omp_context *ctx = (omp_context *) wi->info;
2710 tree t = *tp;
2712 switch (TREE_CODE (t))
2714 case VAR_DECL:
2715 case PARM_DECL:
2716 case LABEL_DECL:
2717 case RESULT_DECL:
2718 if (ctx)
2719 *tp = remap_decl (t, &ctx->cb);
2720 break;
2722 default:
2723 if (ctx && TYPE_P (t))
2724 *tp = remap_type (t, &ctx->cb);
2725 else if (!DECL_P (t))
2727 *walk_subtrees = 1;
2728 if (ctx)
2730 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2731 if (tem != TREE_TYPE (t))
2733 if (TREE_CODE (t) == INTEGER_CST)
2734 *tp = wide_int_to_tree (tem, t);
2735 else
2736 TREE_TYPE (t) = tem;
2740 break;
2743 return NULL_TREE;
2746 /* Return true if FNDECL is a setjmp or a longjmp. */
2748 static bool
2749 setjmp_or_longjmp_p (const_tree fndecl)
2751 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2752 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2753 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2754 return true;
2756 tree declname = DECL_NAME (fndecl);
2757 if (!declname)
2758 return false;
2759 const char *name = IDENTIFIER_POINTER (declname);
2760 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2764 /* Helper function for scan_omp.
2766 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2767 the current statement in GSI. */
2769 static tree
2770 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2771 struct walk_stmt_info *wi)
2773 gimple stmt = gsi_stmt (*gsi);
2774 omp_context *ctx = (omp_context *) wi->info;
2776 if (gimple_has_location (stmt))
2777 input_location = gimple_location (stmt);
2779 /* Check the OpenMP nesting restrictions. */
2780 bool remove = false;
2781 if (is_gimple_omp (stmt))
2782 remove = !check_omp_nesting_restrictions (stmt, ctx);
2783 else if (is_gimple_call (stmt))
2785 tree fndecl = gimple_call_fndecl (stmt);
2786 if (fndecl)
2788 if (setjmp_or_longjmp_p (fndecl)
2789 && ctx
2790 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2791 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2793 remove = true;
2794 error_at (gimple_location (stmt),
2795 "setjmp/longjmp inside simd construct");
2797 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2798 switch (DECL_FUNCTION_CODE (fndecl))
2800 case BUILT_IN_GOMP_BARRIER:
2801 case BUILT_IN_GOMP_CANCEL:
2802 case BUILT_IN_GOMP_CANCELLATION_POINT:
2803 case BUILT_IN_GOMP_TASKYIELD:
2804 case BUILT_IN_GOMP_TASKWAIT:
2805 case BUILT_IN_GOMP_TASKGROUP_START:
2806 case BUILT_IN_GOMP_TASKGROUP_END:
2807 remove = !check_omp_nesting_restrictions (stmt, ctx);
2808 break;
2809 default:
2810 break;
2814 if (remove)
2816 stmt = gimple_build_nop ();
2817 gsi_replace (gsi, stmt, false);
2820 *handled_ops_p = true;
2822 switch (gimple_code (stmt))
2824 case GIMPLE_OMP_PARALLEL:
2825 taskreg_nesting_level++;
2826 scan_omp_parallel (gsi, ctx);
2827 taskreg_nesting_level--;
2828 break;
2830 case GIMPLE_OMP_TASK:
2831 taskreg_nesting_level++;
2832 scan_omp_task (gsi, ctx);
2833 taskreg_nesting_level--;
2834 break;
2836 case GIMPLE_OMP_FOR:
2837 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
2838 break;
2840 case GIMPLE_OMP_SECTIONS:
2841 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
2842 break;
2844 case GIMPLE_OMP_SINGLE:
2845 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
2846 break;
2848 case GIMPLE_OMP_SECTION:
2849 case GIMPLE_OMP_MASTER:
2850 case GIMPLE_OMP_TASKGROUP:
2851 case GIMPLE_OMP_ORDERED:
2852 case GIMPLE_OMP_CRITICAL:
2853 ctx = new_omp_context (stmt, ctx);
2854 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2855 break;
2857 case GIMPLE_OMP_TARGET:
2858 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
2859 break;
2861 case GIMPLE_OMP_TEAMS:
2862 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
2863 break;
2865 case GIMPLE_BIND:
2867 tree var;
2869 *handled_ops_p = false;
2870 if (ctx)
2871 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
2872 var ;
2873 var = DECL_CHAIN (var))
2874 insert_decl_map (&ctx->cb, var, var);
2876 break;
2877 default:
2878 *handled_ops_p = false;
2879 break;
2882 return NULL_TREE;
2886 /* Scan all the statements starting at the current statement. CTX
2887 contains context information about the OpenMP directives and
2888 clauses found during the scan. */
2890 static void
2891 scan_omp (gimple_seq *body_p, omp_context *ctx)
2893 location_t saved_location;
2894 struct walk_stmt_info wi;
2896 memset (&wi, 0, sizeof (wi));
2897 wi.info = ctx;
2898 wi.want_locations = true;
2900 saved_location = input_location;
2901 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2902 input_location = saved_location;
2905 /* Re-gimplification and code generation routines. */
2907 /* Build a call to GOMP_barrier. */
2909 static gimple
2910 build_omp_barrier (tree lhs)
2912 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2913 : BUILT_IN_GOMP_BARRIER);
2914 gcall *g = gimple_build_call (fndecl, 0);
2915 if (lhs)
2916 gimple_call_set_lhs (g, lhs);
2917 return g;
2920 /* If a context was created for STMT when it was scanned, return it. */
2922 static omp_context *
2923 maybe_lookup_ctx (gimple stmt)
2925 splay_tree_node n;
2926 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2927 return n ? (omp_context *) n->value : NULL;
2931 /* Find the mapping for DECL in CTX or the immediately enclosing
2932 context that has a mapping for DECL.
2934 If CTX is a nested parallel directive, we may have to use the decl
2935 mappings created in CTX's parent context. Suppose that we have the
2936 following parallel nesting (variable UIDs showed for clarity):
2938 iD.1562 = 0;
2939 #omp parallel shared(iD.1562) -> outer parallel
2940 iD.1562 = iD.1562 + 1;
2942 #omp parallel shared (iD.1562) -> inner parallel
2943 iD.1562 = iD.1562 - 1;
2945 Each parallel structure will create a distinct .omp_data_s structure
2946 for copying iD.1562 in/out of the directive:
2948 outer parallel .omp_data_s.1.i -> iD.1562
2949 inner parallel .omp_data_s.2.i -> iD.1562
2951 A shared variable mapping will produce a copy-out operation before
2952 the parallel directive and a copy-in operation after it. So, in
2953 this case we would have:
2955 iD.1562 = 0;
2956 .omp_data_o.1.i = iD.1562;
2957 #omp parallel shared(iD.1562) -> outer parallel
2958 .omp_data_i.1 = &.omp_data_o.1
2959 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2961 .omp_data_o.2.i = iD.1562; -> **
2962 #omp parallel shared(iD.1562) -> inner parallel
2963 .omp_data_i.2 = &.omp_data_o.2
2964 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2967 ** This is a problem. The symbol iD.1562 cannot be referenced
2968 inside the body of the outer parallel region. But since we are
2969 emitting this copy operation while expanding the inner parallel
2970 directive, we need to access the CTX structure of the outer
2971 parallel directive to get the correct mapping:
2973 .omp_data_o.2.i = .omp_data_i.1->i
2975 Since there may be other workshare or parallel directives enclosing
2976 the parallel directive, it may be necessary to walk up the context
2977 parent chain. This is not a problem in general because nested
2978 parallelism happens only rarely. */
2980 static tree
2981 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2983 tree t;
2984 omp_context *up;
2986 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2987 t = maybe_lookup_decl (decl, up);
2989 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2991 return t ? t : decl;
2995 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2996 in outer contexts. */
2998 static tree
2999 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3001 tree t = NULL;
3002 omp_context *up;
3004 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3005 t = maybe_lookup_decl (decl, up);
3007 return t ? t : decl;
3011 /* Construct the initialization value for reduction CLAUSE. */
3013 tree
3014 omp_reduction_init (tree clause, tree type)
3016 location_t loc = OMP_CLAUSE_LOCATION (clause);
3017 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3019 case PLUS_EXPR:
3020 case MINUS_EXPR:
3021 case BIT_IOR_EXPR:
3022 case BIT_XOR_EXPR:
3023 case TRUTH_OR_EXPR:
3024 case TRUTH_ORIF_EXPR:
3025 case TRUTH_XOR_EXPR:
3026 case NE_EXPR:
3027 return build_zero_cst (type);
3029 case MULT_EXPR:
3030 case TRUTH_AND_EXPR:
3031 case TRUTH_ANDIF_EXPR:
3032 case EQ_EXPR:
3033 return fold_convert_loc (loc, type, integer_one_node);
3035 case BIT_AND_EXPR:
3036 return fold_convert_loc (loc, type, integer_minus_one_node);
3038 case MAX_EXPR:
3039 if (SCALAR_FLOAT_TYPE_P (type))
3041 REAL_VALUE_TYPE max, min;
3042 if (HONOR_INFINITIES (TYPE_MODE (type)))
3044 real_inf (&max);
3045 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3047 else
3048 real_maxval (&min, 1, TYPE_MODE (type));
3049 return build_real (type, min);
3051 else
3053 gcc_assert (INTEGRAL_TYPE_P (type));
3054 return TYPE_MIN_VALUE (type);
3057 case MIN_EXPR:
3058 if (SCALAR_FLOAT_TYPE_P (type))
3060 REAL_VALUE_TYPE max;
3061 if (HONOR_INFINITIES (TYPE_MODE (type)))
3062 real_inf (&max);
3063 else
3064 real_maxval (&max, 0, TYPE_MODE (type));
3065 return build_real (type, max);
3067 else
3069 gcc_assert (INTEGRAL_TYPE_P (type));
3070 return TYPE_MAX_VALUE (type);
3073 default:
3074 gcc_unreachable ();
3078 /* Return alignment to be assumed for var in CLAUSE, which should be
3079 OMP_CLAUSE_ALIGNED. */
3081 static tree
3082 omp_clause_aligned_alignment (tree clause)
3084 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3085 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3087 /* Otherwise return implementation defined alignment. */
3088 unsigned int al = 1;
3089 machine_mode mode, vmode;
3090 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3091 if (vs)
3092 vs = 1 << floor_log2 (vs);
3093 static enum mode_class classes[]
3094 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3095 for (int i = 0; i < 4; i += 2)
3096 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3097 mode != VOIDmode;
3098 mode = GET_MODE_WIDER_MODE (mode))
3100 vmode = targetm.vectorize.preferred_simd_mode (mode);
3101 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3102 continue;
3103 while (vs
3104 && GET_MODE_SIZE (vmode) < vs
3105 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3106 vmode = GET_MODE_2XWIDER_MODE (vmode);
3108 tree type = lang_hooks.types.type_for_mode (mode, 1);
3109 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3110 continue;
3111 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3112 / GET_MODE_SIZE (mode));
3113 if (TYPE_MODE (type) != vmode)
3114 continue;
3115 if (TYPE_ALIGN_UNIT (type) > al)
3116 al = TYPE_ALIGN_UNIT (type);
3118 return build_int_cst (integer_type_node, al);
3121 /* Return maximum possible vectorization factor for the target. */
3123 static int
3124 omp_max_vf (void)
3126 if (!optimize
3127 || optimize_debug
3128 || !flag_tree_loop_optimize
3129 || (!flag_tree_loop_vectorize
3130 && (global_options_set.x_flag_tree_loop_vectorize
3131 || global_options_set.x_flag_tree_vectorize)))
3132 return 1;
3134 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3135 if (vs)
3137 vs = 1 << floor_log2 (vs);
3138 return vs;
3140 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3141 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3142 return GET_MODE_NUNITS (vqimode);
3143 return 1;
3146 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3147 privatization. */
3149 static bool
3150 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3151 tree &idx, tree &lane, tree &ivar, tree &lvar)
3153 if (max_vf == 0)
3155 max_vf = omp_max_vf ();
3156 if (max_vf > 1)
3158 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3159 OMP_CLAUSE_SAFELEN);
3160 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3161 max_vf = 1;
3162 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3163 max_vf) == -1)
3164 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3166 if (max_vf > 1)
3168 idx = create_tmp_var (unsigned_type_node, NULL);
3169 lane = create_tmp_var (unsigned_type_node, NULL);
3172 if (max_vf == 1)
3173 return false;
3175 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3176 tree avar = create_tmp_var_raw (atype, NULL);
3177 if (TREE_ADDRESSABLE (new_var))
3178 TREE_ADDRESSABLE (avar) = 1;
3179 DECL_ATTRIBUTES (avar)
3180 = tree_cons (get_identifier ("omp simd array"), NULL,
3181 DECL_ATTRIBUTES (avar));
3182 gimple_add_tmp_var (avar);
3183 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3184 NULL_TREE, NULL_TREE);
3185 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3186 NULL_TREE, NULL_TREE);
3187 if (DECL_P (new_var))
3189 SET_DECL_VALUE_EXPR (new_var, lvar);
3190 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3192 return true;
3195 /* Helper function of lower_rec_input_clauses. For a reference
3196 in simd reduction, add an underlying variable it will reference. */
3198 static void
3199 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3201 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3202 if (TREE_CONSTANT (z))
3204 const char *name = NULL;
3205 if (DECL_NAME (new_vard))
3206 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3208 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3209 gimple_add_tmp_var (z);
3210 TREE_ADDRESSABLE (z) = 1;
3211 z = build_fold_addr_expr_loc (loc, z);
3212 gimplify_assign (new_vard, z, ilist);
3216 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3217 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3218 private variables. Initialization statements go in ILIST, while calls
3219 to destructors go in DLIST. */
3221 static void
3222 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3223 omp_context *ctx, struct omp_for_data *fd)
3225 tree c, dtor, copyin_seq, x, ptr;
3226 bool copyin_by_ref = false;
3227 bool lastprivate_firstprivate = false;
3228 bool reduction_omp_orig_ref = false;
3229 int pass;
3230 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3231 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3232 int max_vf = 0;
3233 tree lane = NULL_TREE, idx = NULL_TREE;
3234 tree ivar = NULL_TREE, lvar = NULL_TREE;
3235 gimple_seq llist[2] = { NULL, NULL };
3237 copyin_seq = NULL;
3239 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3240 with data sharing clauses referencing variable sized vars. That
3241 is unnecessarily hard to support and very unlikely to result in
3242 vectorized code anyway. */
3243 if (is_simd)
3244 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3245 switch (OMP_CLAUSE_CODE (c))
3247 case OMP_CLAUSE_LINEAR:
3248 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3249 max_vf = 1;
3250 /* FALLTHRU */
3251 case OMP_CLAUSE_REDUCTION:
3252 case OMP_CLAUSE_PRIVATE:
3253 case OMP_CLAUSE_FIRSTPRIVATE:
3254 case OMP_CLAUSE_LASTPRIVATE:
3255 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3256 max_vf = 1;
3257 break;
3258 default:
3259 continue;
3262 /* Do all the fixed sized types in the first pass, and the variable sized
3263 types in the second pass. This makes sure that the scalar arguments to
3264 the variable sized types are processed before we use them in the
3265 variable sized operations. */
3266 for (pass = 0; pass < 2; ++pass)
3268 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3270 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3271 tree var, new_var;
3272 bool by_ref;
3273 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3275 switch (c_kind)
3277 case OMP_CLAUSE_PRIVATE:
3278 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3279 continue;
3280 break;
3281 case OMP_CLAUSE_SHARED:
3282 /* Ignore shared directives in teams construct. */
3283 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3284 continue;
3285 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3287 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3288 continue;
3290 case OMP_CLAUSE_FIRSTPRIVATE:
3291 case OMP_CLAUSE_COPYIN:
3292 case OMP_CLAUSE_LINEAR:
3293 break;
3294 case OMP_CLAUSE_REDUCTION:
3295 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3296 reduction_omp_orig_ref = true;
3297 break;
3298 case OMP_CLAUSE__LOOPTEMP_:
3299 /* Handle _looptemp_ clauses only on parallel. */
3300 if (fd)
3301 continue;
3302 break;
3303 case OMP_CLAUSE_LASTPRIVATE:
3304 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3306 lastprivate_firstprivate = true;
3307 if (pass != 0)
3308 continue;
3310 /* Even without corresponding firstprivate, if
3311 decl is Fortran allocatable, it needs outer var
3312 reference. */
3313 else if (pass == 0
3314 && lang_hooks.decls.omp_private_outer_ref
3315 (OMP_CLAUSE_DECL (c)))
3316 lastprivate_firstprivate = true;
3317 break;
3318 case OMP_CLAUSE_ALIGNED:
3319 if (pass == 0)
3320 continue;
3321 var = OMP_CLAUSE_DECL (c);
3322 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3323 && !is_global_var (var))
3325 new_var = maybe_lookup_decl (var, ctx);
3326 if (new_var == NULL_TREE)
3327 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3328 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3329 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3330 omp_clause_aligned_alignment (c));
3331 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3332 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3333 gimplify_and_add (x, ilist);
3335 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3336 && is_global_var (var))
3338 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3339 new_var = lookup_decl (var, ctx);
3340 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3341 t = build_fold_addr_expr_loc (clause_loc, t);
3342 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3343 t = build_call_expr_loc (clause_loc, t2, 2, t,
3344 omp_clause_aligned_alignment (c));
3345 t = fold_convert_loc (clause_loc, ptype, t);
3346 x = create_tmp_var (ptype, NULL);
3347 t = build2 (MODIFY_EXPR, ptype, x, t);
3348 gimplify_and_add (t, ilist);
3349 t = build_simple_mem_ref_loc (clause_loc, x);
3350 SET_DECL_VALUE_EXPR (new_var, t);
3351 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3353 continue;
3354 default:
3355 continue;
3358 new_var = var = OMP_CLAUSE_DECL (c);
3359 if (c_kind != OMP_CLAUSE_COPYIN)
3360 new_var = lookup_decl (var, ctx);
3362 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3364 if (pass != 0)
3365 continue;
3367 else if (is_variable_sized (var))
3369 /* For variable sized types, we need to allocate the
3370 actual storage here. Call alloca and store the
3371 result in the pointer decl that we created elsewhere. */
3372 if (pass == 0)
3373 continue;
3375 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3377 gcall *stmt;
3378 tree tmp, atmp;
3380 ptr = DECL_VALUE_EXPR (new_var);
3381 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3382 ptr = TREE_OPERAND (ptr, 0);
3383 gcc_assert (DECL_P (ptr));
3384 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3386 /* void *tmp = __builtin_alloca */
3387 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3388 stmt = gimple_build_call (atmp, 1, x);
3389 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3390 gimple_add_tmp_var (tmp);
3391 gimple_call_set_lhs (stmt, tmp);
3393 gimple_seq_add_stmt (ilist, stmt);
3395 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3396 gimplify_assign (ptr, x, ilist);
3399 else if (is_reference (var))
3401 /* For references that are being privatized for Fortran,
3402 allocate new backing storage for the new pointer
3403 variable. This allows us to avoid changing all the
3404 code that expects a pointer to something that expects
3405 a direct variable. */
3406 if (pass == 0)
3407 continue;
3409 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3410 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3412 x = build_receiver_ref (var, false, ctx);
3413 x = build_fold_addr_expr_loc (clause_loc, x);
3415 else if (TREE_CONSTANT (x))
3417 /* For reduction in SIMD loop, defer adding the
3418 initialization of the reference, because if we decide
3419 to use SIMD array for it, the initilization could cause
3420 expansion ICE. */
3421 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3422 x = NULL_TREE;
3423 else
3425 const char *name = NULL;
3426 if (DECL_NAME (var))
3427 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3429 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3430 name);
3431 gimple_add_tmp_var (x);
3432 TREE_ADDRESSABLE (x) = 1;
3433 x = build_fold_addr_expr_loc (clause_loc, x);
3436 else
3438 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3439 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3442 if (x)
3444 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3445 gimplify_assign (new_var, x, ilist);
3448 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3450 else if (c_kind == OMP_CLAUSE_REDUCTION
3451 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3453 if (pass == 0)
3454 continue;
3456 else if (pass != 0)
3457 continue;
3459 switch (OMP_CLAUSE_CODE (c))
3461 case OMP_CLAUSE_SHARED:
3462 /* Ignore shared directives in teams construct. */
3463 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3464 continue;
3465 /* Shared global vars are just accessed directly. */
3466 if (is_global_var (new_var))
3467 break;
3468 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3469 needs to be delayed until after fixup_child_record_type so
3470 that we get the correct type during the dereference. */
3471 by_ref = use_pointer_for_field (var, ctx);
3472 x = build_receiver_ref (var, by_ref, ctx);
3473 SET_DECL_VALUE_EXPR (new_var, x);
3474 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3476 /* ??? If VAR is not passed by reference, and the variable
3477 hasn't been initialized yet, then we'll get a warning for
3478 the store into the omp_data_s structure. Ideally, we'd be
3479 able to notice this and not store anything at all, but
3480 we're generating code too early. Suppress the warning. */
3481 if (!by_ref)
3482 TREE_NO_WARNING (var) = 1;
3483 break;
3485 case OMP_CLAUSE_LASTPRIVATE:
3486 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3487 break;
3488 /* FALLTHRU */
3490 case OMP_CLAUSE_PRIVATE:
3491 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3492 x = build_outer_var_ref (var, ctx);
3493 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3495 if (is_task_ctx (ctx))
3496 x = build_receiver_ref (var, false, ctx);
3497 else
3498 x = build_outer_var_ref (var, ctx);
3500 else
3501 x = NULL;
3502 do_private:
3503 tree nx;
3504 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3505 if (is_simd)
3507 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3508 if ((TREE_ADDRESSABLE (new_var) || nx || y
3509 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3510 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3511 idx, lane, ivar, lvar))
3513 if (nx)
3514 x = lang_hooks.decls.omp_clause_default_ctor
3515 (c, unshare_expr (ivar), x);
3516 if (nx && x)
3517 gimplify_and_add (x, &llist[0]);
3518 if (y)
3520 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3521 if (y)
3523 gimple_seq tseq = NULL;
3525 dtor = y;
3526 gimplify_stmt (&dtor, &tseq);
3527 gimple_seq_add_seq (&llist[1], tseq);
3530 break;
3533 if (nx)
3534 gimplify_and_add (nx, ilist);
3535 /* FALLTHRU */
3537 do_dtor:
3538 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3539 if (x)
3541 gimple_seq tseq = NULL;
3543 dtor = x;
3544 gimplify_stmt (&dtor, &tseq);
3545 gimple_seq_add_seq (dlist, tseq);
3547 break;
3549 case OMP_CLAUSE_LINEAR:
3550 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3551 goto do_firstprivate;
3552 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3553 x = NULL;
3554 else
3555 x = build_outer_var_ref (var, ctx);
3556 goto do_private;
3558 case OMP_CLAUSE_FIRSTPRIVATE:
3559 if (is_task_ctx (ctx))
3561 if (is_reference (var) || is_variable_sized (var))
3562 goto do_dtor;
3563 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3564 ctx))
3565 || use_pointer_for_field (var, NULL))
3567 x = build_receiver_ref (var, false, ctx);
3568 SET_DECL_VALUE_EXPR (new_var, x);
3569 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3570 goto do_dtor;
3573 do_firstprivate:
3574 x = build_outer_var_ref (var, ctx);
3575 if (is_simd)
3577 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3578 && gimple_omp_for_combined_into_p (ctx->stmt))
3580 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3581 tree stept = TREE_TYPE (t);
3582 tree ct = find_omp_clause (clauses,
3583 OMP_CLAUSE__LOOPTEMP_);
3584 gcc_assert (ct);
3585 tree l = OMP_CLAUSE_DECL (ct);
3586 tree n1 = fd->loop.n1;
3587 tree step = fd->loop.step;
3588 tree itype = TREE_TYPE (l);
3589 if (POINTER_TYPE_P (itype))
3590 itype = signed_type_for (itype);
3591 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3592 if (TYPE_UNSIGNED (itype)
3593 && fd->loop.cond_code == GT_EXPR)
3594 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3595 fold_build1 (NEGATE_EXPR, itype, l),
3596 fold_build1 (NEGATE_EXPR,
3597 itype, step));
3598 else
3599 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3600 t = fold_build2 (MULT_EXPR, stept,
3601 fold_convert (stept, l), t);
3603 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3605 x = lang_hooks.decls.omp_clause_linear_ctor
3606 (c, new_var, x, t);
3607 gimplify_and_add (x, ilist);
3608 goto do_dtor;
3611 if (POINTER_TYPE_P (TREE_TYPE (x)))
3612 x = fold_build2 (POINTER_PLUS_EXPR,
3613 TREE_TYPE (x), x, t);
3614 else
3615 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3618 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3619 || TREE_ADDRESSABLE (new_var))
3620 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3621 idx, lane, ivar, lvar))
3623 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3625 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3626 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3627 gimplify_and_add (x, ilist);
3628 gimple_stmt_iterator gsi
3629 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3630 gassign *g
3631 = gimple_build_assign (unshare_expr (lvar), iv);
3632 gsi_insert_before_without_update (&gsi, g,
3633 GSI_SAME_STMT);
3634 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3635 enum tree_code code = PLUS_EXPR;
3636 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3637 code = POINTER_PLUS_EXPR;
3638 g = gimple_build_assign_with_ops (code, iv, iv, t);
3639 gsi_insert_before_without_update (&gsi, g,
3640 GSI_SAME_STMT);
3641 break;
3643 x = lang_hooks.decls.omp_clause_copy_ctor
3644 (c, unshare_expr (ivar), x);
3645 gimplify_and_add (x, &llist[0]);
3646 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3647 if (x)
3649 gimple_seq tseq = NULL;
3651 dtor = x;
3652 gimplify_stmt (&dtor, &tseq);
3653 gimple_seq_add_seq (&llist[1], tseq);
3655 break;
3658 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3659 gimplify_and_add (x, ilist);
3660 goto do_dtor;
3662 case OMP_CLAUSE__LOOPTEMP_:
3663 gcc_assert (is_parallel_ctx (ctx));
3664 x = build_outer_var_ref (var, ctx);
3665 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3666 gimplify_and_add (x, ilist);
3667 break;
3669 case OMP_CLAUSE_COPYIN:
3670 by_ref = use_pointer_for_field (var, NULL);
3671 x = build_receiver_ref (var, by_ref, ctx);
3672 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3673 append_to_statement_list (x, &copyin_seq);
3674 copyin_by_ref |= by_ref;
3675 break;
3677 case OMP_CLAUSE_REDUCTION:
3678 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3680 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3681 gimple tseq;
3682 x = build_outer_var_ref (var, ctx);
3684 if (is_reference (var)
3685 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3686 TREE_TYPE (x)))
3687 x = build_fold_addr_expr_loc (clause_loc, x);
3688 SET_DECL_VALUE_EXPR (placeholder, x);
3689 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3690 tree new_vard = new_var;
3691 if (is_reference (var))
3693 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3694 new_vard = TREE_OPERAND (new_var, 0);
3695 gcc_assert (DECL_P (new_vard));
3697 if (is_simd
3698 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3699 idx, lane, ivar, lvar))
3701 if (new_vard == new_var)
3703 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3704 SET_DECL_VALUE_EXPR (new_var, ivar);
3706 else
3708 SET_DECL_VALUE_EXPR (new_vard,
3709 build_fold_addr_expr (ivar));
3710 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3712 x = lang_hooks.decls.omp_clause_default_ctor
3713 (c, unshare_expr (ivar),
3714 build_outer_var_ref (var, ctx));
3715 if (x)
3716 gimplify_and_add (x, &llist[0]);
3717 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3719 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3720 lower_omp (&tseq, ctx);
3721 gimple_seq_add_seq (&llist[0], tseq);
3723 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3724 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3725 lower_omp (&tseq, ctx);
3726 gimple_seq_add_seq (&llist[1], tseq);
3727 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3728 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3729 if (new_vard == new_var)
3730 SET_DECL_VALUE_EXPR (new_var, lvar);
3731 else
3732 SET_DECL_VALUE_EXPR (new_vard,
3733 build_fold_addr_expr (lvar));
3734 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3735 if (x)
3737 tseq = NULL;
3738 dtor = x;
3739 gimplify_stmt (&dtor, &tseq);
3740 gimple_seq_add_seq (&llist[1], tseq);
3742 break;
3744 /* If this is a reference to constant size reduction var
3745 with placeholder, we haven't emitted the initializer
3746 for it because it is undesirable if SIMD arrays are used.
3747 But if they aren't used, we need to emit the deferred
3748 initialization now. */
3749 else if (is_reference (var) && is_simd)
3750 handle_simd_reference (clause_loc, new_vard, ilist);
3751 x = lang_hooks.decls.omp_clause_default_ctor
3752 (c, unshare_expr (new_var),
3753 build_outer_var_ref (var, ctx));
3754 if (x)
3755 gimplify_and_add (x, ilist);
3756 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3758 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3759 lower_omp (&tseq, ctx);
3760 gimple_seq_add_seq (ilist, tseq);
3762 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3763 if (is_simd)
3765 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3766 lower_omp (&tseq, ctx);
3767 gimple_seq_add_seq (dlist, tseq);
3768 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3770 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3771 goto do_dtor;
3773 else
3775 x = omp_reduction_init (c, TREE_TYPE (new_var));
3776 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3777 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3779 /* reduction(-:var) sums up the partial results, so it
3780 acts identically to reduction(+:var). */
3781 if (code == MINUS_EXPR)
3782 code = PLUS_EXPR;
3784 tree new_vard = new_var;
3785 if (is_simd && is_reference (var))
3787 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3788 new_vard = TREE_OPERAND (new_var, 0);
3789 gcc_assert (DECL_P (new_vard));
3791 if (is_simd
3792 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3793 idx, lane, ivar, lvar))
3795 tree ref = build_outer_var_ref (var, ctx);
3797 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3799 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3800 ref = build_outer_var_ref (var, ctx);
3801 gimplify_assign (ref, x, &llist[1]);
3803 if (new_vard != new_var)
3805 SET_DECL_VALUE_EXPR (new_vard,
3806 build_fold_addr_expr (lvar));
3807 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3810 else
3812 if (is_reference (var) && is_simd)
3813 handle_simd_reference (clause_loc, new_vard, ilist);
3814 gimplify_assign (new_var, x, ilist);
3815 if (is_simd)
3817 tree ref = build_outer_var_ref (var, ctx);
3819 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3820 ref = build_outer_var_ref (var, ctx);
3821 gimplify_assign (ref, x, dlist);
3825 break;
3827 default:
3828 gcc_unreachable ();
3833 if (lane)
3835 tree uid = create_tmp_var (ptr_type_node, "simduid");
3836 /* Don't want uninit warnings on simduid, it is always uninitialized,
3837 but we use it not for the value, but for the DECL_UID only. */
3838 TREE_NO_WARNING (uid) = 1;
3839 gimple g
3840 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3841 gimple_call_set_lhs (g, lane);
3842 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3843 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3844 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3845 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3846 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3847 gimple_omp_for_set_clauses (ctx->stmt, c);
3848 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3849 build_int_cst (unsigned_type_node, 0));
3850 gimple_seq_add_stmt (ilist, g);
3851 for (int i = 0; i < 2; i++)
3852 if (llist[i])
3854 tree vf = create_tmp_var (unsigned_type_node, NULL);
3855 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3856 gimple_call_set_lhs (g, vf);
3857 gimple_seq *seq = i == 0 ? ilist : dlist;
3858 gimple_seq_add_stmt (seq, g);
3859 tree t = build_int_cst (unsigned_type_node, 0);
3860 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t);
3861 gimple_seq_add_stmt (seq, g);
3862 tree body = create_artificial_label (UNKNOWN_LOCATION);
3863 tree header = create_artificial_label (UNKNOWN_LOCATION);
3864 tree end = create_artificial_label (UNKNOWN_LOCATION);
3865 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3866 gimple_seq_add_stmt (seq, gimple_build_label (body));
3867 gimple_seq_add_seq (seq, llist[i]);
3868 t = build_int_cst (unsigned_type_node, 1);
3869 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3870 gimple_seq_add_stmt (seq, g);
3871 gimple_seq_add_stmt (seq, gimple_build_label (header));
3872 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3873 gimple_seq_add_stmt (seq, g);
3874 gimple_seq_add_stmt (seq, gimple_build_label (end));
3878 /* The copyin sequence is not to be executed by the main thread, since
3879 that would result in self-copies. Perhaps not visible to scalars,
3880 but it certainly is to C++ operator=. */
3881 if (copyin_seq)
3883 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3885 x = build2 (NE_EXPR, boolean_type_node, x,
3886 build_int_cst (TREE_TYPE (x), 0));
3887 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3888 gimplify_and_add (x, ilist);
3891 /* If any copyin variable is passed by reference, we must ensure the
3892 master thread doesn't modify it before it is copied over in all
3893 threads. Similarly for variables in both firstprivate and
3894 lastprivate clauses we need to ensure the lastprivate copying
3895 happens after firstprivate copying in all threads. And similarly
3896 for UDRs if initializer expression refers to omp_orig. */
3897 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3899 /* Don't add any barrier for #pragma omp simd or
3900 #pragma omp distribute. */
3901 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3902 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3903 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3906 /* If max_vf is non-zero, then we can use only a vectorization factor
3907 up to the max_vf we chose. So stick it into the safelen clause. */
3908 if (max_vf)
3910 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3911 OMP_CLAUSE_SAFELEN);
3912 if (c == NULL_TREE
3913 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
3914 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3915 max_vf) == 1))
3917 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3918 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3919 max_vf);
3920 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3921 gimple_omp_for_set_clauses (ctx->stmt, c);
3927 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3928 both parallel and workshare constructs. PREDICATE may be NULL if it's
3929 always true. */
3931 static void
3932 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3933 omp_context *ctx)
3935 tree x, c, label = NULL, orig_clauses = clauses;
3936 bool par_clauses = false;
3937 tree simduid = NULL, lastlane = NULL;
3939 /* Early exit if there are no lastprivate or linear clauses. */
3940 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3941 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3942 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3943 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3944 break;
3945 if (clauses == NULL)
3947 /* If this was a workshare clause, see if it had been combined
3948 with its parallel. In that case, look for the clauses on the
3949 parallel statement itself. */
3950 if (is_parallel_ctx (ctx))
3951 return;
3953 ctx = ctx->outer;
3954 if (ctx == NULL || !is_parallel_ctx (ctx))
3955 return;
3957 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3958 OMP_CLAUSE_LASTPRIVATE);
3959 if (clauses == NULL)
3960 return;
3961 par_clauses = true;
3964 if (predicate)
3966 gcond *stmt;
3967 tree label_true, arm1, arm2;
3969 label = create_artificial_label (UNKNOWN_LOCATION);
3970 label_true = create_artificial_label (UNKNOWN_LOCATION);
3971 arm1 = TREE_OPERAND (predicate, 0);
3972 arm2 = TREE_OPERAND (predicate, 1);
3973 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3974 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3975 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3976 label_true, label);
3977 gimple_seq_add_stmt (stmt_list, stmt);
3978 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3981 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3982 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3984 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3985 if (simduid)
3986 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3989 for (c = clauses; c ;)
3991 tree var, new_var;
3992 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3994 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3995 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3996 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3998 var = OMP_CLAUSE_DECL (c);
3999 new_var = lookup_decl (var, ctx);
4001 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4003 tree val = DECL_VALUE_EXPR (new_var);
4004 if (TREE_CODE (val) == ARRAY_REF
4005 && VAR_P (TREE_OPERAND (val, 0))
4006 && lookup_attribute ("omp simd array",
4007 DECL_ATTRIBUTES (TREE_OPERAND (val,
4008 0))))
4010 if (lastlane == NULL)
4012 lastlane = create_tmp_var (unsigned_type_node, NULL);
4013 gcall *g
4014 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4015 2, simduid,
4016 TREE_OPERAND (val, 1));
4017 gimple_call_set_lhs (g, lastlane);
4018 gimple_seq_add_stmt (stmt_list, g);
4020 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4021 TREE_OPERAND (val, 0), lastlane,
4022 NULL_TREE, NULL_TREE);
4026 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4027 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4029 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4030 gimple_seq_add_seq (stmt_list,
4031 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4032 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4034 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4035 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4037 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4038 gimple_seq_add_seq (stmt_list,
4039 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4040 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4043 x = build_outer_var_ref (var, ctx);
4044 if (is_reference (var))
4045 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4046 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4047 gimplify_and_add (x, stmt_list);
4049 c = OMP_CLAUSE_CHAIN (c);
4050 if (c == NULL && !par_clauses)
4052 /* If this was a workshare clause, see if it had been combined
4053 with its parallel. In that case, continue looking for the
4054 clauses also on the parallel statement itself. */
4055 if (is_parallel_ctx (ctx))
4056 break;
4058 ctx = ctx->outer;
4059 if (ctx == NULL || !is_parallel_ctx (ctx))
4060 break;
4062 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4063 OMP_CLAUSE_LASTPRIVATE);
4064 par_clauses = true;
4068 if (label)
4069 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4073 /* Generate code to implement the REDUCTION clauses. */
4075 static void
4076 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4078 gimple_seq sub_seq = NULL;
4079 gimple stmt;
4080 tree x, c;
4081 int count = 0;
4083 /* SIMD reductions are handled in lower_rec_input_clauses. */
4084 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4085 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4086 return;
4088 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4089 update in that case, otherwise use a lock. */
4090 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4091 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4093 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4095 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4096 count = -1;
4097 break;
4099 count++;
4102 if (count == 0)
4103 return;
4105 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4107 tree var, ref, new_var;
4108 enum tree_code code;
4109 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4111 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4112 continue;
4114 var = OMP_CLAUSE_DECL (c);
4115 new_var = lookup_decl (var, ctx);
4116 if (is_reference (var))
4117 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4118 ref = build_outer_var_ref (var, ctx);
4119 code = OMP_CLAUSE_REDUCTION_CODE (c);
4121 /* reduction(-:var) sums up the partial results, so it acts
4122 identically to reduction(+:var). */
4123 if (code == MINUS_EXPR)
4124 code = PLUS_EXPR;
4126 if (count == 1)
4128 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4130 addr = save_expr (addr);
4131 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4132 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4133 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4134 gimplify_and_add (x, stmt_seqp);
4135 return;
4138 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4140 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4142 if (is_reference (var)
4143 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4144 TREE_TYPE (ref)))
4145 ref = build_fold_addr_expr_loc (clause_loc, ref);
4146 SET_DECL_VALUE_EXPR (placeholder, ref);
4147 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4148 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4149 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4150 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4151 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4153 else
4155 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4156 ref = build_outer_var_ref (var, ctx);
4157 gimplify_assign (ref, x, &sub_seq);
4161 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4163 gimple_seq_add_stmt (stmt_seqp, stmt);
4165 gimple_seq_add_seq (stmt_seqp, sub_seq);
4167 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4169 gimple_seq_add_stmt (stmt_seqp, stmt);
4173 /* Generate code to implement the COPYPRIVATE clauses. */
4175 static void
4176 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4177 omp_context *ctx)
4179 tree c;
4181 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4183 tree var, new_var, ref, x;
4184 bool by_ref;
4185 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4187 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4188 continue;
4190 var = OMP_CLAUSE_DECL (c);
4191 by_ref = use_pointer_for_field (var, NULL);
4193 ref = build_sender_ref (var, ctx);
4194 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4195 if (by_ref)
4197 x = build_fold_addr_expr_loc (clause_loc, new_var);
4198 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4200 gimplify_assign (ref, x, slist);
4202 ref = build_receiver_ref (var, false, ctx);
4203 if (by_ref)
4205 ref = fold_convert_loc (clause_loc,
4206 build_pointer_type (TREE_TYPE (new_var)),
4207 ref);
4208 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4210 if (is_reference (var))
4212 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4213 ref = build_simple_mem_ref_loc (clause_loc, ref);
4214 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4216 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4217 gimplify_and_add (x, rlist);
4222 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4223 and REDUCTION from the sender (aka parent) side. */
4225 static void
4226 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4227 omp_context *ctx)
4229 tree c;
4231 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4233 tree val, ref, x, var;
4234 bool by_ref, do_in = false, do_out = false;
4235 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4237 switch (OMP_CLAUSE_CODE (c))
4239 case OMP_CLAUSE_PRIVATE:
4240 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4241 break;
4242 continue;
4243 case OMP_CLAUSE_FIRSTPRIVATE:
4244 case OMP_CLAUSE_COPYIN:
4245 case OMP_CLAUSE_LASTPRIVATE:
4246 case OMP_CLAUSE_REDUCTION:
4247 case OMP_CLAUSE__LOOPTEMP_:
4248 break;
4249 default:
4250 continue;
4253 val = OMP_CLAUSE_DECL (c);
4254 var = lookup_decl_in_outer_ctx (val, ctx);
4256 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4257 && is_global_var (var))
4258 continue;
4259 if (is_variable_sized (val))
4260 continue;
4261 by_ref = use_pointer_for_field (val, NULL);
4263 switch (OMP_CLAUSE_CODE (c))
4265 case OMP_CLAUSE_PRIVATE:
4266 case OMP_CLAUSE_FIRSTPRIVATE:
4267 case OMP_CLAUSE_COPYIN:
4268 case OMP_CLAUSE__LOOPTEMP_:
4269 do_in = true;
4270 break;
4272 case OMP_CLAUSE_LASTPRIVATE:
4273 if (by_ref || is_reference (val))
4275 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4276 continue;
4277 do_in = true;
4279 else
4281 do_out = true;
4282 if (lang_hooks.decls.omp_private_outer_ref (val))
4283 do_in = true;
4285 break;
4287 case OMP_CLAUSE_REDUCTION:
4288 do_in = true;
4289 do_out = !(by_ref || is_reference (val));
4290 break;
4292 default:
4293 gcc_unreachable ();
4296 if (do_in)
4298 ref = build_sender_ref (val, ctx);
4299 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4300 gimplify_assign (ref, x, ilist);
4301 if (is_task_ctx (ctx))
4302 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4305 if (do_out)
4307 ref = build_sender_ref (val, ctx);
4308 gimplify_assign (var, ref, olist);
4313 /* Generate code to implement SHARED from the sender (aka parent)
4314 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4315 list things that got automatically shared. */
4317 static void
4318 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4320 tree var, ovar, nvar, f, x, record_type;
4322 if (ctx->record_type == NULL)
4323 return;
4325 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4326 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4328 ovar = DECL_ABSTRACT_ORIGIN (f);
4329 nvar = maybe_lookup_decl (ovar, ctx);
4330 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4331 continue;
4333 /* If CTX is a nested parallel directive. Find the immediately
4334 enclosing parallel or workshare construct that contains a
4335 mapping for OVAR. */
4336 var = lookup_decl_in_outer_ctx (ovar, ctx);
4338 if (use_pointer_for_field (ovar, ctx))
4340 x = build_sender_ref (ovar, ctx);
4341 var = build_fold_addr_expr (var);
4342 gimplify_assign (x, var, ilist);
4344 else
4346 x = build_sender_ref (ovar, ctx);
4347 gimplify_assign (x, var, ilist);
4349 if (!TREE_READONLY (var)
4350 /* We don't need to receive a new reference to a result
4351 or parm decl. In fact we may not store to it as we will
4352 invalidate any pending RSO and generate wrong gimple
4353 during inlining. */
4354 && !((TREE_CODE (var) == RESULT_DECL
4355 || TREE_CODE (var) == PARM_DECL)
4356 && DECL_BY_REFERENCE (var)))
4358 x = build_sender_ref (ovar, ctx);
4359 gimplify_assign (var, x, olist);
4366 /* A convenience function to build an empty GIMPLE_COND with just the
4367 condition. */
4369 static gcond *
4370 gimple_build_cond_empty (tree cond)
4372 enum tree_code pred_code;
4373 tree lhs, rhs;
4375 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4376 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4380 /* Build the function calls to GOMP_parallel_start etc to actually
4381 generate the parallel operation. REGION is the parallel region
4382 being expanded. BB is the block where to insert the code. WS_ARGS
4383 will be set if this is a call to a combined parallel+workshare
4384 construct, it contains the list of additional arguments needed by
4385 the workshare construct. */
4387 static void
4388 expand_parallel_call (struct omp_region *region, basic_block bb,
4389 gomp_parallel *entry_stmt,
4390 vec<tree, va_gc> *ws_args)
4392 tree t, t1, t2, val, cond, c, clauses, flags;
4393 gimple_stmt_iterator gsi;
4394 gimple stmt;
4395 enum built_in_function start_ix;
4396 int start_ix2;
4397 location_t clause_loc;
4398 vec<tree, va_gc> *args;
4400 clauses = gimple_omp_parallel_clauses (entry_stmt);
4402 /* Determine what flavor of GOMP_parallel we will be
4403 emitting. */
4404 start_ix = BUILT_IN_GOMP_PARALLEL;
4405 if (is_combined_parallel (region))
4407 switch (region->inner->type)
4409 case GIMPLE_OMP_FOR:
4410 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4411 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4412 + (region->inner->sched_kind
4413 == OMP_CLAUSE_SCHEDULE_RUNTIME
4414 ? 3 : region->inner->sched_kind));
4415 start_ix = (enum built_in_function)start_ix2;
4416 break;
4417 case GIMPLE_OMP_SECTIONS:
4418 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4419 break;
4420 default:
4421 gcc_unreachable ();
4425 /* By default, the value of NUM_THREADS is zero (selected at run time)
4426 and there is no conditional. */
4427 cond = NULL_TREE;
4428 val = build_int_cst (unsigned_type_node, 0);
4429 flags = build_int_cst (unsigned_type_node, 0);
4431 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4432 if (c)
4433 cond = OMP_CLAUSE_IF_EXPR (c);
4435 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4436 if (c)
4438 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4439 clause_loc = OMP_CLAUSE_LOCATION (c);
4441 else
4442 clause_loc = gimple_location (entry_stmt);
4444 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4445 if (c)
4446 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4448 /* Ensure 'val' is of the correct type. */
4449 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4451 /* If we found the clause 'if (cond)', build either
4452 (cond != 0) or (cond ? val : 1u). */
4453 if (cond)
4455 cond = gimple_boolify (cond);
4457 if (integer_zerop (val))
4458 val = fold_build2_loc (clause_loc,
4459 EQ_EXPR, unsigned_type_node, cond,
4460 build_int_cst (TREE_TYPE (cond), 0));
4461 else
4463 basic_block cond_bb, then_bb, else_bb;
4464 edge e, e_then, e_else;
4465 tree tmp_then, tmp_else, tmp_join, tmp_var;
4467 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4468 if (gimple_in_ssa_p (cfun))
4470 tmp_then = make_ssa_name (tmp_var, NULL);
4471 tmp_else = make_ssa_name (tmp_var, NULL);
4472 tmp_join = make_ssa_name (tmp_var, NULL);
4474 else
4476 tmp_then = tmp_var;
4477 tmp_else = tmp_var;
4478 tmp_join = tmp_var;
4481 e = split_block (bb, NULL);
4482 cond_bb = e->src;
4483 bb = e->dest;
4484 remove_edge (e);
4486 then_bb = create_empty_bb (cond_bb);
4487 else_bb = create_empty_bb (then_bb);
4488 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4489 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4491 stmt = gimple_build_cond_empty (cond);
4492 gsi = gsi_start_bb (cond_bb);
4493 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4495 gsi = gsi_start_bb (then_bb);
4496 stmt = gimple_build_assign (tmp_then, val);
4497 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4499 gsi = gsi_start_bb (else_bb);
4500 stmt = gimple_build_assign
4501 (tmp_else, build_int_cst (unsigned_type_node, 1));
4502 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4504 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4505 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4506 add_bb_to_loop (then_bb, cond_bb->loop_father);
4507 add_bb_to_loop (else_bb, cond_bb->loop_father);
4508 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4509 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4511 if (gimple_in_ssa_p (cfun))
4513 gphi *phi = create_phi_node (tmp_join, bb);
4514 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4515 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4518 val = tmp_join;
4521 gsi = gsi_start_bb (bb);
4522 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4523 false, GSI_CONTINUE_LINKING);
4526 gsi = gsi_last_bb (bb);
4527 t = gimple_omp_parallel_data_arg (entry_stmt);
4528 if (t == NULL)
4529 t1 = null_pointer_node;
4530 else
4531 t1 = build_fold_addr_expr (t);
4532 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4534 vec_alloc (args, 4 + vec_safe_length (ws_args));
4535 args->quick_push (t2);
4536 args->quick_push (t1);
4537 args->quick_push (val);
4538 if (ws_args)
4539 args->splice (*ws_args);
4540 args->quick_push (flags);
4542 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4543 builtin_decl_explicit (start_ix), args);
4545 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4546 false, GSI_CONTINUE_LINKING);
4549 /* Insert a function call whose name is FUNC_NAME with the information from
4550 ENTRY_STMT into the basic_block BB. */
4552 static void
4553 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
4554 vec <tree, va_gc> *ws_args)
4556 tree t, t1, t2;
4557 gimple_stmt_iterator gsi;
4558 vec <tree, va_gc> *args;
4560 gcc_assert (vec_safe_length (ws_args) == 2);
4561 tree func_name = (*ws_args)[0];
4562 tree grain = (*ws_args)[1];
4564 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
4565 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
4566 gcc_assert (count != NULL_TREE);
4567 count = OMP_CLAUSE_OPERAND (count, 0);
4569 gsi = gsi_last_bb (bb);
4570 t = gimple_omp_parallel_data_arg (entry_stmt);
4571 if (t == NULL)
4572 t1 = null_pointer_node;
4573 else
4574 t1 = build_fold_addr_expr (t);
4575 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4577 vec_alloc (args, 4);
4578 args->quick_push (t2);
4579 args->quick_push (t1);
4580 args->quick_push (count);
4581 args->quick_push (grain);
4582 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
4584 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
4585 GSI_CONTINUE_LINKING);
4588 /* Build the function call to GOMP_task to actually
4589 generate the task operation. BB is the block where to insert the code. */
4591 static void
4592 expand_task_call (basic_block bb, gomp_task *entry_stmt)
4594 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4595 gimple_stmt_iterator gsi;
4596 location_t loc = gimple_location (entry_stmt);
4598 clauses = gimple_omp_task_clauses (entry_stmt);
4600 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4601 if (c)
4602 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4603 else
4604 cond = boolean_true_node;
4606 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4607 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4608 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4609 flags = build_int_cst (unsigned_type_node,
4610 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4612 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4613 if (c)
4615 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4616 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4617 build_int_cst (unsigned_type_node, 2),
4618 build_int_cst (unsigned_type_node, 0));
4619 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4621 if (depend)
4622 depend = OMP_CLAUSE_DECL (depend);
4623 else
4624 depend = build_int_cst (ptr_type_node, 0);
4626 gsi = gsi_last_bb (bb);
4627 t = gimple_omp_task_data_arg (entry_stmt);
4628 if (t == NULL)
4629 t2 = null_pointer_node;
4630 else
4631 t2 = build_fold_addr_expr_loc (loc, t);
4632 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4633 t = gimple_omp_task_copy_fn (entry_stmt);
4634 if (t == NULL)
4635 t3 = null_pointer_node;
4636 else
4637 t3 = build_fold_addr_expr_loc (loc, t);
4639 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4640 8, t1, t2, t3,
4641 gimple_omp_task_arg_size (entry_stmt),
4642 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4643 depend);
4645 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4646 false, GSI_CONTINUE_LINKING);
4650 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4651 catch handler and return it. This prevents programs from violating the
4652 structured block semantics with throws. */
4654 static gimple_seq
4655 maybe_catch_exception (gimple_seq body)
4657 gimple g;
4658 tree decl;
4660 if (!flag_exceptions)
4661 return body;
4663 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4664 decl = lang_hooks.eh_protect_cleanup_actions ();
4665 else
4666 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4668 g = gimple_build_eh_must_not_throw (decl);
4669 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4670 GIMPLE_TRY_CATCH);
4672 return gimple_seq_alloc_with_stmt (g);
4675 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4677 static tree
4678 vec2chain (vec<tree, va_gc> *v)
4680 tree chain = NULL_TREE, t;
4681 unsigned ix;
4683 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4685 DECL_CHAIN (t) = chain;
4686 chain = t;
4689 return chain;
4693 /* Remove barriers in REGION->EXIT's block. Note that this is only
4694 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4695 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4696 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4697 removed. */
4699 static void
4700 remove_exit_barrier (struct omp_region *region)
4702 gimple_stmt_iterator gsi;
4703 basic_block exit_bb;
4704 edge_iterator ei;
4705 edge e;
4706 gimple stmt;
4707 int any_addressable_vars = -1;
4709 exit_bb = region->exit;
4711 /* If the parallel region doesn't return, we don't have REGION->EXIT
4712 block at all. */
4713 if (! exit_bb)
4714 return;
4716 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4717 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4718 statements that can appear in between are extremely limited -- no
4719 memory operations at all. Here, we allow nothing at all, so the
4720 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4721 gsi = gsi_last_bb (exit_bb);
4722 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4723 gsi_prev (&gsi);
4724 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4725 return;
4727 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4729 gsi = gsi_last_bb (e->src);
4730 if (gsi_end_p (gsi))
4731 continue;
4732 stmt = gsi_stmt (gsi);
4733 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4734 && !gimple_omp_return_nowait_p (stmt))
4736 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4737 in many cases. If there could be tasks queued, the barrier
4738 might be needed to let the tasks run before some local
4739 variable of the parallel that the task uses as shared
4740 runs out of scope. The task can be spawned either
4741 from within current function (this would be easy to check)
4742 or from some function it calls and gets passed an address
4743 of such a variable. */
4744 if (any_addressable_vars < 0)
4746 gomp_parallel *parallel_stmt
4747 = as_a <gomp_parallel *> (last_stmt (region->entry));
4748 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4749 tree local_decls, block, decl;
4750 unsigned ix;
4752 any_addressable_vars = 0;
4753 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4754 if (TREE_ADDRESSABLE (decl))
4756 any_addressable_vars = 1;
4757 break;
4759 for (block = gimple_block (stmt);
4760 !any_addressable_vars
4761 && block
4762 && TREE_CODE (block) == BLOCK;
4763 block = BLOCK_SUPERCONTEXT (block))
4765 for (local_decls = BLOCK_VARS (block);
4766 local_decls;
4767 local_decls = DECL_CHAIN (local_decls))
4768 if (TREE_ADDRESSABLE (local_decls))
4770 any_addressable_vars = 1;
4771 break;
4773 if (block == gimple_block (parallel_stmt))
4774 break;
4777 if (!any_addressable_vars)
4778 gimple_omp_return_set_nowait (stmt);
4783 static void
4784 remove_exit_barriers (struct omp_region *region)
4786 if (region->type == GIMPLE_OMP_PARALLEL)
4787 remove_exit_barrier (region);
4789 if (region->inner)
4791 region = region->inner;
4792 remove_exit_barriers (region);
4793 while (region->next)
4795 region = region->next;
4796 remove_exit_barriers (region);
4801 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4802 calls. These can't be declared as const functions, but
4803 within one parallel body they are constant, so they can be
4804 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4805 which are declared const. Similarly for task body, except
4806 that in untied task omp_get_thread_num () can change at any task
4807 scheduling point. */
4809 static void
4810 optimize_omp_library_calls (gimple entry_stmt)
4812 basic_block bb;
4813 gimple_stmt_iterator gsi;
4814 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4815 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4816 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4817 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4818 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4819 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4820 OMP_CLAUSE_UNTIED) != NULL);
4822 FOR_EACH_BB_FN (bb, cfun)
4823 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4825 gimple call = gsi_stmt (gsi);
4826 tree decl;
4828 if (is_gimple_call (call)
4829 && (decl = gimple_call_fndecl (call))
4830 && DECL_EXTERNAL (decl)
4831 && TREE_PUBLIC (decl)
4832 && DECL_INITIAL (decl) == NULL)
4834 tree built_in;
4836 if (DECL_NAME (decl) == thr_num_id)
4838 /* In #pragma omp task untied omp_get_thread_num () can change
4839 during the execution of the task region. */
4840 if (untied_task)
4841 continue;
4842 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4844 else if (DECL_NAME (decl) == num_thr_id)
4845 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4846 else
4847 continue;
4849 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4850 || gimple_call_num_args (call) != 0)
4851 continue;
4853 if (flag_exceptions && !TREE_NOTHROW (decl))
4854 continue;
4856 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4857 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4858 TREE_TYPE (TREE_TYPE (built_in))))
4859 continue;
4861 gimple_call_set_fndecl (call, built_in);
4866 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4867 regimplified. */
4869 static tree
4870 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4872 tree t = *tp;
4874 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4875 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4876 return t;
4878 if (TREE_CODE (t) == ADDR_EXPR)
4879 recompute_tree_invariant_for_addr_expr (t);
4881 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4882 return NULL_TREE;
4885 /* Prepend TO = FROM assignment before *GSI_P. */
4887 static void
4888 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4890 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4891 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4892 true, GSI_SAME_STMT);
4893 gimple stmt = gimple_build_assign (to, from);
4894 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4895 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4896 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4898 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4899 gimple_regimplify_operands (stmt, &gsi);
4903 /* Expand the OpenMP parallel or task directive starting at REGION. */
4905 static void
4906 expand_omp_taskreg (struct omp_region *region)
4908 basic_block entry_bb, exit_bb, new_bb;
4909 struct function *child_cfun;
4910 tree child_fn, block, t;
4911 gimple_stmt_iterator gsi;
4912 gimple entry_stmt, stmt;
4913 edge e;
4914 vec<tree, va_gc> *ws_args;
4916 entry_stmt = last_stmt (region->entry);
4917 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4918 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4920 entry_bb = region->entry;
4921 exit_bb = region->exit;
4923 bool is_cilk_for
4924 = (flag_cilkplus
4925 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
4926 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
4927 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
4929 if (is_cilk_for)
4930 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
4931 and the inner statement contains the name of the built-in function
4932 and grain. */
4933 ws_args = region->inner->ws_args;
4934 else if (is_combined_parallel (region))
4935 ws_args = region->ws_args;
4936 else
4937 ws_args = NULL;
4939 if (child_cfun->cfg)
4941 /* Due to inlining, it may happen that we have already outlined
4942 the region, in which case all we need to do is make the
4943 sub-graph unreachable and emit the parallel call. */
4944 edge entry_succ_e, exit_succ_e;
4946 entry_succ_e = single_succ_edge (entry_bb);
4948 gsi = gsi_last_bb (entry_bb);
4949 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4950 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4951 gsi_remove (&gsi, true);
4953 new_bb = entry_bb;
4954 if (exit_bb)
4956 exit_succ_e = single_succ_edge (exit_bb);
4957 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4959 remove_edge_and_dominated_blocks (entry_succ_e);
4961 else
4963 unsigned srcidx, dstidx, num;
4965 /* If the parallel region needs data sent from the parent
4966 function, then the very first statement (except possible
4967 tree profile counter updates) of the parallel body
4968 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4969 &.OMP_DATA_O is passed as an argument to the child function,
4970 we need to replace it with the argument as seen by the child
4971 function.
4973 In most cases, this will end up being the identity assignment
4974 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4975 a function call that has been inlined, the original PARM_DECL
4976 .OMP_DATA_I may have been converted into a different local
4977 variable. In which case, we need to keep the assignment. */
4978 if (gimple_omp_taskreg_data_arg (entry_stmt))
4980 basic_block entry_succ_bb = single_succ (entry_bb);
4981 tree arg, narg;
4982 gimple parcopy_stmt = NULL;
4984 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4986 gimple stmt;
4988 gcc_assert (!gsi_end_p (gsi));
4989 stmt = gsi_stmt (gsi);
4990 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4991 continue;
4993 if (gimple_num_ops (stmt) == 2)
4995 tree arg = gimple_assign_rhs1 (stmt);
4997 /* We're ignore the subcode because we're
4998 effectively doing a STRIP_NOPS. */
5000 if (TREE_CODE (arg) == ADDR_EXPR
5001 && TREE_OPERAND (arg, 0)
5002 == gimple_omp_taskreg_data_arg (entry_stmt))
5004 parcopy_stmt = stmt;
5005 break;
5010 gcc_assert (parcopy_stmt != NULL);
5011 arg = DECL_ARGUMENTS (child_fn);
5013 if (!gimple_in_ssa_p (cfun))
5015 if (gimple_assign_lhs (parcopy_stmt) == arg)
5016 gsi_remove (&gsi, true);
5017 else
5019 /* ?? Is setting the subcode really necessary ?? */
5020 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5021 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5024 else
5026 /* If we are in ssa form, we must load the value from the default
5027 definition of the argument. That should not be defined now,
5028 since the argument is not used uninitialized. */
5029 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5030 narg = make_ssa_name (arg, gimple_build_nop ());
5031 set_ssa_default_def (cfun, arg, narg);
5032 /* ?? Is setting the subcode really necessary ?? */
5033 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5034 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5035 update_stmt (parcopy_stmt);
5039 /* Declare local variables needed in CHILD_CFUN. */
5040 block = DECL_INITIAL (child_fn);
5041 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5042 /* The gimplifier could record temporaries in parallel/task block
5043 rather than in containing function's local_decls chain,
5044 which would mean cgraph missed finalizing them. Do it now. */
5045 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5046 if (TREE_CODE (t) == VAR_DECL
5047 && TREE_STATIC (t)
5048 && !DECL_EXTERNAL (t))
5049 varpool_node::finalize_decl (t);
5050 DECL_SAVED_TREE (child_fn) = NULL;
5051 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5052 gimple_set_body (child_fn, NULL);
5053 TREE_USED (block) = 1;
5055 /* Reset DECL_CONTEXT on function arguments. */
5056 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5057 DECL_CONTEXT (t) = child_fn;
5059 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5060 so that it can be moved to the child function. */
5061 gsi = gsi_last_bb (entry_bb);
5062 stmt = gsi_stmt (gsi);
5063 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5064 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5065 gsi_remove (&gsi, true);
5066 e = split_block (entry_bb, stmt);
5067 entry_bb = e->dest;
5068 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5070 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5071 if (exit_bb)
5073 gsi = gsi_last_bb (exit_bb);
5074 gcc_assert (!gsi_end_p (gsi)
5075 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5076 stmt = gimple_build_return (NULL);
5077 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5078 gsi_remove (&gsi, true);
5081 /* Move the parallel region into CHILD_CFUN. */
5083 if (gimple_in_ssa_p (cfun))
5085 init_tree_ssa (child_cfun);
5086 init_ssa_operands (child_cfun);
5087 child_cfun->gimple_df->in_ssa_p = true;
5088 block = NULL_TREE;
5090 else
5091 block = gimple_block (entry_stmt);
5093 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5094 if (exit_bb)
5095 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5096 /* When the OMP expansion process cannot guarantee an up-to-date
5097 loop tree arrange for the child function to fixup loops. */
5098 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5099 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5101 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5102 num = vec_safe_length (child_cfun->local_decls);
5103 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5105 t = (*child_cfun->local_decls)[srcidx];
5106 if (DECL_CONTEXT (t) == cfun->decl)
5107 continue;
5108 if (srcidx != dstidx)
5109 (*child_cfun->local_decls)[dstidx] = t;
5110 dstidx++;
5112 if (dstidx != num)
5113 vec_safe_truncate (child_cfun->local_decls, dstidx);
5115 /* Inform the callgraph about the new function. */
5116 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5117 cgraph_node::add_new_function (child_fn, true);
5119 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5120 fixed in a following pass. */
5121 push_cfun (child_cfun);
5122 if (optimize)
5123 optimize_omp_library_calls (entry_stmt);
5124 cgraph_edge::rebuild_edges ();
5126 /* Some EH regions might become dead, see PR34608. If
5127 pass_cleanup_cfg isn't the first pass to happen with the
5128 new child, these dead EH edges might cause problems.
5129 Clean them up now. */
5130 if (flag_exceptions)
5132 basic_block bb;
5133 bool changed = false;
5135 FOR_EACH_BB_FN (bb, cfun)
5136 changed |= gimple_purge_dead_eh_edges (bb);
5137 if (changed)
5138 cleanup_tree_cfg ();
5140 if (gimple_in_ssa_p (cfun))
5141 update_ssa (TODO_update_ssa);
5142 pop_cfun ();
5145 /* Emit a library call to launch the children threads. */
5146 if (is_cilk_for)
5147 expand_cilk_for_call (new_bb,
5148 as_a <gomp_parallel *> (entry_stmt), ws_args);
5149 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5150 expand_parallel_call (region, new_bb,
5151 as_a <gomp_parallel *> (entry_stmt), ws_args);
5152 else
5153 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5154 if (gimple_in_ssa_p (cfun))
5155 update_ssa (TODO_update_ssa_only_virtuals);
5159 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5160 of the combined collapse > 1 loop constructs, generate code like:
5161 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5162 if (cond3 is <)
5163 adj = STEP3 - 1;
5164 else
5165 adj = STEP3 + 1;
5166 count3 = (adj + N32 - N31) / STEP3;
5167 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5168 if (cond2 is <)
5169 adj = STEP2 - 1;
5170 else
5171 adj = STEP2 + 1;
5172 count2 = (adj + N22 - N21) / STEP2;
5173 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5174 if (cond1 is <)
5175 adj = STEP1 - 1;
5176 else
5177 adj = STEP1 + 1;
5178 count1 = (adj + N12 - N11) / STEP1;
5179 count = count1 * count2 * count3;
5180 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5181 count = 0;
5182 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5183 of the combined loop constructs, just initialize COUNTS array
5184 from the _looptemp_ clauses. */
5186 /* NOTE: It *could* be better to moosh all of the BBs together,
5187 creating one larger BB with all the computation and the unexpected
5188 jump at the end. I.e.
5190 bool zero3, zero2, zero1, zero;
5192 zero3 = N32 c3 N31;
5193 count3 = (N32 - N31) /[cl] STEP3;
5194 zero2 = N22 c2 N21;
5195 count2 = (N22 - N21) /[cl] STEP2;
5196 zero1 = N12 c1 N11;
5197 count1 = (N12 - N11) /[cl] STEP1;
5198 zero = zero3 || zero2 || zero1;
5199 count = count1 * count2 * count3;
5200 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5202 After all, we expect the zero=false, and thus we expect to have to
5203 evaluate all of the comparison expressions, so short-circuiting
5204 oughtn't be a win. Since the condition isn't protecting a
5205 denominator, we're not concerned about divide-by-zero, so we can
5206 fully evaluate count even if a numerator turned out to be wrong.
5208 It seems like putting this all together would create much better
5209 scheduling opportunities, and less pressure on the chip's branch
5210 predictor. */
5212 static void
5213 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5214 basic_block &entry_bb, tree *counts,
5215 basic_block &zero_iter_bb, int &first_zero_iter,
5216 basic_block &l2_dom_bb)
5218 tree t, type = TREE_TYPE (fd->loop.v);
5219 edge e, ne;
5220 int i;
5222 /* Collapsed loops need work for expansion into SSA form. */
5223 gcc_assert (!gimple_in_ssa_p (cfun));
5225 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5226 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5228 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5229 isn't supposed to be handled, as the inner loop doesn't
5230 use it. */
5231 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5232 OMP_CLAUSE__LOOPTEMP_);
5233 gcc_assert (innerc);
5234 for (i = 0; i < fd->collapse; i++)
5236 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5237 OMP_CLAUSE__LOOPTEMP_);
5238 gcc_assert (innerc);
5239 if (i)
5240 counts[i] = OMP_CLAUSE_DECL (innerc);
5241 else
5242 counts[0] = NULL_TREE;
5244 return;
5247 for (i = 0; i < fd->collapse; i++)
5249 tree itype = TREE_TYPE (fd->loops[i].v);
5251 if (SSA_VAR_P (fd->loop.n2)
5252 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5253 fold_convert (itype, fd->loops[i].n1),
5254 fold_convert (itype, fd->loops[i].n2)))
5255 == NULL_TREE || !integer_onep (t)))
5257 gcond *cond_stmt;
5258 tree n1, n2;
5259 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5260 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5261 true, GSI_SAME_STMT);
5262 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5263 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5264 true, GSI_SAME_STMT);
5265 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5266 NULL_TREE, NULL_TREE);
5267 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5268 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5269 expand_omp_regimplify_p, NULL, NULL)
5270 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5271 expand_omp_regimplify_p, NULL, NULL))
5273 *gsi = gsi_for_stmt (cond_stmt);
5274 gimple_regimplify_operands (cond_stmt, gsi);
5276 e = split_block (entry_bb, cond_stmt);
5277 if (zero_iter_bb == NULL)
5279 gassign *assign_stmt;
5280 first_zero_iter = i;
5281 zero_iter_bb = create_empty_bb (entry_bb);
5282 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5283 *gsi = gsi_after_labels (zero_iter_bb);
5284 assign_stmt = gimple_build_assign (fd->loop.n2,
5285 build_zero_cst (type));
5286 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5287 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5288 entry_bb);
5290 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5291 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5292 e->flags = EDGE_TRUE_VALUE;
5293 e->probability = REG_BR_PROB_BASE - ne->probability;
5294 if (l2_dom_bb == NULL)
5295 l2_dom_bb = entry_bb;
5296 entry_bb = e->dest;
5297 *gsi = gsi_last_bb (entry_bb);
5300 if (POINTER_TYPE_P (itype))
5301 itype = signed_type_for (itype);
5302 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5303 ? -1 : 1));
5304 t = fold_build2 (PLUS_EXPR, itype,
5305 fold_convert (itype, fd->loops[i].step), t);
5306 t = fold_build2 (PLUS_EXPR, itype, t,
5307 fold_convert (itype, fd->loops[i].n2));
5308 t = fold_build2 (MINUS_EXPR, itype, t,
5309 fold_convert (itype, fd->loops[i].n1));
5310 /* ?? We could probably use CEIL_DIV_EXPR instead of
5311 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5312 generate the same code in the end because generically we
5313 don't know that the values involved must be negative for
5314 GT?? */
5315 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5316 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5317 fold_build1 (NEGATE_EXPR, itype, t),
5318 fold_build1 (NEGATE_EXPR, itype,
5319 fold_convert (itype,
5320 fd->loops[i].step)));
5321 else
5322 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5323 fold_convert (itype, fd->loops[i].step));
5324 t = fold_convert (type, t);
5325 if (TREE_CODE (t) == INTEGER_CST)
5326 counts[i] = t;
5327 else
5329 counts[i] = create_tmp_reg (type, ".count");
5330 expand_omp_build_assign (gsi, counts[i], t);
5332 if (SSA_VAR_P (fd->loop.n2))
5334 if (i == 0)
5335 t = counts[0];
5336 else
5337 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5338 expand_omp_build_assign (gsi, fd->loop.n2, t);
5344 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5345 T = V;
5346 V3 = N31 + (T % count3) * STEP3;
5347 T = T / count3;
5348 V2 = N21 + (T % count2) * STEP2;
5349 T = T / count2;
5350 V1 = N11 + T * STEP1;
5351 if this loop doesn't have an inner loop construct combined with it.
5352 If it does have an inner loop construct combined with it and the
5353 iteration count isn't known constant, store values from counts array
5354 into its _looptemp_ temporaries instead. */
5356 static void
5357 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5358 tree *counts, gimple inner_stmt, tree startvar)
5360 int i;
5361 if (gimple_omp_for_combined_p (fd->for_stmt))
5363 /* If fd->loop.n2 is constant, then no propagation of the counts
5364 is needed, they are constant. */
5365 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5366 return;
5368 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5369 ? gimple_omp_parallel_clauses (inner_stmt)
5370 : gimple_omp_for_clauses (inner_stmt);
5371 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5372 isn't supposed to be handled, as the inner loop doesn't
5373 use it. */
5374 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5375 gcc_assert (innerc);
5376 for (i = 0; i < fd->collapse; i++)
5378 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5379 OMP_CLAUSE__LOOPTEMP_);
5380 gcc_assert (innerc);
5381 if (i)
5383 tree tem = OMP_CLAUSE_DECL (innerc);
5384 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5385 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5386 false, GSI_CONTINUE_LINKING);
5387 gassign *stmt = gimple_build_assign (tem, t);
5388 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5391 return;
5394 tree type = TREE_TYPE (fd->loop.v);
5395 tree tem = create_tmp_reg (type, ".tem");
5396 gassign *stmt = gimple_build_assign (tem, startvar);
5397 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5399 for (i = fd->collapse - 1; i >= 0; i--)
5401 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5402 itype = vtype;
5403 if (POINTER_TYPE_P (vtype))
5404 itype = signed_type_for (vtype);
5405 if (i != 0)
5406 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5407 else
5408 t = tem;
5409 t = fold_convert (itype, t);
5410 t = fold_build2 (MULT_EXPR, itype, t,
5411 fold_convert (itype, fd->loops[i].step));
5412 if (POINTER_TYPE_P (vtype))
5413 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5414 else
5415 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5416 t = force_gimple_operand_gsi (gsi, t,
5417 DECL_P (fd->loops[i].v)
5418 && TREE_ADDRESSABLE (fd->loops[i].v),
5419 NULL_TREE, false,
5420 GSI_CONTINUE_LINKING);
5421 stmt = gimple_build_assign (fd->loops[i].v, t);
5422 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5423 if (i != 0)
5425 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5426 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5427 false, GSI_CONTINUE_LINKING);
5428 stmt = gimple_build_assign (tem, t);
5429 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5435 /* Helper function for expand_omp_for_*. Generate code like:
5436 L10:
5437 V3 += STEP3;
5438 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5439 L11:
5440 V3 = N31;
5441 V2 += STEP2;
5442 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5443 L12:
5444 V2 = N21;
5445 V1 += STEP1;
5446 goto BODY_BB; */
5448 static basic_block
5449 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5450 basic_block body_bb)
5452 basic_block last_bb, bb, collapse_bb = NULL;
5453 int i;
5454 gimple_stmt_iterator gsi;
5455 edge e;
5456 tree t;
5457 gimple stmt;
5459 last_bb = cont_bb;
5460 for (i = fd->collapse - 1; i >= 0; i--)
5462 tree vtype = TREE_TYPE (fd->loops[i].v);
5464 bb = create_empty_bb (last_bb);
5465 add_bb_to_loop (bb, last_bb->loop_father);
5466 gsi = gsi_start_bb (bb);
5468 if (i < fd->collapse - 1)
5470 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5471 e->probability = REG_BR_PROB_BASE / 8;
5473 t = fd->loops[i + 1].n1;
5474 t = force_gimple_operand_gsi (&gsi, t,
5475 DECL_P (fd->loops[i + 1].v)
5476 && TREE_ADDRESSABLE (fd->loops[i
5477 + 1].v),
5478 NULL_TREE, false,
5479 GSI_CONTINUE_LINKING);
5480 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5481 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5483 else
5484 collapse_bb = bb;
5486 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5488 if (POINTER_TYPE_P (vtype))
5489 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5490 else
5491 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5492 t = force_gimple_operand_gsi (&gsi, t,
5493 DECL_P (fd->loops[i].v)
5494 && TREE_ADDRESSABLE (fd->loops[i].v),
5495 NULL_TREE, false, GSI_CONTINUE_LINKING);
5496 stmt = gimple_build_assign (fd->loops[i].v, t);
5497 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5499 if (i > 0)
5501 t = fd->loops[i].n2;
5502 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5503 false, GSI_CONTINUE_LINKING);
5504 tree v = fd->loops[i].v;
5505 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5506 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5507 false, GSI_CONTINUE_LINKING);
5508 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5509 stmt = gimple_build_cond_empty (t);
5510 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5511 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5512 e->probability = REG_BR_PROB_BASE * 7 / 8;
5514 else
5515 make_edge (bb, body_bb, EDGE_FALLTHRU);
5516 last_bb = bb;
5519 return collapse_bb;
5523 /* A subroutine of expand_omp_for. Generate code for a parallel
5524 loop with any schedule. Given parameters:
5526 for (V = N1; V cond N2; V += STEP) BODY;
5528 where COND is "<" or ">", we generate pseudocode
5530 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5531 if (more) goto L0; else goto L3;
5533 V = istart0;
5534 iend = iend0;
5536 BODY;
5537 V += STEP;
5538 if (V cond iend) goto L1; else goto L2;
5540 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5543 If this is a combined omp parallel loop, instead of the call to
5544 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5545 If this is gimple_omp_for_combined_p loop, then instead of assigning
5546 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5547 inner GIMPLE_OMP_FOR and V += STEP; and
5548 if (V cond iend) goto L1; else goto L2; are removed.
5550 For collapsed loops, given parameters:
5551 collapse(3)
5552 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5553 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5554 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5555 BODY;
5557 we generate pseudocode
5559 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5560 if (cond3 is <)
5561 adj = STEP3 - 1;
5562 else
5563 adj = STEP3 + 1;
5564 count3 = (adj + N32 - N31) / STEP3;
5565 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5566 if (cond2 is <)
5567 adj = STEP2 - 1;
5568 else
5569 adj = STEP2 + 1;
5570 count2 = (adj + N22 - N21) / STEP2;
5571 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5572 if (cond1 is <)
5573 adj = STEP1 - 1;
5574 else
5575 adj = STEP1 + 1;
5576 count1 = (adj + N12 - N11) / STEP1;
5577 count = count1 * count2 * count3;
5578 goto Z1;
5580 count = 0;
5582 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5583 if (more) goto L0; else goto L3;
5585 V = istart0;
5586 T = V;
5587 V3 = N31 + (T % count3) * STEP3;
5588 T = T / count3;
5589 V2 = N21 + (T % count2) * STEP2;
5590 T = T / count2;
5591 V1 = N11 + T * STEP1;
5592 iend = iend0;
5594 BODY;
5595 V += 1;
5596 if (V < iend) goto L10; else goto L2;
5597 L10:
5598 V3 += STEP3;
5599 if (V3 cond3 N32) goto L1; else goto L11;
5600 L11:
5601 V3 = N31;
5602 V2 += STEP2;
5603 if (V2 cond2 N22) goto L1; else goto L12;
5604 L12:
5605 V2 = N21;
5606 V1 += STEP1;
5607 goto L1;
5609 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5614 static void
5615 expand_omp_for_generic (struct omp_region *region,
5616 struct omp_for_data *fd,
5617 enum built_in_function start_fn,
5618 enum built_in_function next_fn,
5619 gimple inner_stmt)
5621 tree type, istart0, iend0, iend;
5622 tree t, vmain, vback, bias = NULL_TREE;
5623 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5624 basic_block l2_bb = NULL, l3_bb = NULL;
5625 gimple_stmt_iterator gsi;
5626 gassign *assign_stmt;
5627 bool in_combined_parallel = is_combined_parallel (region);
5628 bool broken_loop = region->cont == NULL;
5629 edge e, ne;
5630 tree *counts = NULL;
5631 int i;
5633 gcc_assert (!broken_loop || !in_combined_parallel);
5634 gcc_assert (fd->iter_type == long_integer_type_node
5635 || !in_combined_parallel);
5637 type = TREE_TYPE (fd->loop.v);
5638 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5639 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5640 TREE_ADDRESSABLE (istart0) = 1;
5641 TREE_ADDRESSABLE (iend0) = 1;
5643 /* See if we need to bias by LLONG_MIN. */
5644 if (fd->iter_type == long_long_unsigned_type_node
5645 && TREE_CODE (type) == INTEGER_TYPE
5646 && !TYPE_UNSIGNED (type))
5648 tree n1, n2;
5650 if (fd->loop.cond_code == LT_EXPR)
5652 n1 = fd->loop.n1;
5653 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5655 else
5657 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5658 n2 = fd->loop.n1;
5660 if (TREE_CODE (n1) != INTEGER_CST
5661 || TREE_CODE (n2) != INTEGER_CST
5662 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5663 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5666 entry_bb = region->entry;
5667 cont_bb = region->cont;
5668 collapse_bb = NULL;
5669 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5670 gcc_assert (broken_loop
5671 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5672 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5673 l1_bb = single_succ (l0_bb);
5674 if (!broken_loop)
5676 l2_bb = create_empty_bb (cont_bb);
5677 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5678 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5680 else
5681 l2_bb = NULL;
5682 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5683 exit_bb = region->exit;
5685 gsi = gsi_last_bb (entry_bb);
5687 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5688 if (fd->collapse > 1)
5690 int first_zero_iter = -1;
5691 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5693 counts = XALLOCAVEC (tree, fd->collapse);
5694 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5695 zero_iter_bb, first_zero_iter,
5696 l2_dom_bb);
5698 if (zero_iter_bb)
5700 /* Some counts[i] vars might be uninitialized if
5701 some loop has zero iterations. But the body shouldn't
5702 be executed in that case, so just avoid uninit warnings. */
5703 for (i = first_zero_iter; i < fd->collapse; i++)
5704 if (SSA_VAR_P (counts[i]))
5705 TREE_NO_WARNING (counts[i]) = 1;
5706 gsi_prev (&gsi);
5707 e = split_block (entry_bb, gsi_stmt (gsi));
5708 entry_bb = e->dest;
5709 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5710 gsi = gsi_last_bb (entry_bb);
5711 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5712 get_immediate_dominator (CDI_DOMINATORS,
5713 zero_iter_bb));
5716 if (in_combined_parallel)
5718 /* In a combined parallel loop, emit a call to
5719 GOMP_loop_foo_next. */
5720 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5721 build_fold_addr_expr (istart0),
5722 build_fold_addr_expr (iend0));
5724 else
5726 tree t0, t1, t2, t3, t4;
5727 /* If this is not a combined parallel loop, emit a call to
5728 GOMP_loop_foo_start in ENTRY_BB. */
5729 t4 = build_fold_addr_expr (iend0);
5730 t3 = build_fold_addr_expr (istart0);
5731 t2 = fold_convert (fd->iter_type, fd->loop.step);
5732 t1 = fd->loop.n2;
5733 t0 = fd->loop.n1;
5734 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5736 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5737 OMP_CLAUSE__LOOPTEMP_);
5738 gcc_assert (innerc);
5739 t0 = OMP_CLAUSE_DECL (innerc);
5740 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5741 OMP_CLAUSE__LOOPTEMP_);
5742 gcc_assert (innerc);
5743 t1 = OMP_CLAUSE_DECL (innerc);
5745 if (POINTER_TYPE_P (TREE_TYPE (t0))
5746 && TYPE_PRECISION (TREE_TYPE (t0))
5747 != TYPE_PRECISION (fd->iter_type))
5749 /* Avoid casting pointers to integer of a different size. */
5750 tree itype = signed_type_for (type);
5751 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5752 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5754 else
5756 t1 = fold_convert (fd->iter_type, t1);
5757 t0 = fold_convert (fd->iter_type, t0);
5759 if (bias)
5761 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5762 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5764 if (fd->iter_type == long_integer_type_node)
5766 if (fd->chunk_size)
5768 t = fold_convert (fd->iter_type, fd->chunk_size);
5769 t = build_call_expr (builtin_decl_explicit (start_fn),
5770 6, t0, t1, t2, t, t3, t4);
5772 else
5773 t = build_call_expr (builtin_decl_explicit (start_fn),
5774 5, t0, t1, t2, t3, t4);
5776 else
5778 tree t5;
5779 tree c_bool_type;
5780 tree bfn_decl;
5782 /* The GOMP_loop_ull_*start functions have additional boolean
5783 argument, true for < loops and false for > loops.
5784 In Fortran, the C bool type can be different from
5785 boolean_type_node. */
5786 bfn_decl = builtin_decl_explicit (start_fn);
5787 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5788 t5 = build_int_cst (c_bool_type,
5789 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5790 if (fd->chunk_size)
5792 tree bfn_decl = builtin_decl_explicit (start_fn);
5793 t = fold_convert (fd->iter_type, fd->chunk_size);
5794 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5796 else
5797 t = build_call_expr (builtin_decl_explicit (start_fn),
5798 6, t5, t0, t1, t2, t3, t4);
5801 if (TREE_TYPE (t) != boolean_type_node)
5802 t = fold_build2 (NE_EXPR, boolean_type_node,
5803 t, build_int_cst (TREE_TYPE (t), 0));
5804 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5805 true, GSI_SAME_STMT);
5806 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5808 /* Remove the GIMPLE_OMP_FOR statement. */
5809 gsi_remove (&gsi, true);
5811 /* Iteration setup for sequential loop goes in L0_BB. */
5812 tree startvar = fd->loop.v;
5813 tree endvar = NULL_TREE;
5815 if (gimple_omp_for_combined_p (fd->for_stmt))
5817 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5818 && gimple_omp_for_kind (inner_stmt)
5819 == GF_OMP_FOR_KIND_SIMD);
5820 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5821 OMP_CLAUSE__LOOPTEMP_);
5822 gcc_assert (innerc);
5823 startvar = OMP_CLAUSE_DECL (innerc);
5824 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5825 OMP_CLAUSE__LOOPTEMP_);
5826 gcc_assert (innerc);
5827 endvar = OMP_CLAUSE_DECL (innerc);
5830 gsi = gsi_start_bb (l0_bb);
5831 t = istart0;
5832 if (bias)
5833 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5834 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5835 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5836 t = fold_convert (TREE_TYPE (startvar), t);
5837 t = force_gimple_operand_gsi (&gsi, t,
5838 DECL_P (startvar)
5839 && TREE_ADDRESSABLE (startvar),
5840 NULL_TREE, false, GSI_CONTINUE_LINKING);
5841 assign_stmt = gimple_build_assign (startvar, t);
5842 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5844 t = iend0;
5845 if (bias)
5846 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5847 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5848 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5849 t = fold_convert (TREE_TYPE (startvar), t);
5850 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5851 false, GSI_CONTINUE_LINKING);
5852 if (endvar)
5854 assign_stmt = gimple_build_assign (endvar, iend);
5855 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5856 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
5857 assign_stmt = gimple_build_assign (fd->loop.v, iend);
5858 else
5859 assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend);
5860 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5862 if (fd->collapse > 1)
5863 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5865 if (!broken_loop)
5867 /* Code to control the increment and predicate for the sequential
5868 loop goes in the CONT_BB. */
5869 gsi = gsi_last_bb (cont_bb);
5870 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
5871 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
5872 vmain = gimple_omp_continue_control_use (cont_stmt);
5873 vback = gimple_omp_continue_control_def (cont_stmt);
5875 if (!gimple_omp_for_combined_p (fd->for_stmt))
5877 if (POINTER_TYPE_P (type))
5878 t = fold_build_pointer_plus (vmain, fd->loop.step);
5879 else
5880 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5881 t = force_gimple_operand_gsi (&gsi, t,
5882 DECL_P (vback)
5883 && TREE_ADDRESSABLE (vback),
5884 NULL_TREE, true, GSI_SAME_STMT);
5885 assign_stmt = gimple_build_assign (vback, t);
5886 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
5888 t = build2 (fd->loop.cond_code, boolean_type_node,
5889 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5890 iend);
5891 gcond *cond_stmt = gimple_build_cond_empty (t);
5892 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
5895 /* Remove GIMPLE_OMP_CONTINUE. */
5896 gsi_remove (&gsi, true);
5898 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5899 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5901 /* Emit code to get the next parallel iteration in L2_BB. */
5902 gsi = gsi_start_bb (l2_bb);
5904 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5905 build_fold_addr_expr (istart0),
5906 build_fold_addr_expr (iend0));
5907 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5908 false, GSI_CONTINUE_LINKING);
5909 if (TREE_TYPE (t) != boolean_type_node)
5910 t = fold_build2 (NE_EXPR, boolean_type_node,
5911 t, build_int_cst (TREE_TYPE (t), 0));
5912 gcond *cond_stmt = gimple_build_cond_empty (t);
5913 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
5916 /* Add the loop cleanup function. */
5917 gsi = gsi_last_bb (exit_bb);
5918 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5919 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5920 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5921 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5922 else
5923 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5924 gcall *call_stmt = gimple_build_call (t, 0);
5925 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5926 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5927 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
5928 gsi_remove (&gsi, true);
5930 /* Connect the new blocks. */
5931 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5932 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5934 if (!broken_loop)
5936 gimple_seq phis;
5938 e = find_edge (cont_bb, l3_bb);
5939 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5941 phis = phi_nodes (l3_bb);
5942 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5944 gimple phi = gsi_stmt (gsi);
5945 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5946 PHI_ARG_DEF_FROM_EDGE (phi, e));
5948 remove_edge (e);
5950 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5951 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5952 e = find_edge (cont_bb, l1_bb);
5953 if (gimple_omp_for_combined_p (fd->for_stmt))
5955 remove_edge (e);
5956 e = NULL;
5958 else if (fd->collapse > 1)
5960 remove_edge (e);
5961 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5963 else
5964 e->flags = EDGE_TRUE_VALUE;
5965 if (e)
5967 e->probability = REG_BR_PROB_BASE * 7 / 8;
5968 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5970 else
5972 e = find_edge (cont_bb, l2_bb);
5973 e->flags = EDGE_FALLTHRU;
5975 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5977 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5978 recompute_dominator (CDI_DOMINATORS, l2_bb));
5979 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5980 recompute_dominator (CDI_DOMINATORS, l3_bb));
5981 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5982 recompute_dominator (CDI_DOMINATORS, l0_bb));
5983 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5984 recompute_dominator (CDI_DOMINATORS, l1_bb));
5986 struct loop *outer_loop = alloc_loop ();
5987 outer_loop->header = l0_bb;
5988 outer_loop->latch = l2_bb;
5989 add_loop (outer_loop, l0_bb->loop_father);
5991 if (!gimple_omp_for_combined_p (fd->for_stmt))
5993 struct loop *loop = alloc_loop ();
5994 loop->header = l1_bb;
5995 /* The loop may have multiple latches. */
5996 add_loop (loop, outer_loop);
6002 /* A subroutine of expand_omp_for. Generate code for a parallel
6003 loop with static schedule and no specified chunk size. Given
6004 parameters:
6006 for (V = N1; V cond N2; V += STEP) BODY;
6008 where COND is "<" or ">", we generate pseudocode
6010 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6011 if (cond is <)
6012 adj = STEP - 1;
6013 else
6014 adj = STEP + 1;
6015 if ((__typeof (V)) -1 > 0 && cond is >)
6016 n = -(adj + N2 - N1) / -STEP;
6017 else
6018 n = (adj + N2 - N1) / STEP;
6019 q = n / nthreads;
6020 tt = n % nthreads;
6021 if (threadid < tt) goto L3; else goto L4;
6023 tt = 0;
6024 q = q + 1;
6026 s0 = q * threadid + tt;
6027 e0 = s0 + q;
6028 V = s0 * STEP + N1;
6029 if (s0 >= e0) goto L2; else goto L0;
6031 e = e0 * STEP + N1;
6033 BODY;
6034 V += STEP;
6035 if (V cond e) goto L1;
6039 static void
6040 expand_omp_for_static_nochunk (struct omp_region *region,
6041 struct omp_for_data *fd,
6042 gimple inner_stmt)
6044 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6045 tree type, itype, vmain, vback;
6046 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6047 basic_block body_bb, cont_bb, collapse_bb = NULL;
6048 basic_block fin_bb;
6049 gimple_stmt_iterator gsi;
6050 edge ep;
6051 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6052 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6053 bool broken_loop = region->cont == NULL;
6054 tree *counts = NULL;
6055 tree n1, n2, step;
6057 itype = type = TREE_TYPE (fd->loop.v);
6058 if (POINTER_TYPE_P (type))
6059 itype = signed_type_for (type);
6061 entry_bb = region->entry;
6062 cont_bb = region->cont;
6063 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6064 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6065 gcc_assert (broken_loop
6066 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6067 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6068 body_bb = single_succ (seq_start_bb);
6069 if (!broken_loop)
6071 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6072 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6074 exit_bb = region->exit;
6076 /* Iteration space partitioning goes in ENTRY_BB. */
6077 gsi = gsi_last_bb (entry_bb);
6078 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6080 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6082 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6083 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6086 if (fd->collapse > 1)
6088 int first_zero_iter = -1;
6089 basic_block l2_dom_bb = NULL;
6091 counts = XALLOCAVEC (tree, fd->collapse);
6092 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6093 fin_bb, first_zero_iter,
6094 l2_dom_bb);
6095 t = NULL_TREE;
6097 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6098 t = integer_one_node;
6099 else
6100 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6101 fold_convert (type, fd->loop.n1),
6102 fold_convert (type, fd->loop.n2));
6103 if (fd->collapse == 1
6104 && TYPE_UNSIGNED (type)
6105 && (t == NULL_TREE || !integer_onep (t)))
6107 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6108 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6109 true, GSI_SAME_STMT);
6110 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6111 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6112 true, GSI_SAME_STMT);
6113 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6114 NULL_TREE, NULL_TREE);
6115 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6116 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6117 expand_omp_regimplify_p, NULL, NULL)
6118 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6119 expand_omp_regimplify_p, NULL, NULL))
6121 gsi = gsi_for_stmt (cond_stmt);
6122 gimple_regimplify_operands (cond_stmt, &gsi);
6124 ep = split_block (entry_bb, cond_stmt);
6125 ep->flags = EDGE_TRUE_VALUE;
6126 entry_bb = ep->dest;
6127 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6128 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6129 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6130 if (gimple_in_ssa_p (cfun))
6132 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6133 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6134 !gsi_end_p (gpi); gsi_next (&gpi))
6136 gphi *phi = gpi.phi ();
6137 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6138 ep, UNKNOWN_LOCATION);
6141 gsi = gsi_last_bb (entry_bb);
6144 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6145 t = fold_convert (itype, t);
6146 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6147 true, GSI_SAME_STMT);
6149 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6150 t = fold_convert (itype, t);
6151 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6152 true, GSI_SAME_STMT);
6154 n1 = fd->loop.n1;
6155 n2 = fd->loop.n2;
6156 step = fd->loop.step;
6157 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6159 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6160 OMP_CLAUSE__LOOPTEMP_);
6161 gcc_assert (innerc);
6162 n1 = OMP_CLAUSE_DECL (innerc);
6163 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6164 OMP_CLAUSE__LOOPTEMP_);
6165 gcc_assert (innerc);
6166 n2 = OMP_CLAUSE_DECL (innerc);
6168 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6169 true, NULL_TREE, true, GSI_SAME_STMT);
6170 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6171 true, NULL_TREE, true, GSI_SAME_STMT);
6172 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6173 true, NULL_TREE, true, GSI_SAME_STMT);
6175 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6176 t = fold_build2 (PLUS_EXPR, itype, step, t);
6177 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6178 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6179 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6180 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6181 fold_build1 (NEGATE_EXPR, itype, t),
6182 fold_build1 (NEGATE_EXPR, itype, step));
6183 else
6184 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6185 t = fold_convert (itype, t);
6186 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6188 q = create_tmp_reg (itype, "q");
6189 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6190 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6191 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6193 tt = create_tmp_reg (itype, "tt");
6194 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6195 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6196 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6198 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6199 gcond *cond_stmt = gimple_build_cond_empty (t);
6200 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6202 second_bb = split_block (entry_bb, cond_stmt)->dest;
6203 gsi = gsi_last_bb (second_bb);
6204 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6206 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6207 GSI_SAME_STMT);
6208 gassign *assign_stmt
6209 = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
6210 build_int_cst (itype, 1));
6211 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6213 third_bb = split_block (second_bb, assign_stmt)->dest;
6214 gsi = gsi_last_bb (third_bb);
6215 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6217 t = build2 (MULT_EXPR, itype, q, threadid);
6218 t = build2 (PLUS_EXPR, itype, t, tt);
6219 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6221 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6222 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6224 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6225 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6227 /* Remove the GIMPLE_OMP_FOR statement. */
6228 gsi_remove (&gsi, true);
6230 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6231 gsi = gsi_start_bb (seq_start_bb);
6233 tree startvar = fd->loop.v;
6234 tree endvar = NULL_TREE;
6236 if (gimple_omp_for_combined_p (fd->for_stmt))
6238 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6239 ? gimple_omp_parallel_clauses (inner_stmt)
6240 : gimple_omp_for_clauses (inner_stmt);
6241 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6242 gcc_assert (innerc);
6243 startvar = OMP_CLAUSE_DECL (innerc);
6244 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6245 OMP_CLAUSE__LOOPTEMP_);
6246 gcc_assert (innerc);
6247 endvar = OMP_CLAUSE_DECL (innerc);
6249 t = fold_convert (itype, s0);
6250 t = fold_build2 (MULT_EXPR, itype, t, step);
6251 if (POINTER_TYPE_P (type))
6252 t = fold_build_pointer_plus (n1, t);
6253 else
6254 t = fold_build2 (PLUS_EXPR, type, t, n1);
6255 t = fold_convert (TREE_TYPE (startvar), t);
6256 t = force_gimple_operand_gsi (&gsi, t,
6257 DECL_P (startvar)
6258 && TREE_ADDRESSABLE (startvar),
6259 NULL_TREE, false, GSI_CONTINUE_LINKING);
6260 assign_stmt = gimple_build_assign (startvar, t);
6261 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6263 t = fold_convert (itype, e0);
6264 t = fold_build2 (MULT_EXPR, itype, t, step);
6265 if (POINTER_TYPE_P (type))
6266 t = fold_build_pointer_plus (n1, t);
6267 else
6268 t = fold_build2 (PLUS_EXPR, type, t, n1);
6269 t = fold_convert (TREE_TYPE (startvar), t);
6270 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6271 false, GSI_CONTINUE_LINKING);
6272 if (endvar)
6274 assign_stmt = gimple_build_assign (endvar, e);
6275 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6276 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6277 assign_stmt = gimple_build_assign (fd->loop.v, e);
6278 else
6279 assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e);
6280 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6282 if (fd->collapse > 1)
6283 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6285 if (!broken_loop)
6287 /* The code controlling the sequential loop replaces the
6288 GIMPLE_OMP_CONTINUE. */
6289 gsi = gsi_last_bb (cont_bb);
6290 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6291 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6292 vmain = gimple_omp_continue_control_use (cont_stmt);
6293 vback = gimple_omp_continue_control_def (cont_stmt);
6295 if (!gimple_omp_for_combined_p (fd->for_stmt))
6297 if (POINTER_TYPE_P (type))
6298 t = fold_build_pointer_plus (vmain, step);
6299 else
6300 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6301 t = force_gimple_operand_gsi (&gsi, t,
6302 DECL_P (vback)
6303 && TREE_ADDRESSABLE (vback),
6304 NULL_TREE, true, GSI_SAME_STMT);
6305 assign_stmt = gimple_build_assign (vback, t);
6306 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6308 t = build2 (fd->loop.cond_code, boolean_type_node,
6309 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6310 ? t : vback, e);
6311 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6314 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6315 gsi_remove (&gsi, true);
6317 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6318 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6321 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6322 gsi = gsi_last_bb (exit_bb);
6323 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6325 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6326 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6328 gsi_remove (&gsi, true);
6330 /* Connect all the blocks. */
6331 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6332 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6333 ep = find_edge (entry_bb, second_bb);
6334 ep->flags = EDGE_TRUE_VALUE;
6335 ep->probability = REG_BR_PROB_BASE / 4;
6336 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6337 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6339 if (!broken_loop)
6341 ep = find_edge (cont_bb, body_bb);
6342 if (gimple_omp_for_combined_p (fd->for_stmt))
6344 remove_edge (ep);
6345 ep = NULL;
6347 else if (fd->collapse > 1)
6349 remove_edge (ep);
6350 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6352 else
6353 ep->flags = EDGE_TRUE_VALUE;
6354 find_edge (cont_bb, fin_bb)->flags
6355 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6358 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6359 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6360 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6362 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6363 recompute_dominator (CDI_DOMINATORS, body_bb));
6364 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6365 recompute_dominator (CDI_DOMINATORS, fin_bb));
6367 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6369 struct loop *loop = alloc_loop ();
6370 loop->header = body_bb;
6371 if (collapse_bb == NULL)
6372 loop->latch = cont_bb;
6373 add_loop (loop, body_bb->loop_father);
6378 /* A subroutine of expand_omp_for. Generate code for a parallel
6379 loop with static schedule and a specified chunk size. Given
6380 parameters:
6382 for (V = N1; V cond N2; V += STEP) BODY;
6384 where COND is "<" or ">", we generate pseudocode
6386 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6387 if (cond is <)
6388 adj = STEP - 1;
6389 else
6390 adj = STEP + 1;
6391 if ((__typeof (V)) -1 > 0 && cond is >)
6392 n = -(adj + N2 - N1) / -STEP;
6393 else
6394 n = (adj + N2 - N1) / STEP;
6395 trip = 0;
6396 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6397 here so that V is defined
6398 if the loop is not entered
6400 s0 = (trip * nthreads + threadid) * CHUNK;
6401 e0 = min(s0 + CHUNK, n);
6402 if (s0 < n) goto L1; else goto L4;
6404 V = s0 * STEP + N1;
6405 e = e0 * STEP + N1;
6407 BODY;
6408 V += STEP;
6409 if (V cond e) goto L2; else goto L3;
6411 trip += 1;
6412 goto L0;
6416 static void
6417 expand_omp_for_static_chunk (struct omp_region *region,
6418 struct omp_for_data *fd, gimple inner_stmt)
6420 tree n, s0, e0, e, t;
6421 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6422 tree type, itype, vmain, vback, vextra;
6423 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6424 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6425 gimple_stmt_iterator gsi;
6426 edge se;
6427 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6428 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6429 bool broken_loop = region->cont == NULL;
6430 tree *counts = NULL;
6431 tree n1, n2, step;
6433 itype = type = TREE_TYPE (fd->loop.v);
6434 if (POINTER_TYPE_P (type))
6435 itype = signed_type_for (type);
6437 entry_bb = region->entry;
6438 se = split_block (entry_bb, last_stmt (entry_bb));
6439 entry_bb = se->src;
6440 iter_part_bb = se->dest;
6441 cont_bb = region->cont;
6442 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6443 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6444 gcc_assert (broken_loop
6445 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6446 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6447 body_bb = single_succ (seq_start_bb);
6448 if (!broken_loop)
6450 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6451 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6452 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6454 exit_bb = region->exit;
6456 /* Trip and adjustment setup goes in ENTRY_BB. */
6457 gsi = gsi_last_bb (entry_bb);
6458 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6460 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6462 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6463 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6466 if (fd->collapse > 1)
6468 int first_zero_iter = -1;
6469 basic_block l2_dom_bb = NULL;
6471 counts = XALLOCAVEC (tree, fd->collapse);
6472 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6473 fin_bb, first_zero_iter,
6474 l2_dom_bb);
6475 t = NULL_TREE;
6477 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6478 t = integer_one_node;
6479 else
6480 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6481 fold_convert (type, fd->loop.n1),
6482 fold_convert (type, fd->loop.n2));
6483 if (fd->collapse == 1
6484 && TYPE_UNSIGNED (type)
6485 && (t == NULL_TREE || !integer_onep (t)))
6487 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6488 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6489 true, GSI_SAME_STMT);
6490 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6491 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6492 true, GSI_SAME_STMT);
6493 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6494 NULL_TREE, NULL_TREE);
6495 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6496 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6497 expand_omp_regimplify_p, NULL, NULL)
6498 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6499 expand_omp_regimplify_p, NULL, NULL))
6501 gsi = gsi_for_stmt (cond_stmt);
6502 gimple_regimplify_operands (cond_stmt, &gsi);
6504 se = split_block (entry_bb, cond_stmt);
6505 se->flags = EDGE_TRUE_VALUE;
6506 entry_bb = se->dest;
6507 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6508 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6509 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6510 if (gimple_in_ssa_p (cfun))
6512 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6513 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6514 !gsi_end_p (gpi); gsi_next (&gpi))
6516 gphi *phi = gpi.phi ();
6517 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6518 se, UNKNOWN_LOCATION);
6521 gsi = gsi_last_bb (entry_bb);
6524 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6525 t = fold_convert (itype, t);
6526 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6527 true, GSI_SAME_STMT);
6529 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6530 t = fold_convert (itype, t);
6531 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6532 true, GSI_SAME_STMT);
6534 n1 = fd->loop.n1;
6535 n2 = fd->loop.n2;
6536 step = fd->loop.step;
6537 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6539 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6540 OMP_CLAUSE__LOOPTEMP_);
6541 gcc_assert (innerc);
6542 n1 = OMP_CLAUSE_DECL (innerc);
6543 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6544 OMP_CLAUSE__LOOPTEMP_);
6545 gcc_assert (innerc);
6546 n2 = OMP_CLAUSE_DECL (innerc);
6548 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6549 true, NULL_TREE, true, GSI_SAME_STMT);
6550 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6551 true, NULL_TREE, true, GSI_SAME_STMT);
6552 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6553 true, NULL_TREE, true, GSI_SAME_STMT);
6554 fd->chunk_size
6555 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
6556 true, NULL_TREE, true, GSI_SAME_STMT);
6558 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6559 t = fold_build2 (PLUS_EXPR, itype, step, t);
6560 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6561 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6562 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6563 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6564 fold_build1 (NEGATE_EXPR, itype, t),
6565 fold_build1 (NEGATE_EXPR, itype, step));
6566 else
6567 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6568 t = fold_convert (itype, t);
6569 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6570 true, GSI_SAME_STMT);
6572 trip_var = create_tmp_reg (itype, ".trip");
6573 if (gimple_in_ssa_p (cfun))
6575 trip_init = make_ssa_name (trip_var, NULL);
6576 trip_main = make_ssa_name (trip_var, NULL);
6577 trip_back = make_ssa_name (trip_var, NULL);
6579 else
6581 trip_init = trip_var;
6582 trip_main = trip_var;
6583 trip_back = trip_var;
6586 gassign *assign_stmt
6587 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6588 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6590 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6591 t = fold_build2 (MULT_EXPR, itype, t, step);
6592 if (POINTER_TYPE_P (type))
6593 t = fold_build_pointer_plus (n1, t);
6594 else
6595 t = fold_build2 (PLUS_EXPR, type, t, n1);
6596 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6597 true, GSI_SAME_STMT);
6599 /* Remove the GIMPLE_OMP_FOR. */
6600 gsi_remove (&gsi, true);
6602 /* Iteration space partitioning goes in ITER_PART_BB. */
6603 gsi = gsi_last_bb (iter_part_bb);
6605 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6606 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6607 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6608 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6609 false, GSI_CONTINUE_LINKING);
6611 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6612 t = fold_build2 (MIN_EXPR, itype, t, n);
6613 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6614 false, GSI_CONTINUE_LINKING);
6616 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6617 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6619 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6620 gsi = gsi_start_bb (seq_start_bb);
6622 tree startvar = fd->loop.v;
6623 tree endvar = NULL_TREE;
6625 if (gimple_omp_for_combined_p (fd->for_stmt))
6627 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6628 ? gimple_omp_parallel_clauses (inner_stmt)
6629 : gimple_omp_for_clauses (inner_stmt);
6630 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6631 gcc_assert (innerc);
6632 startvar = OMP_CLAUSE_DECL (innerc);
6633 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6634 OMP_CLAUSE__LOOPTEMP_);
6635 gcc_assert (innerc);
6636 endvar = OMP_CLAUSE_DECL (innerc);
6639 t = fold_convert (itype, s0);
6640 t = fold_build2 (MULT_EXPR, itype, t, step);
6641 if (POINTER_TYPE_P (type))
6642 t = fold_build_pointer_plus (n1, t);
6643 else
6644 t = fold_build2 (PLUS_EXPR, type, t, n1);
6645 t = fold_convert (TREE_TYPE (startvar), t);
6646 t = force_gimple_operand_gsi (&gsi, t,
6647 DECL_P (startvar)
6648 && TREE_ADDRESSABLE (startvar),
6649 NULL_TREE, false, GSI_CONTINUE_LINKING);
6650 assign_stmt = gimple_build_assign (startvar, t);
6651 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6653 t = fold_convert (itype, e0);
6654 t = fold_build2 (MULT_EXPR, itype, t, step);
6655 if (POINTER_TYPE_P (type))
6656 t = fold_build_pointer_plus (n1, t);
6657 else
6658 t = fold_build2 (PLUS_EXPR, type, t, n1);
6659 t = fold_convert (TREE_TYPE (startvar), t);
6660 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6661 false, GSI_CONTINUE_LINKING);
6662 if (endvar)
6664 assign_stmt = gimple_build_assign (endvar, e);
6665 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6666 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6667 assign_stmt = gimple_build_assign (fd->loop.v, e);
6668 else
6669 assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e);
6670 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6672 if (fd->collapse > 1)
6673 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6675 if (!broken_loop)
6677 /* The code controlling the sequential loop goes in CONT_BB,
6678 replacing the GIMPLE_OMP_CONTINUE. */
6679 gsi = gsi_last_bb (cont_bb);
6680 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6681 vmain = gimple_omp_continue_control_use (cont_stmt);
6682 vback = gimple_omp_continue_control_def (cont_stmt);
6684 if (!gimple_omp_for_combined_p (fd->for_stmt))
6686 if (POINTER_TYPE_P (type))
6687 t = fold_build_pointer_plus (vmain, step);
6688 else
6689 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6690 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
6691 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6692 true, GSI_SAME_STMT);
6693 assign_stmt = gimple_build_assign (vback, t);
6694 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6696 t = build2 (fd->loop.cond_code, boolean_type_node,
6697 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6698 ? t : vback, e);
6699 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6702 /* Remove GIMPLE_OMP_CONTINUE. */
6703 gsi_remove (&gsi, true);
6705 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6706 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6708 /* Trip update code goes into TRIP_UPDATE_BB. */
6709 gsi = gsi_start_bb (trip_update_bb);
6711 t = build_int_cst (itype, 1);
6712 t = build2 (PLUS_EXPR, itype, trip_main, t);
6713 assign_stmt = gimple_build_assign (trip_back, t);
6714 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6717 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6718 gsi = gsi_last_bb (exit_bb);
6719 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6721 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6722 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6724 gsi_remove (&gsi, true);
6726 /* Connect the new blocks. */
6727 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6728 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6730 if (!broken_loop)
6732 se = find_edge (cont_bb, body_bb);
6733 if (gimple_omp_for_combined_p (fd->for_stmt))
6735 remove_edge (se);
6736 se = NULL;
6738 else if (fd->collapse > 1)
6740 remove_edge (se);
6741 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6743 else
6744 se->flags = EDGE_TRUE_VALUE;
6745 find_edge (cont_bb, trip_update_bb)->flags
6746 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6748 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6751 if (gimple_in_ssa_p (cfun))
6753 gphi_iterator psi;
6754 gphi *phi;
6755 edge re, ene;
6756 edge_var_map *vm;
6757 size_t i;
6759 gcc_assert (fd->collapse == 1 && !broken_loop);
6761 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6762 remove arguments of the phi nodes in fin_bb. We need to create
6763 appropriate phi nodes in iter_part_bb instead. */
6764 se = single_pred_edge (fin_bb);
6765 re = single_succ_edge (trip_update_bb);
6766 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
6767 ene = single_succ_edge (entry_bb);
6769 psi = gsi_start_phis (fin_bb);
6770 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6771 gsi_next (&psi), ++i)
6773 gphi *nphi;
6774 source_location locus;
6776 phi = psi.phi ();
6777 t = gimple_phi_result (phi);
6778 gcc_assert (t == redirect_edge_var_map_result (vm));
6779 nphi = create_phi_node (t, iter_part_bb);
6781 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6782 locus = gimple_phi_arg_location_from_edge (phi, se);
6784 /* A special case -- fd->loop.v is not yet computed in
6785 iter_part_bb, we need to use vextra instead. */
6786 if (t == fd->loop.v)
6787 t = vextra;
6788 add_phi_arg (nphi, t, ene, locus);
6789 locus = redirect_edge_var_map_location (vm);
6790 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6792 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6793 redirect_edge_var_map_clear (re);
6794 while (1)
6796 psi = gsi_start_phis (fin_bb);
6797 if (gsi_end_p (psi))
6798 break;
6799 remove_phi_node (&psi, false);
6802 /* Make phi node for trip. */
6803 phi = create_phi_node (trip_main, iter_part_bb);
6804 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6805 UNKNOWN_LOCATION);
6806 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6807 UNKNOWN_LOCATION);
6810 if (!broken_loop)
6811 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6812 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6813 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6814 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6815 recompute_dominator (CDI_DOMINATORS, fin_bb));
6816 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6817 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6818 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6819 recompute_dominator (CDI_DOMINATORS, body_bb));
6821 if (!broken_loop)
6823 struct loop *trip_loop = alloc_loop ();
6824 trip_loop->header = iter_part_bb;
6825 trip_loop->latch = trip_update_bb;
6826 add_loop (trip_loop, iter_part_bb->loop_father);
6828 if (!gimple_omp_for_combined_p (fd->for_stmt))
6830 struct loop *loop = alloc_loop ();
6831 loop->header = body_bb;
6832 if (collapse_bb == NULL)
6833 loop->latch = cont_bb;
6834 add_loop (loop, trip_loop);
6839 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
6840 Given parameters:
6841 for (V = N1; V cond N2; V += STEP) BODY;
6843 where COND is "<" or ">" or "!=", we generate pseudocode
6845 for (ind_var = low; ind_var < high; ind_var++)
6847 V = n1 + (ind_var * STEP)
6849 <BODY>
6852 In the above pseudocode, low and high are function parameters of the
6853 child function. In the function below, we are inserting a temp.
6854 variable that will be making a call to two OMP functions that will not be
6855 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
6856 with _Cilk_for). These functions are replaced with low and high
6857 by the function that handles taskreg. */
6860 static void
6861 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
6863 bool broken_loop = region->cont == NULL;
6864 basic_block entry_bb = region->entry;
6865 basic_block cont_bb = region->cont;
6867 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6868 gcc_assert (broken_loop
6869 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6870 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6871 basic_block l1_bb, l2_bb;
6873 if (!broken_loop)
6875 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6876 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6877 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6878 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6880 else
6882 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6883 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6884 l2_bb = single_succ (l1_bb);
6886 basic_block exit_bb = region->exit;
6887 basic_block l2_dom_bb = NULL;
6889 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
6891 /* Below statements until the "tree high_val = ..." are pseudo statements
6892 used to pass information to be used by expand_omp_taskreg.
6893 low_val and high_val will be replaced by the __low and __high
6894 parameter from the child function.
6896 The call_exprs part is a place-holder, it is mainly used
6897 to distinctly identify to the top-level part that this is
6898 where we should put low and high (reasoning given in header
6899 comment). */
6901 tree child_fndecl
6902 = gimple_omp_parallel_child_fn (
6903 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
6904 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
6905 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
6907 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
6908 high_val = t;
6909 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
6910 low_val = t;
6912 gcc_assert (low_val && high_val);
6914 tree type = TREE_TYPE (low_val);
6915 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
6916 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6918 /* Not needed in SSA form right now. */
6919 gcc_assert (!gimple_in_ssa_p (cfun));
6920 if (l2_dom_bb == NULL)
6921 l2_dom_bb = l1_bb;
6923 tree n1 = low_val;
6924 tree n2 = high_val;
6926 gimple stmt = gimple_build_assign (ind_var, n1);
6928 /* Replace the GIMPLE_OMP_FOR statement. */
6929 gsi_replace (&gsi, stmt, true);
6931 if (!broken_loop)
6933 /* Code to control the increment goes in the CONT_BB. */
6934 gsi = gsi_last_bb (cont_bb);
6935 stmt = gsi_stmt (gsi);
6936 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6937 stmt = gimple_build_assign_with_ops (PLUS_EXPR, ind_var, ind_var,
6938 build_one_cst (type));
6940 /* Replace GIMPLE_OMP_CONTINUE. */
6941 gsi_replace (&gsi, stmt, true);
6944 /* Emit the condition in L1_BB. */
6945 gsi = gsi_after_labels (l1_bb);
6946 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
6947 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
6948 fd->loop.step);
6949 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
6950 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6951 fd->loop.n1, fold_convert (sizetype, t));
6952 else
6953 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6954 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
6955 t = fold_convert (TREE_TYPE (fd->loop.v), t);
6956 expand_omp_build_assign (&gsi, fd->loop.v, t);
6958 /* The condition is always '<' since the runtime will fill in the low
6959 and high values. */
6960 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
6961 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6963 /* Remove GIMPLE_OMP_RETURN. */
6964 gsi = gsi_last_bb (exit_bb);
6965 gsi_remove (&gsi, true);
6967 /* Connect the new blocks. */
6968 remove_edge (FALLTHRU_EDGE (entry_bb));
6970 edge e, ne;
6971 if (!broken_loop)
6973 remove_edge (BRANCH_EDGE (entry_bb));
6974 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6976 e = BRANCH_EDGE (l1_bb);
6977 ne = FALLTHRU_EDGE (l1_bb);
6978 e->flags = EDGE_TRUE_VALUE;
6980 else
6982 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6984 ne = single_succ_edge (l1_bb);
6985 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6988 ne->flags = EDGE_FALSE_VALUE;
6989 e->probability = REG_BR_PROB_BASE * 7 / 8;
6990 ne->probability = REG_BR_PROB_BASE / 8;
6992 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6993 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6994 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6996 if (!broken_loop)
6998 struct loop *loop = alloc_loop ();
6999 loop->header = l1_bb;
7000 loop->latch = cont_bb;
7001 add_loop (loop, l1_bb->loop_father);
7002 loop->safelen = INT_MAX;
7005 /* Pick the correct library function based on the precision of the
7006 induction variable type. */
7007 tree lib_fun = NULL_TREE;
7008 if (TYPE_PRECISION (type) == 32)
7009 lib_fun = cilk_for_32_fndecl;
7010 else if (TYPE_PRECISION (type) == 64)
7011 lib_fun = cilk_for_64_fndecl;
7012 else
7013 gcc_unreachable ();
7015 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7017 /* WS_ARGS contains the library function flavor to call:
7018 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7019 user-defined grain value. If the user does not define one, then zero
7020 is passed in by the parser. */
7021 vec_alloc (region->ws_args, 2);
7022 region->ws_args->quick_push (lib_fun);
7023 region->ws_args->quick_push (fd->chunk_size);
7026 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7027 loop. Given parameters:
7029 for (V = N1; V cond N2; V += STEP) BODY;
7031 where COND is "<" or ">", we generate pseudocode
7033 V = N1;
7034 goto L1;
7036 BODY;
7037 V += STEP;
7039 if (V cond N2) goto L0; else goto L2;
7042 For collapsed loops, given parameters:
7043 collapse(3)
7044 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7045 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7046 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7047 BODY;
7049 we generate pseudocode
7051 if (cond3 is <)
7052 adj = STEP3 - 1;
7053 else
7054 adj = STEP3 + 1;
7055 count3 = (adj + N32 - N31) / STEP3;
7056 if (cond2 is <)
7057 adj = STEP2 - 1;
7058 else
7059 adj = STEP2 + 1;
7060 count2 = (adj + N22 - N21) / STEP2;
7061 if (cond1 is <)
7062 adj = STEP1 - 1;
7063 else
7064 adj = STEP1 + 1;
7065 count1 = (adj + N12 - N11) / STEP1;
7066 count = count1 * count2 * count3;
7067 V = 0;
7068 V1 = N11;
7069 V2 = N21;
7070 V3 = N31;
7071 goto L1;
7073 BODY;
7074 V += 1;
7075 V3 += STEP3;
7076 V2 += (V3 cond3 N32) ? 0 : STEP2;
7077 V3 = (V3 cond3 N32) ? V3 : N31;
7078 V1 += (V2 cond2 N22) ? 0 : STEP1;
7079 V2 = (V2 cond2 N22) ? V2 : N21;
7081 if (V < count) goto L0; else goto L2;
7086 static void
7087 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7089 tree type, t;
7090 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7091 gimple_stmt_iterator gsi;
7092 gimple stmt;
7093 gcond *cond_stmt;
7094 bool broken_loop = region->cont == NULL;
7095 edge e, ne;
7096 tree *counts = NULL;
7097 int i;
7098 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7099 OMP_CLAUSE_SAFELEN);
7100 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7101 OMP_CLAUSE__SIMDUID_);
7102 tree n1, n2;
7104 type = TREE_TYPE (fd->loop.v);
7105 entry_bb = region->entry;
7106 cont_bb = region->cont;
7107 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7108 gcc_assert (broken_loop
7109 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7110 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7111 if (!broken_loop)
7113 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7114 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7115 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7116 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7118 else
7120 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7121 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7122 l2_bb = single_succ (l1_bb);
7124 exit_bb = region->exit;
7125 l2_dom_bb = NULL;
7127 gsi = gsi_last_bb (entry_bb);
7129 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7130 /* Not needed in SSA form right now. */
7131 gcc_assert (!gimple_in_ssa_p (cfun));
7132 if (fd->collapse > 1)
7134 int first_zero_iter = -1;
7135 basic_block zero_iter_bb = l2_bb;
7137 counts = XALLOCAVEC (tree, fd->collapse);
7138 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7139 zero_iter_bb, first_zero_iter,
7140 l2_dom_bb);
7142 if (l2_dom_bb == NULL)
7143 l2_dom_bb = l1_bb;
7145 n1 = fd->loop.n1;
7146 n2 = fd->loop.n2;
7147 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7149 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7150 OMP_CLAUSE__LOOPTEMP_);
7151 gcc_assert (innerc);
7152 n1 = OMP_CLAUSE_DECL (innerc);
7153 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7154 OMP_CLAUSE__LOOPTEMP_);
7155 gcc_assert (innerc);
7156 n2 = OMP_CLAUSE_DECL (innerc);
7157 expand_omp_build_assign (&gsi, fd->loop.v,
7158 fold_convert (type, n1));
7159 if (fd->collapse > 1)
7161 gsi_prev (&gsi);
7162 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7163 gsi_next (&gsi);
7166 else
7168 expand_omp_build_assign (&gsi, fd->loop.v,
7169 fold_convert (type, fd->loop.n1));
7170 if (fd->collapse > 1)
7171 for (i = 0; i < fd->collapse; i++)
7173 tree itype = TREE_TYPE (fd->loops[i].v);
7174 if (POINTER_TYPE_P (itype))
7175 itype = signed_type_for (itype);
7176 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7177 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7181 /* Remove the GIMPLE_OMP_FOR statement. */
7182 gsi_remove (&gsi, true);
7184 if (!broken_loop)
7186 /* Code to control the increment goes in the CONT_BB. */
7187 gsi = gsi_last_bb (cont_bb);
7188 stmt = gsi_stmt (gsi);
7189 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7191 if (POINTER_TYPE_P (type))
7192 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7193 else
7194 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7195 expand_omp_build_assign (&gsi, fd->loop.v, t);
7197 if (fd->collapse > 1)
7199 i = fd->collapse - 1;
7200 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7202 t = fold_convert (sizetype, fd->loops[i].step);
7203 t = fold_build_pointer_plus (fd->loops[i].v, t);
7205 else
7207 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7208 fd->loops[i].step);
7209 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7210 fd->loops[i].v, t);
7212 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7214 for (i = fd->collapse - 1; i > 0; i--)
7216 tree itype = TREE_TYPE (fd->loops[i].v);
7217 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7218 if (POINTER_TYPE_P (itype2))
7219 itype2 = signed_type_for (itype2);
7220 t = build3 (COND_EXPR, itype2,
7221 build2 (fd->loops[i].cond_code, boolean_type_node,
7222 fd->loops[i].v,
7223 fold_convert (itype, fd->loops[i].n2)),
7224 build_int_cst (itype2, 0),
7225 fold_convert (itype2, fd->loops[i - 1].step));
7226 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7227 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7228 else
7229 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7230 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7232 t = build3 (COND_EXPR, itype,
7233 build2 (fd->loops[i].cond_code, boolean_type_node,
7234 fd->loops[i].v,
7235 fold_convert (itype, fd->loops[i].n2)),
7236 fd->loops[i].v,
7237 fold_convert (itype, fd->loops[i].n1));
7238 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7242 /* Remove GIMPLE_OMP_CONTINUE. */
7243 gsi_remove (&gsi, true);
7246 /* Emit the condition in L1_BB. */
7247 gsi = gsi_start_bb (l1_bb);
7249 t = fold_convert (type, n2);
7250 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7251 false, GSI_CONTINUE_LINKING);
7252 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7253 cond_stmt = gimple_build_cond_empty (t);
7254 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7255 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7256 NULL, NULL)
7257 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7258 NULL, NULL))
7260 gsi = gsi_for_stmt (cond_stmt);
7261 gimple_regimplify_operands (cond_stmt, &gsi);
7264 /* Remove GIMPLE_OMP_RETURN. */
7265 gsi = gsi_last_bb (exit_bb);
7266 gsi_remove (&gsi, true);
7268 /* Connect the new blocks. */
7269 remove_edge (FALLTHRU_EDGE (entry_bb));
7271 if (!broken_loop)
7273 remove_edge (BRANCH_EDGE (entry_bb));
7274 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7276 e = BRANCH_EDGE (l1_bb);
7277 ne = FALLTHRU_EDGE (l1_bb);
7278 e->flags = EDGE_TRUE_VALUE;
7280 else
7282 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7284 ne = single_succ_edge (l1_bb);
7285 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7288 ne->flags = EDGE_FALSE_VALUE;
7289 e->probability = REG_BR_PROB_BASE * 7 / 8;
7290 ne->probability = REG_BR_PROB_BASE / 8;
7292 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7293 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7294 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7296 if (!broken_loop)
7298 struct loop *loop = alloc_loop ();
7299 loop->header = l1_bb;
7300 loop->latch = cont_bb;
7301 add_loop (loop, l1_bb->loop_father);
7302 if (safelen == NULL_TREE)
7303 loop->safelen = INT_MAX;
7304 else
7306 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7307 if (TREE_CODE (safelen) != INTEGER_CST)
7308 loop->safelen = 0;
7309 else if (!tree_fits_uhwi_p (safelen)
7310 || tree_to_uhwi (safelen) > INT_MAX)
7311 loop->safelen = INT_MAX;
7312 else
7313 loop->safelen = tree_to_uhwi (safelen);
7314 if (loop->safelen == 1)
7315 loop->safelen = 0;
7317 if (simduid)
7319 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7320 cfun->has_simduid_loops = true;
7322 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7323 the loop. */
7324 if ((flag_tree_loop_vectorize
7325 || (!global_options_set.x_flag_tree_loop_vectorize
7326 && !global_options_set.x_flag_tree_vectorize))
7327 && flag_tree_loop_optimize
7328 && loop->safelen > 1)
7330 loop->force_vectorize = true;
7331 cfun->has_force_vectorize_loops = true;
7337 /* Expand the OpenMP loop defined by REGION. */
7339 static void
7340 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7342 struct omp_for_data fd;
7343 struct omp_for_data_loop *loops;
7345 loops
7346 = (struct omp_for_data_loop *)
7347 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7348 * sizeof (struct omp_for_data_loop));
7349 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7350 &fd, loops);
7351 region->sched_kind = fd.sched_kind;
7353 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7354 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7355 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7356 if (region->cont)
7358 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7359 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7360 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7362 else
7363 /* If there isn't a continue then this is a degerate case where
7364 the introduction of abnormal edges during lowering will prevent
7365 original loops from being detected. Fix that up. */
7366 loops_state_set (LOOPS_NEED_FIXUP);
7368 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7369 expand_omp_simd (region, &fd);
7370 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7371 expand_cilk_for (region, &fd);
7372 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7373 && !fd.have_ordered)
7375 if (fd.chunk_size == NULL)
7376 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7377 else
7378 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7380 else
7382 int fn_index, start_ix, next_ix;
7384 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7385 == GF_OMP_FOR_KIND_FOR);
7386 if (fd.chunk_size == NULL
7387 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7388 fd.chunk_size = integer_zero_node;
7389 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7390 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7391 ? 3 : fd.sched_kind;
7392 fn_index += fd.have_ordered * 4;
7393 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7394 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7395 if (fd.iter_type == long_long_unsigned_type_node)
7397 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7398 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7399 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7400 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7402 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7403 (enum built_in_function) next_ix, inner_stmt);
7406 if (gimple_in_ssa_p (cfun))
7407 update_ssa (TODO_update_ssa_only_virtuals);
7411 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7413 v = GOMP_sections_start (n);
7415 switch (v)
7417 case 0:
7418 goto L2;
7419 case 1:
7420 section 1;
7421 goto L1;
7422 case 2:
7424 case n:
7426 default:
7427 abort ();
7430 v = GOMP_sections_next ();
7431 goto L0;
7433 reduction;
7435 If this is a combined parallel sections, replace the call to
7436 GOMP_sections_start with call to GOMP_sections_next. */
7438 static void
7439 expand_omp_sections (struct omp_region *region)
7441 tree t, u, vin = NULL, vmain, vnext, l2;
7442 unsigned len;
7443 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7444 gimple_stmt_iterator si, switch_si;
7445 gomp_sections *sections_stmt;
7446 gimple stmt;
7447 gomp_continue *cont;
7448 edge_iterator ei;
7449 edge e;
7450 struct omp_region *inner;
7451 unsigned i, casei;
7452 bool exit_reachable = region->cont != NULL;
7454 gcc_assert (region->exit != NULL);
7455 entry_bb = region->entry;
7456 l0_bb = single_succ (entry_bb);
7457 l1_bb = region->cont;
7458 l2_bb = region->exit;
7459 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7460 l2 = gimple_block_label (l2_bb);
7461 else
7463 /* This can happen if there are reductions. */
7464 len = EDGE_COUNT (l0_bb->succs);
7465 gcc_assert (len > 0);
7466 e = EDGE_SUCC (l0_bb, len - 1);
7467 si = gsi_last_bb (e->dest);
7468 l2 = NULL_TREE;
7469 if (gsi_end_p (si)
7470 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7471 l2 = gimple_block_label (e->dest);
7472 else
7473 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7475 si = gsi_last_bb (e->dest);
7476 if (gsi_end_p (si)
7477 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7479 l2 = gimple_block_label (e->dest);
7480 break;
7484 if (exit_reachable)
7485 default_bb = create_empty_bb (l1_bb->prev_bb);
7486 else
7487 default_bb = create_empty_bb (l0_bb);
7489 /* We will build a switch() with enough cases for all the
7490 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7491 and a default case to abort if something goes wrong. */
7492 len = EDGE_COUNT (l0_bb->succs);
7494 /* Use vec::quick_push on label_vec throughout, since we know the size
7495 in advance. */
7496 auto_vec<tree> label_vec (len);
7498 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7499 GIMPLE_OMP_SECTIONS statement. */
7500 si = gsi_last_bb (entry_bb);
7501 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
7502 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7503 vin = gimple_omp_sections_control (sections_stmt);
7504 if (!is_combined_parallel (region))
7506 /* If we are not inside a combined parallel+sections region,
7507 call GOMP_sections_start. */
7508 t = build_int_cst (unsigned_type_node, len - 1);
7509 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7510 stmt = gimple_build_call (u, 1, t);
7512 else
7514 /* Otherwise, call GOMP_sections_next. */
7515 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7516 stmt = gimple_build_call (u, 0);
7518 gimple_call_set_lhs (stmt, vin);
7519 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7520 gsi_remove (&si, true);
7522 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7523 L0_BB. */
7524 switch_si = gsi_last_bb (l0_bb);
7525 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7526 if (exit_reachable)
7528 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
7529 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7530 vmain = gimple_omp_continue_control_use (cont);
7531 vnext = gimple_omp_continue_control_def (cont);
7533 else
7535 vmain = vin;
7536 vnext = NULL_TREE;
7539 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7540 label_vec.quick_push (t);
7541 i = 1;
7543 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7544 for (inner = region->inner, casei = 1;
7545 inner;
7546 inner = inner->next, i++, casei++)
7548 basic_block s_entry_bb, s_exit_bb;
7550 /* Skip optional reduction region. */
7551 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7553 --i;
7554 --casei;
7555 continue;
7558 s_entry_bb = inner->entry;
7559 s_exit_bb = inner->exit;
7561 t = gimple_block_label (s_entry_bb);
7562 u = build_int_cst (unsigned_type_node, casei);
7563 u = build_case_label (u, NULL, t);
7564 label_vec.quick_push (u);
7566 si = gsi_last_bb (s_entry_bb);
7567 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7568 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7569 gsi_remove (&si, true);
7570 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7572 if (s_exit_bb == NULL)
7573 continue;
7575 si = gsi_last_bb (s_exit_bb);
7576 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7577 gsi_remove (&si, true);
7579 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7582 /* Error handling code goes in DEFAULT_BB. */
7583 t = gimple_block_label (default_bb);
7584 u = build_case_label (NULL, NULL, t);
7585 make_edge (l0_bb, default_bb, 0);
7586 add_bb_to_loop (default_bb, current_loops->tree_root);
7588 stmt = gimple_build_switch (vmain, u, label_vec);
7589 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7590 gsi_remove (&switch_si, true);
7592 si = gsi_start_bb (default_bb);
7593 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7594 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7596 if (exit_reachable)
7598 tree bfn_decl;
7600 /* Code to get the next section goes in L1_BB. */
7601 si = gsi_last_bb (l1_bb);
7602 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7604 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7605 stmt = gimple_build_call (bfn_decl, 0);
7606 gimple_call_set_lhs (stmt, vnext);
7607 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7608 gsi_remove (&si, true);
7610 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7613 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7614 si = gsi_last_bb (l2_bb);
7615 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7616 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7617 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7618 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7619 else
7620 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7621 stmt = gimple_build_call (t, 0);
7622 if (gimple_omp_return_lhs (gsi_stmt (si)))
7623 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7624 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7625 gsi_remove (&si, true);
7627 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7631 /* Expand code for an OpenMP single directive. We've already expanded
7632 much of the code, here we simply place the GOMP_barrier call. */
7634 static void
7635 expand_omp_single (struct omp_region *region)
7637 basic_block entry_bb, exit_bb;
7638 gimple_stmt_iterator si;
7640 entry_bb = region->entry;
7641 exit_bb = region->exit;
7643 si = gsi_last_bb (entry_bb);
7644 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7645 gsi_remove (&si, true);
7646 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7648 si = gsi_last_bb (exit_bb);
7649 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7651 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7652 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7654 gsi_remove (&si, true);
7655 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7659 /* Generic expansion for OpenMP synchronization directives: master,
7660 ordered and critical. All we need to do here is remove the entry
7661 and exit markers for REGION. */
7663 static void
7664 expand_omp_synch (struct omp_region *region)
7666 basic_block entry_bb, exit_bb;
7667 gimple_stmt_iterator si;
7669 entry_bb = region->entry;
7670 exit_bb = region->exit;
7672 si = gsi_last_bb (entry_bb);
7673 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7674 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7675 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7676 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7677 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7678 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7679 gsi_remove (&si, true);
7680 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7682 if (exit_bb)
7684 si = gsi_last_bb (exit_bb);
7685 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7686 gsi_remove (&si, true);
7687 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7691 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7692 operation as a normal volatile load. */
7694 static bool
7695 expand_omp_atomic_load (basic_block load_bb, tree addr,
7696 tree loaded_val, int index)
7698 enum built_in_function tmpbase;
7699 gimple_stmt_iterator gsi;
7700 basic_block store_bb;
7701 location_t loc;
7702 gimple stmt;
7703 tree decl, call, type, itype;
7705 gsi = gsi_last_bb (load_bb);
7706 stmt = gsi_stmt (gsi);
7707 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7708 loc = gimple_location (stmt);
7710 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7711 is smaller than word size, then expand_atomic_load assumes that the load
7712 is atomic. We could avoid the builtin entirely in this case. */
7714 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7715 decl = builtin_decl_explicit (tmpbase);
7716 if (decl == NULL_TREE)
7717 return false;
7719 type = TREE_TYPE (loaded_val);
7720 itype = TREE_TYPE (TREE_TYPE (decl));
7722 call = build_call_expr_loc (loc, decl, 2, addr,
7723 build_int_cst (NULL,
7724 gimple_omp_atomic_seq_cst_p (stmt)
7725 ? MEMMODEL_SEQ_CST
7726 : MEMMODEL_RELAXED));
7727 if (!useless_type_conversion_p (type, itype))
7728 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7729 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7731 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7732 gsi_remove (&gsi, true);
7734 store_bb = single_succ (load_bb);
7735 gsi = gsi_last_bb (store_bb);
7736 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7737 gsi_remove (&gsi, true);
7739 if (gimple_in_ssa_p (cfun))
7740 update_ssa (TODO_update_ssa_no_phi);
7742 return true;
7745 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7746 operation as a normal volatile store. */
7748 static bool
7749 expand_omp_atomic_store (basic_block load_bb, tree addr,
7750 tree loaded_val, tree stored_val, int index)
7752 enum built_in_function tmpbase;
7753 gimple_stmt_iterator gsi;
7754 basic_block store_bb = single_succ (load_bb);
7755 location_t loc;
7756 gimple stmt;
7757 tree decl, call, type, itype;
7758 machine_mode imode;
7759 bool exchange;
7761 gsi = gsi_last_bb (load_bb);
7762 stmt = gsi_stmt (gsi);
7763 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7765 /* If the load value is needed, then this isn't a store but an exchange. */
7766 exchange = gimple_omp_atomic_need_value_p (stmt);
7768 gsi = gsi_last_bb (store_bb);
7769 stmt = gsi_stmt (gsi);
7770 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7771 loc = gimple_location (stmt);
7773 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7774 is smaller than word size, then expand_atomic_store assumes that the store
7775 is atomic. We could avoid the builtin entirely in this case. */
7777 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7778 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7779 decl = builtin_decl_explicit (tmpbase);
7780 if (decl == NULL_TREE)
7781 return false;
7783 type = TREE_TYPE (stored_val);
7785 /* Dig out the type of the function's second argument. */
7786 itype = TREE_TYPE (decl);
7787 itype = TYPE_ARG_TYPES (itype);
7788 itype = TREE_CHAIN (itype);
7789 itype = TREE_VALUE (itype);
7790 imode = TYPE_MODE (itype);
7792 if (exchange && !can_atomic_exchange_p (imode, true))
7793 return false;
7795 if (!useless_type_conversion_p (itype, type))
7796 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7797 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7798 build_int_cst (NULL,
7799 gimple_omp_atomic_seq_cst_p (stmt)
7800 ? MEMMODEL_SEQ_CST
7801 : MEMMODEL_RELAXED));
7802 if (exchange)
7804 if (!useless_type_conversion_p (type, itype))
7805 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7806 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7809 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7810 gsi_remove (&gsi, true);
7812 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7813 gsi = gsi_last_bb (load_bb);
7814 gsi_remove (&gsi, true);
7816 if (gimple_in_ssa_p (cfun))
7817 update_ssa (TODO_update_ssa_no_phi);
7819 return true;
7822 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7823 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7824 size of the data type, and thus usable to find the index of the builtin
7825 decl. Returns false if the expression is not of the proper form. */
7827 static bool
7828 expand_omp_atomic_fetch_op (basic_block load_bb,
7829 tree addr, tree loaded_val,
7830 tree stored_val, int index)
7832 enum built_in_function oldbase, newbase, tmpbase;
7833 tree decl, itype, call;
7834 tree lhs, rhs;
7835 basic_block store_bb = single_succ (load_bb);
7836 gimple_stmt_iterator gsi;
7837 gimple stmt;
7838 location_t loc;
7839 enum tree_code code;
7840 bool need_old, need_new;
7841 machine_mode imode;
7842 bool seq_cst;
7844 /* We expect to find the following sequences:
7846 load_bb:
7847 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7849 store_bb:
7850 val = tmp OP something; (or: something OP tmp)
7851 GIMPLE_OMP_STORE (val)
7853 ???FIXME: Allow a more flexible sequence.
7854 Perhaps use data flow to pick the statements.
7858 gsi = gsi_after_labels (store_bb);
7859 stmt = gsi_stmt (gsi);
7860 loc = gimple_location (stmt);
7861 if (!is_gimple_assign (stmt))
7862 return false;
7863 gsi_next (&gsi);
7864 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7865 return false;
7866 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7867 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7868 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7869 gcc_checking_assert (!need_old || !need_new);
7871 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7872 return false;
7874 /* Check for one of the supported fetch-op operations. */
7875 code = gimple_assign_rhs_code (stmt);
7876 switch (code)
7878 case PLUS_EXPR:
7879 case POINTER_PLUS_EXPR:
7880 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7881 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7882 break;
7883 case MINUS_EXPR:
7884 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7885 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7886 break;
7887 case BIT_AND_EXPR:
7888 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7889 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7890 break;
7891 case BIT_IOR_EXPR:
7892 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7893 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7894 break;
7895 case BIT_XOR_EXPR:
7896 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7897 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7898 break;
7899 default:
7900 return false;
7903 /* Make sure the expression is of the proper form. */
7904 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7905 rhs = gimple_assign_rhs2 (stmt);
7906 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7907 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7908 rhs = gimple_assign_rhs1 (stmt);
7909 else
7910 return false;
7912 tmpbase = ((enum built_in_function)
7913 ((need_new ? newbase : oldbase) + index + 1));
7914 decl = builtin_decl_explicit (tmpbase);
7915 if (decl == NULL_TREE)
7916 return false;
7917 itype = TREE_TYPE (TREE_TYPE (decl));
7918 imode = TYPE_MODE (itype);
7920 /* We could test all of the various optabs involved, but the fact of the
7921 matter is that (with the exception of i486 vs i586 and xadd) all targets
7922 that support any atomic operaton optab also implements compare-and-swap.
7923 Let optabs.c take care of expanding any compare-and-swap loop. */
7924 if (!can_compare_and_swap_p (imode, true))
7925 return false;
7927 gsi = gsi_last_bb (load_bb);
7928 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7930 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7931 It only requires that the operation happen atomically. Thus we can
7932 use the RELAXED memory model. */
7933 call = build_call_expr_loc (loc, decl, 3, addr,
7934 fold_convert_loc (loc, itype, rhs),
7935 build_int_cst (NULL,
7936 seq_cst ? MEMMODEL_SEQ_CST
7937 : MEMMODEL_RELAXED));
7939 if (need_old || need_new)
7941 lhs = need_old ? loaded_val : stored_val;
7942 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7943 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7945 else
7946 call = fold_convert_loc (loc, void_type_node, call);
7947 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7948 gsi_remove (&gsi, true);
7950 gsi = gsi_last_bb (store_bb);
7951 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7952 gsi_remove (&gsi, true);
7953 gsi = gsi_last_bb (store_bb);
7954 gsi_remove (&gsi, true);
7956 if (gimple_in_ssa_p (cfun))
7957 update_ssa (TODO_update_ssa_no_phi);
7959 return true;
7962 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7964 oldval = *addr;
7965 repeat:
7966 newval = rhs; // with oldval replacing *addr in rhs
7967 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7968 if (oldval != newval)
7969 goto repeat;
7971 INDEX is log2 of the size of the data type, and thus usable to find the
7972 index of the builtin decl. */
7974 static bool
7975 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7976 tree addr, tree loaded_val, tree stored_val,
7977 int index)
7979 tree loadedi, storedi, initial, new_storedi, old_vali;
7980 tree type, itype, cmpxchg, iaddr;
7981 gimple_stmt_iterator si;
7982 basic_block loop_header = single_succ (load_bb);
7983 gimple phi, stmt;
7984 edge e;
7985 enum built_in_function fncode;
7987 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7988 order to use the RELAXED memory model effectively. */
7989 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7990 + index + 1);
7991 cmpxchg = builtin_decl_explicit (fncode);
7992 if (cmpxchg == NULL_TREE)
7993 return false;
7994 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7995 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7997 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7998 return false;
8000 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8001 si = gsi_last_bb (load_bb);
8002 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8004 /* For floating-point values, we'll need to view-convert them to integers
8005 so that we can perform the atomic compare and swap. Simplify the
8006 following code by always setting up the "i"ntegral variables. */
8007 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8009 tree iaddr_val;
8011 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8012 true), NULL);
8013 iaddr_val
8014 = force_gimple_operand_gsi (&si,
8015 fold_convert (TREE_TYPE (iaddr), addr),
8016 false, NULL_TREE, true, GSI_SAME_STMT);
8017 stmt = gimple_build_assign (iaddr, iaddr_val);
8018 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8019 loadedi = create_tmp_var (itype, NULL);
8020 if (gimple_in_ssa_p (cfun))
8021 loadedi = make_ssa_name (loadedi, NULL);
8023 else
8025 iaddr = addr;
8026 loadedi = loaded_val;
8029 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8030 tree loaddecl = builtin_decl_explicit (fncode);
8031 if (loaddecl)
8032 initial
8033 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8034 build_call_expr (loaddecl, 2, iaddr,
8035 build_int_cst (NULL_TREE,
8036 MEMMODEL_RELAXED)));
8037 else
8038 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8039 build_int_cst (TREE_TYPE (iaddr), 0));
8041 initial
8042 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8043 GSI_SAME_STMT);
8045 /* Move the value to the LOADEDI temporary. */
8046 if (gimple_in_ssa_p (cfun))
8048 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8049 phi = create_phi_node (loadedi, loop_header);
8050 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8051 initial);
8053 else
8054 gsi_insert_before (&si,
8055 gimple_build_assign (loadedi, initial),
8056 GSI_SAME_STMT);
8057 if (loadedi != loaded_val)
8059 gimple_stmt_iterator gsi2;
8060 tree x;
8062 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8063 gsi2 = gsi_start_bb (loop_header);
8064 if (gimple_in_ssa_p (cfun))
8066 gassign *stmt;
8067 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8068 true, GSI_SAME_STMT);
8069 stmt = gimple_build_assign (loaded_val, x);
8070 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8072 else
8074 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8075 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8076 true, GSI_SAME_STMT);
8079 gsi_remove (&si, true);
8081 si = gsi_last_bb (store_bb);
8082 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8084 if (iaddr == addr)
8085 storedi = stored_val;
8086 else
8087 storedi =
8088 force_gimple_operand_gsi (&si,
8089 build1 (VIEW_CONVERT_EXPR, itype,
8090 stored_val), true, NULL_TREE, true,
8091 GSI_SAME_STMT);
8093 /* Build the compare&swap statement. */
8094 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8095 new_storedi = force_gimple_operand_gsi (&si,
8096 fold_convert (TREE_TYPE (loadedi),
8097 new_storedi),
8098 true, NULL_TREE,
8099 true, GSI_SAME_STMT);
8101 if (gimple_in_ssa_p (cfun))
8102 old_vali = loadedi;
8103 else
8105 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
8106 stmt = gimple_build_assign (old_vali, loadedi);
8107 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8109 stmt = gimple_build_assign (loadedi, new_storedi);
8110 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8113 /* Note that we always perform the comparison as an integer, even for
8114 floating point. This allows the atomic operation to properly
8115 succeed even with NaNs and -0.0. */
8116 stmt = gimple_build_cond_empty
8117 (build2 (NE_EXPR, boolean_type_node,
8118 new_storedi, old_vali));
8119 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8121 /* Update cfg. */
8122 e = single_succ_edge (store_bb);
8123 e->flags &= ~EDGE_FALLTHRU;
8124 e->flags |= EDGE_FALSE_VALUE;
8126 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8128 /* Copy the new value to loadedi (we already did that before the condition
8129 if we are not in SSA). */
8130 if (gimple_in_ssa_p (cfun))
8132 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8133 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8136 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8137 gsi_remove (&si, true);
8139 struct loop *loop = alloc_loop ();
8140 loop->header = loop_header;
8141 loop->latch = store_bb;
8142 add_loop (loop, loop_header->loop_father);
8144 if (gimple_in_ssa_p (cfun))
8145 update_ssa (TODO_update_ssa_no_phi);
8147 return true;
8150 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8152 GOMP_atomic_start ();
8153 *addr = rhs;
8154 GOMP_atomic_end ();
8156 The result is not globally atomic, but works so long as all parallel
8157 references are within #pragma omp atomic directives. According to
8158 responses received from omp@openmp.org, appears to be within spec.
8159 Which makes sense, since that's how several other compilers handle
8160 this situation as well.
8161 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8162 expanding. STORED_VAL is the operand of the matching
8163 GIMPLE_OMP_ATOMIC_STORE.
8165 We replace
8166 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8167 loaded_val = *addr;
8169 and replace
8170 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8171 *addr = stored_val;
8174 static bool
8175 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8176 tree addr, tree loaded_val, tree stored_val)
8178 gimple_stmt_iterator si;
8179 gassign *stmt;
8180 tree t;
8182 si = gsi_last_bb (load_bb);
8183 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8185 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8186 t = build_call_expr (t, 0);
8187 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8189 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8190 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8191 gsi_remove (&si, true);
8193 si = gsi_last_bb (store_bb);
8194 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8196 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8197 stored_val);
8198 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8200 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8201 t = build_call_expr (t, 0);
8202 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8203 gsi_remove (&si, true);
8205 if (gimple_in_ssa_p (cfun))
8206 update_ssa (TODO_update_ssa_no_phi);
8207 return true;
8210 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8211 using expand_omp_atomic_fetch_op. If it failed, we try to
8212 call expand_omp_atomic_pipeline, and if it fails too, the
8213 ultimate fallback is wrapping the operation in a mutex
8214 (expand_omp_atomic_mutex). REGION is the atomic region built
8215 by build_omp_regions_1(). */
8217 static void
8218 expand_omp_atomic (struct omp_region *region)
8220 basic_block load_bb = region->entry, store_bb = region->exit;
8221 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8222 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8223 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8224 tree addr = gimple_omp_atomic_load_rhs (load);
8225 tree stored_val = gimple_omp_atomic_store_val (store);
8226 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8227 HOST_WIDE_INT index;
8229 /* Make sure the type is one of the supported sizes. */
8230 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8231 index = exact_log2 (index);
8232 if (index >= 0 && index <= 4)
8234 unsigned int align = TYPE_ALIGN_UNIT (type);
8236 /* __sync builtins require strict data alignment. */
8237 if (exact_log2 (align) >= index)
8239 /* Atomic load. */
8240 if (loaded_val == stored_val
8241 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8242 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8243 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8244 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8245 return;
8247 /* Atomic store. */
8248 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8249 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8250 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8251 && store_bb == single_succ (load_bb)
8252 && first_stmt (store_bb) == store
8253 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8254 stored_val, index))
8255 return;
8257 /* When possible, use specialized atomic update functions. */
8258 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8259 && store_bb == single_succ (load_bb)
8260 && expand_omp_atomic_fetch_op (load_bb, addr,
8261 loaded_val, stored_val, index))
8262 return;
8264 /* If we don't have specialized __sync builtins, try and implement
8265 as a compare and swap loop. */
8266 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8267 loaded_val, stored_val, index))
8268 return;
8272 /* The ultimate fallback is wrapping the operation in a mutex. */
8273 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8277 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
8279 static void
8280 expand_omp_target (struct omp_region *region)
8282 basic_block entry_bb, exit_bb, new_bb;
8283 struct function *child_cfun = NULL;
8284 tree child_fn = NULL_TREE, block, t;
8285 gimple_stmt_iterator gsi;
8286 gomp_target *entry_stmt;
8287 gimple stmt;
8288 edge e;
8290 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8291 new_bb = region->entry;
8292 int kind = gimple_omp_target_kind (entry_stmt);
8293 if (kind == GF_OMP_TARGET_KIND_REGION)
8295 child_fn = gimple_omp_target_child_fn (entry_stmt);
8296 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8299 entry_bb = region->entry;
8300 exit_bb = region->exit;
8302 if (kind == GF_OMP_TARGET_KIND_REGION)
8304 unsigned srcidx, dstidx, num;
8306 /* If the target region needs data sent from the parent
8307 function, then the very first statement (except possible
8308 tree profile counter updates) of the parallel body
8309 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8310 &.OMP_DATA_O is passed as an argument to the child function,
8311 we need to replace it with the argument as seen by the child
8312 function.
8314 In most cases, this will end up being the identity assignment
8315 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8316 a function call that has been inlined, the original PARM_DECL
8317 .OMP_DATA_I may have been converted into a different local
8318 variable. In which case, we need to keep the assignment. */
8319 if (gimple_omp_target_data_arg (entry_stmt))
8321 basic_block entry_succ_bb = single_succ (entry_bb);
8322 gimple_stmt_iterator gsi;
8323 tree arg;
8324 gimple tgtcopy_stmt = NULL;
8325 tree sender
8326 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
8328 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8330 gcc_assert (!gsi_end_p (gsi));
8331 stmt = gsi_stmt (gsi);
8332 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8333 continue;
8335 if (gimple_num_ops (stmt) == 2)
8337 tree arg = gimple_assign_rhs1 (stmt);
8339 /* We're ignoring the subcode because we're
8340 effectively doing a STRIP_NOPS. */
8342 if (TREE_CODE (arg) == ADDR_EXPR
8343 && TREE_OPERAND (arg, 0) == sender)
8345 tgtcopy_stmt = stmt;
8346 break;
8351 gcc_assert (tgtcopy_stmt != NULL);
8352 arg = DECL_ARGUMENTS (child_fn);
8354 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8355 gsi_remove (&gsi, true);
8358 /* Declare local variables needed in CHILD_CFUN. */
8359 block = DECL_INITIAL (child_fn);
8360 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8361 /* The gimplifier could record temporaries in target block
8362 rather than in containing function's local_decls chain,
8363 which would mean cgraph missed finalizing them. Do it now. */
8364 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8365 if (TREE_CODE (t) == VAR_DECL
8366 && TREE_STATIC (t)
8367 && !DECL_EXTERNAL (t))
8368 varpool_node::finalize_decl (t);
8369 DECL_SAVED_TREE (child_fn) = NULL;
8370 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8371 gimple_set_body (child_fn, NULL);
8372 TREE_USED (block) = 1;
8374 /* Reset DECL_CONTEXT on function arguments. */
8375 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8376 DECL_CONTEXT (t) = child_fn;
8378 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8379 so that it can be moved to the child function. */
8380 gsi = gsi_last_bb (entry_bb);
8381 stmt = gsi_stmt (gsi);
8382 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
8383 && gimple_omp_target_kind (stmt)
8384 == GF_OMP_TARGET_KIND_REGION);
8385 gsi_remove (&gsi, true);
8386 e = split_block (entry_bb, stmt);
8387 entry_bb = e->dest;
8388 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8390 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8391 if (exit_bb)
8393 gsi = gsi_last_bb (exit_bb);
8394 gcc_assert (!gsi_end_p (gsi)
8395 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8396 stmt = gimple_build_return (NULL);
8397 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8398 gsi_remove (&gsi, true);
8401 /* Move the target region into CHILD_CFUN. */
8403 block = gimple_block (entry_stmt);
8405 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8406 if (exit_bb)
8407 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8408 /* When the OMP expansion process cannot guarantee an up-to-date
8409 loop tree arrange for the child function to fixup loops. */
8410 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8411 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8413 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8414 num = vec_safe_length (child_cfun->local_decls);
8415 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8417 t = (*child_cfun->local_decls)[srcidx];
8418 if (DECL_CONTEXT (t) == cfun->decl)
8419 continue;
8420 if (srcidx != dstidx)
8421 (*child_cfun->local_decls)[dstidx] = t;
8422 dstidx++;
8424 if (dstidx != num)
8425 vec_safe_truncate (child_cfun->local_decls, dstidx);
8427 /* Inform the callgraph about the new function. */
8428 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8429 cgraph_node::add_new_function (child_fn, true);
8431 #ifdef ENABLE_OFFLOADING
8432 /* Add the new function to the offload table. */
8433 vec_safe_push (offload_funcs, child_fn);
8434 #endif
8436 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8437 fixed in a following pass. */
8438 push_cfun (child_cfun);
8439 cgraph_edge::rebuild_edges ();
8441 #ifdef ENABLE_OFFLOADING
8442 /* Prevent IPA from removing child_fn as unreachable, since there are no
8443 refs from the parent function to child_fn in offload LTO mode. */
8444 struct cgraph_node *node = cgraph_node::get (child_fn);
8445 node->mark_force_output ();
8446 #endif
8448 /* Some EH regions might become dead, see PR34608. If
8449 pass_cleanup_cfg isn't the first pass to happen with the
8450 new child, these dead EH edges might cause problems.
8451 Clean them up now. */
8452 if (flag_exceptions)
8454 basic_block bb;
8455 bool changed = false;
8457 FOR_EACH_BB_FN (bb, cfun)
8458 changed |= gimple_purge_dead_eh_edges (bb);
8459 if (changed)
8460 cleanup_tree_cfg ();
8462 pop_cfun ();
8465 /* Emit a library call to launch the target region, or do data
8466 transfers. */
8467 tree t1, t2, t3, t4, device, cond, c, clauses;
8468 enum built_in_function start_ix;
8469 location_t clause_loc;
8471 clauses = gimple_omp_target_clauses (entry_stmt);
8473 if (kind == GF_OMP_TARGET_KIND_REGION)
8474 start_ix = BUILT_IN_GOMP_TARGET;
8475 else if (kind == GF_OMP_TARGET_KIND_DATA)
8476 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8477 else
8478 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8480 /* By default, the value of DEVICE is -1 (let runtime library choose)
8481 and there is no conditional. */
8482 cond = NULL_TREE;
8483 device = build_int_cst (integer_type_node, -1);
8485 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8486 if (c)
8487 cond = OMP_CLAUSE_IF_EXPR (c);
8489 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8490 if (c)
8492 device = OMP_CLAUSE_DEVICE_ID (c);
8493 clause_loc = OMP_CLAUSE_LOCATION (c);
8495 else
8496 clause_loc = gimple_location (entry_stmt);
8498 /* Ensure 'device' is of the correct type. */
8499 device = fold_convert_loc (clause_loc, integer_type_node, device);
8501 /* If we found the clause 'if (cond)', build
8502 (cond ? device : -2). */
8503 if (cond)
8505 cond = gimple_boolify (cond);
8507 basic_block cond_bb, then_bb, else_bb;
8508 edge e;
8509 tree tmp_var;
8511 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8512 if (kind != GF_OMP_TARGET_KIND_REGION)
8514 gsi = gsi_last_bb (new_bb);
8515 gsi_prev (&gsi);
8516 e = split_block (new_bb, gsi_stmt (gsi));
8518 else
8519 e = split_block (new_bb, NULL);
8520 cond_bb = e->src;
8521 new_bb = e->dest;
8522 remove_edge (e);
8524 then_bb = create_empty_bb (cond_bb);
8525 else_bb = create_empty_bb (then_bb);
8526 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8527 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8529 stmt = gimple_build_cond_empty (cond);
8530 gsi = gsi_last_bb (cond_bb);
8531 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8533 gsi = gsi_start_bb (then_bb);
8534 stmt = gimple_build_assign (tmp_var, device);
8535 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8537 gsi = gsi_start_bb (else_bb);
8538 stmt = gimple_build_assign (tmp_var,
8539 build_int_cst (integer_type_node, -2));
8540 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8542 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8543 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8544 add_bb_to_loop (then_bb, cond_bb->loop_father);
8545 add_bb_to_loop (else_bb, cond_bb->loop_father);
8546 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8547 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8549 device = tmp_var;
8552 gsi = gsi_last_bb (new_bb);
8553 t = gimple_omp_target_data_arg (entry_stmt);
8554 if (t == NULL)
8556 t1 = size_zero_node;
8557 t2 = build_zero_cst (ptr_type_node);
8558 t3 = t2;
8559 t4 = t2;
8561 else
8563 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8564 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8565 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8566 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8567 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8570 gimple g;
8571 /* FIXME: This will be address of
8572 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8573 symbol, as soon as the linker plugin is able to create it for us. */
8574 tree openmp_target = build_zero_cst (ptr_type_node);
8575 if (kind == GF_OMP_TARGET_KIND_REGION)
8577 tree fnaddr = build_fold_addr_expr (child_fn);
8578 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8579 device, fnaddr, openmp_target, t1, t2, t3, t4);
8581 else
8582 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8583 device, openmp_target, t1, t2, t3, t4);
8584 gimple_set_location (g, gimple_location (entry_stmt));
8585 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8586 if (kind != GF_OMP_TARGET_KIND_REGION)
8588 g = gsi_stmt (gsi);
8589 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8590 gsi_remove (&gsi, true);
8592 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8594 gsi = gsi_last_bb (region->exit);
8595 g = gsi_stmt (gsi);
8596 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8597 gsi_remove (&gsi, true);
8602 /* Expand the parallel region tree rooted at REGION. Expansion
8603 proceeds in depth-first order. Innermost regions are expanded
8604 first. This way, parallel regions that require a new function to
8605 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8606 internal dependencies in their body. */
8608 static void
8609 expand_omp (struct omp_region *region)
8611 while (region)
8613 location_t saved_location;
8614 gimple inner_stmt = NULL;
8616 /* First, determine whether this is a combined parallel+workshare
8617 region. */
8618 if (region->type == GIMPLE_OMP_PARALLEL)
8619 determine_parallel_type (region);
8621 if (region->type == GIMPLE_OMP_FOR
8622 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8623 inner_stmt = last_stmt (region->inner->entry);
8625 if (region->inner)
8626 expand_omp (region->inner);
8628 saved_location = input_location;
8629 if (gimple_has_location (last_stmt (region->entry)))
8630 input_location = gimple_location (last_stmt (region->entry));
8632 switch (region->type)
8634 case GIMPLE_OMP_PARALLEL:
8635 case GIMPLE_OMP_TASK:
8636 expand_omp_taskreg (region);
8637 break;
8639 case GIMPLE_OMP_FOR:
8640 expand_omp_for (region, inner_stmt);
8641 break;
8643 case GIMPLE_OMP_SECTIONS:
8644 expand_omp_sections (region);
8645 break;
8647 case GIMPLE_OMP_SECTION:
8648 /* Individual omp sections are handled together with their
8649 parent GIMPLE_OMP_SECTIONS region. */
8650 break;
8652 case GIMPLE_OMP_SINGLE:
8653 expand_omp_single (region);
8654 break;
8656 case GIMPLE_OMP_MASTER:
8657 case GIMPLE_OMP_TASKGROUP:
8658 case GIMPLE_OMP_ORDERED:
8659 case GIMPLE_OMP_CRITICAL:
8660 case GIMPLE_OMP_TEAMS:
8661 expand_omp_synch (region);
8662 break;
8664 case GIMPLE_OMP_ATOMIC_LOAD:
8665 expand_omp_atomic (region);
8666 break;
8668 case GIMPLE_OMP_TARGET:
8669 expand_omp_target (region);
8670 break;
8672 default:
8673 gcc_unreachable ();
8676 input_location = saved_location;
8677 region = region->next;
8682 /* Helper for build_omp_regions. Scan the dominator tree starting at
8683 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8684 true, the function ends once a single tree is built (otherwise, whole
8685 forest of OMP constructs may be built). */
8687 static void
8688 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8689 bool single_tree)
8691 gimple_stmt_iterator gsi;
8692 gimple stmt;
8693 basic_block son;
8695 gsi = gsi_last_bb (bb);
8696 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8698 struct omp_region *region;
8699 enum gimple_code code;
8701 stmt = gsi_stmt (gsi);
8702 code = gimple_code (stmt);
8703 if (code == GIMPLE_OMP_RETURN)
8705 /* STMT is the return point out of region PARENT. Mark it
8706 as the exit point and make PARENT the immediately
8707 enclosing region. */
8708 gcc_assert (parent);
8709 region = parent;
8710 region->exit = bb;
8711 parent = parent->outer;
8713 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8715 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8716 GIMPLE_OMP_RETURN, but matches with
8717 GIMPLE_OMP_ATOMIC_LOAD. */
8718 gcc_assert (parent);
8719 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8720 region = parent;
8721 region->exit = bb;
8722 parent = parent->outer;
8725 else if (code == GIMPLE_OMP_CONTINUE)
8727 gcc_assert (parent);
8728 parent->cont = bb;
8730 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8732 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8733 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8736 else if (code == GIMPLE_OMP_TARGET
8737 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8738 new_omp_region (bb, code, parent);
8739 else
8741 /* Otherwise, this directive becomes the parent for a new
8742 region. */
8743 region = new_omp_region (bb, code, parent);
8744 parent = region;
8748 if (single_tree && !parent)
8749 return;
8751 for (son = first_dom_son (CDI_DOMINATORS, bb);
8752 son;
8753 son = next_dom_son (CDI_DOMINATORS, son))
8754 build_omp_regions_1 (son, parent, single_tree);
8757 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8758 root_omp_region. */
8760 static void
8761 build_omp_regions_root (basic_block root)
8763 gcc_assert (root_omp_region == NULL);
8764 build_omp_regions_1 (root, NULL, true);
8765 gcc_assert (root_omp_region != NULL);
8768 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8770 void
8771 omp_expand_local (basic_block head)
8773 build_omp_regions_root (head);
8774 if (dump_file && (dump_flags & TDF_DETAILS))
8776 fprintf (dump_file, "\nOMP region tree\n\n");
8777 dump_omp_region (dump_file, root_omp_region, 0);
8778 fprintf (dump_file, "\n");
8781 remove_exit_barriers (root_omp_region);
8782 expand_omp (root_omp_region);
8784 free_omp_regions ();
8787 /* Scan the CFG and build a tree of OMP regions. Return the root of
8788 the OMP region tree. */
8790 static void
8791 build_omp_regions (void)
8793 gcc_assert (root_omp_region == NULL);
8794 calculate_dominance_info (CDI_DOMINATORS);
8795 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8798 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8800 static unsigned int
8801 execute_expand_omp (void)
8803 build_omp_regions ();
8805 if (!root_omp_region)
8806 return 0;
8808 if (dump_file)
8810 fprintf (dump_file, "\nOMP region tree\n\n");
8811 dump_omp_region (dump_file, root_omp_region, 0);
8812 fprintf (dump_file, "\n");
8815 remove_exit_barriers (root_omp_region);
8817 expand_omp (root_omp_region);
8819 cleanup_tree_cfg ();
8821 free_omp_regions ();
8823 return 0;
8826 /* OMP expansion -- the default pass, run before creation of SSA form. */
8828 namespace {
8830 const pass_data pass_data_expand_omp =
8832 GIMPLE_PASS, /* type */
8833 "ompexp", /* name */
8834 OPTGROUP_NONE, /* optinfo_flags */
8835 TV_NONE, /* tv_id */
8836 PROP_gimple_any, /* properties_required */
8837 PROP_gimple_eomp, /* properties_provided */
8838 0, /* properties_destroyed */
8839 0, /* todo_flags_start */
8840 0, /* todo_flags_finish */
8843 class pass_expand_omp : public gimple_opt_pass
8845 public:
8846 pass_expand_omp (gcc::context *ctxt)
8847 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8850 /* opt_pass methods: */
8851 virtual unsigned int execute (function *)
8853 bool gate = ((flag_openmp != 0 || flag_openmp_simd != 0
8854 || flag_cilkplus != 0) && !seen_error ());
8856 /* This pass always runs, to provide PROP_gimple_eomp.
8857 But there is nothing to do unless -fopenmp is given. */
8858 if (!gate)
8859 return 0;
8861 return execute_expand_omp ();
8864 }; // class pass_expand_omp
8866 } // anon namespace
8868 gimple_opt_pass *
8869 make_pass_expand_omp (gcc::context *ctxt)
8871 return new pass_expand_omp (ctxt);
8874 namespace {
8876 const pass_data pass_data_expand_omp_ssa =
8878 GIMPLE_PASS, /* type */
8879 "ompexpssa", /* name */
8880 OPTGROUP_NONE, /* optinfo_flags */
8881 TV_NONE, /* tv_id */
8882 PROP_cfg | PROP_ssa, /* properties_required */
8883 PROP_gimple_eomp, /* properties_provided */
8884 0, /* properties_destroyed */
8885 0, /* todo_flags_start */
8886 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
8889 class pass_expand_omp_ssa : public gimple_opt_pass
8891 public:
8892 pass_expand_omp_ssa (gcc::context *ctxt)
8893 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
8896 /* opt_pass methods: */
8897 virtual bool gate (function *fun)
8899 return !(fun->curr_properties & PROP_gimple_eomp);
8901 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8903 }; // class pass_expand_omp_ssa
8905 } // anon namespace
8907 gimple_opt_pass *
8908 make_pass_expand_omp_ssa (gcc::context *ctxt)
8910 return new pass_expand_omp_ssa (ctxt);
8913 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8915 /* If ctx is a worksharing context inside of a cancellable parallel
8916 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8917 and conditional branch to parallel's cancel_label to handle
8918 cancellation in the implicit barrier. */
8920 static void
8921 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8923 gimple omp_return = gimple_seq_last_stmt (*body);
8924 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8925 if (gimple_omp_return_nowait_p (omp_return))
8926 return;
8927 if (ctx->outer
8928 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8929 && ctx->outer->cancellable)
8931 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8932 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8933 tree lhs = create_tmp_var (c_bool_type, NULL);
8934 gimple_omp_return_set_lhs (omp_return, lhs);
8935 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8936 gimple g = gimple_build_cond (NE_EXPR, lhs,
8937 fold_convert (c_bool_type,
8938 boolean_false_node),
8939 ctx->outer->cancel_label, fallthru_label);
8940 gimple_seq_add_stmt (body, g);
8941 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8945 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8946 CTX is the enclosing OMP context for the current statement. */
8948 static void
8949 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8951 tree block, control;
8952 gimple_stmt_iterator tgsi;
8953 gomp_sections *stmt;
8954 gimple t;
8955 gbind *new_stmt, *bind;
8956 gimple_seq ilist, dlist, olist, new_body;
8958 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
8960 push_gimplify_context ();
8962 dlist = NULL;
8963 ilist = NULL;
8964 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8965 &ilist, &dlist, ctx, NULL);
8967 new_body = gimple_omp_body (stmt);
8968 gimple_omp_set_body (stmt, NULL);
8969 tgsi = gsi_start (new_body);
8970 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8972 omp_context *sctx;
8973 gimple sec_start;
8975 sec_start = gsi_stmt (tgsi);
8976 sctx = maybe_lookup_ctx (sec_start);
8977 gcc_assert (sctx);
8979 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8980 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8981 GSI_CONTINUE_LINKING);
8982 gimple_omp_set_body (sec_start, NULL);
8984 if (gsi_one_before_end_p (tgsi))
8986 gimple_seq l = NULL;
8987 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8988 &l, ctx);
8989 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8990 gimple_omp_section_set_last (sec_start);
8993 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8994 GSI_CONTINUE_LINKING);
8997 block = make_node (BLOCK);
8998 bind = gimple_build_bind (NULL, new_body, block);
9000 olist = NULL;
9001 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
9003 block = make_node (BLOCK);
9004 new_stmt = gimple_build_bind (NULL, NULL, block);
9005 gsi_replace (gsi_p, new_stmt, true);
9007 pop_gimplify_context (new_stmt);
9008 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9009 BLOCK_VARS (block) = gimple_bind_vars (bind);
9010 if (BLOCK_VARS (block))
9011 TREE_USED (block) = 1;
9013 new_body = NULL;
9014 gimple_seq_add_seq (&new_body, ilist);
9015 gimple_seq_add_stmt (&new_body, stmt);
9016 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
9017 gimple_seq_add_stmt (&new_body, bind);
9019 control = create_tmp_var (unsigned_type_node, ".section");
9020 t = gimple_build_omp_continue (control, control);
9021 gimple_omp_sections_set_control (stmt, control);
9022 gimple_seq_add_stmt (&new_body, t);
9024 gimple_seq_add_seq (&new_body, olist);
9025 if (ctx->cancellable)
9026 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9027 gimple_seq_add_seq (&new_body, dlist);
9029 new_body = maybe_catch_exception (new_body);
9031 t = gimple_build_omp_return
9032 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
9033 OMP_CLAUSE_NOWAIT));
9034 gimple_seq_add_stmt (&new_body, t);
9035 maybe_add_implicit_barrier_cancel (ctx, &new_body);
9037 gimple_bind_set_body (new_stmt, new_body);
9041 /* A subroutine of lower_omp_single. Expand the simple form of
9042 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
9044 if (GOMP_single_start ())
9045 BODY;
9046 [ GOMP_barrier (); ] -> unless 'nowait' is present.
9048 FIXME. It may be better to delay expanding the logic of this until
9049 pass_expand_omp. The expanded logic may make the job more difficult
9050 to a synchronization analysis pass. */
9052 static void
9053 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
9055 location_t loc = gimple_location (single_stmt);
9056 tree tlabel = create_artificial_label (loc);
9057 tree flabel = create_artificial_label (loc);
9058 gimple call, cond;
9059 tree lhs, decl;
9061 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
9062 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
9063 call = gimple_build_call (decl, 0);
9064 gimple_call_set_lhs (call, lhs);
9065 gimple_seq_add_stmt (pre_p, call);
9067 cond = gimple_build_cond (EQ_EXPR, lhs,
9068 fold_convert_loc (loc, TREE_TYPE (lhs),
9069 boolean_true_node),
9070 tlabel, flabel);
9071 gimple_seq_add_stmt (pre_p, cond);
9072 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
9073 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9074 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
9078 /* A subroutine of lower_omp_single. Expand the simple form of
9079 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
9081 #pragma omp single copyprivate (a, b, c)
9083 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
9086 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
9088 BODY;
9089 copyout.a = a;
9090 copyout.b = b;
9091 copyout.c = c;
9092 GOMP_single_copy_end (&copyout);
9094 else
9096 a = copyout_p->a;
9097 b = copyout_p->b;
9098 c = copyout_p->c;
9100 GOMP_barrier ();
9103 FIXME. It may be better to delay expanding the logic of this until
9104 pass_expand_omp. The expanded logic may make the job more difficult
9105 to a synchronization analysis pass. */
9107 static void
9108 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
9109 omp_context *ctx)
9111 tree ptr_type, t, l0, l1, l2, bfn_decl;
9112 gimple_seq copyin_seq;
9113 location_t loc = gimple_location (single_stmt);
9115 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
9117 ptr_type = build_pointer_type (ctx->record_type);
9118 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
9120 l0 = create_artificial_label (loc);
9121 l1 = create_artificial_label (loc);
9122 l2 = create_artificial_label (loc);
9124 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
9125 t = build_call_expr_loc (loc, bfn_decl, 0);
9126 t = fold_convert_loc (loc, ptr_type, t);
9127 gimplify_assign (ctx->receiver_decl, t, pre_p);
9129 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
9130 build_int_cst (ptr_type, 0));
9131 t = build3 (COND_EXPR, void_type_node, t,
9132 build_and_jump (&l0), build_and_jump (&l1));
9133 gimplify_and_add (t, pre_p);
9135 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
9137 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9139 copyin_seq = NULL;
9140 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
9141 &copyin_seq, ctx);
9143 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9144 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
9145 t = build_call_expr_loc (loc, bfn_decl, 1, t);
9146 gimplify_and_add (t, pre_p);
9148 t = build_and_jump (&l2);
9149 gimplify_and_add (t, pre_p);
9151 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
9153 gimple_seq_add_seq (pre_p, copyin_seq);
9155 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
9159 /* Expand code for an OpenMP single directive. */
9161 static void
9162 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9164 tree block;
9165 gimple t;
9166 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
9167 gbind *bind;
9168 gimple_seq bind_body, bind_body_tail = NULL, dlist;
9170 push_gimplify_context ();
9172 block = make_node (BLOCK);
9173 bind = gimple_build_bind (NULL, NULL, block);
9174 gsi_replace (gsi_p, bind, true);
9175 bind_body = NULL;
9176 dlist = NULL;
9177 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
9178 &bind_body, &dlist, ctx, NULL);
9179 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
9181 gimple_seq_add_stmt (&bind_body, single_stmt);
9183 if (ctx->record_type)
9184 lower_omp_single_copy (single_stmt, &bind_body, ctx);
9185 else
9186 lower_omp_single_simple (single_stmt, &bind_body);
9188 gimple_omp_set_body (single_stmt, NULL);
9190 gimple_seq_add_seq (&bind_body, dlist);
9192 bind_body = maybe_catch_exception (bind_body);
9194 t = gimple_build_omp_return
9195 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
9196 OMP_CLAUSE_NOWAIT));
9197 gimple_seq_add_stmt (&bind_body_tail, t);
9198 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
9199 if (ctx->record_type)
9201 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9202 tree clobber = build_constructor (ctx->record_type, NULL);
9203 TREE_THIS_VOLATILE (clobber) = 1;
9204 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9205 clobber), GSI_SAME_STMT);
9207 gimple_seq_add_seq (&bind_body, bind_body_tail);
9208 gimple_bind_set_body (bind, bind_body);
9210 pop_gimplify_context (bind);
9212 gimple_bind_append_vars (bind, ctx->block_vars);
9213 BLOCK_VARS (block) = ctx->block_vars;
9214 if (BLOCK_VARS (block))
9215 TREE_USED (block) = 1;
9219 /* Expand code for an OpenMP master directive. */
9221 static void
9222 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9224 tree block, lab = NULL, x, bfn_decl;
9225 gimple stmt = gsi_stmt (*gsi_p);
9226 gbind *bind;
9227 location_t loc = gimple_location (stmt);
9228 gimple_seq tseq;
9230 push_gimplify_context ();
9232 block = make_node (BLOCK);
9233 bind = gimple_build_bind (NULL, NULL, block);
9234 gsi_replace (gsi_p, bind, true);
9235 gimple_bind_add_stmt (bind, stmt);
9237 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9238 x = build_call_expr_loc (loc, bfn_decl, 0);
9239 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
9240 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9241 tseq = NULL;
9242 gimplify_and_add (x, &tseq);
9243 gimple_bind_add_seq (bind, tseq);
9245 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9246 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9247 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9248 gimple_omp_set_body (stmt, NULL);
9250 gimple_bind_add_stmt (bind, gimple_build_label (lab));
9252 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9254 pop_gimplify_context (bind);
9256 gimple_bind_append_vars (bind, ctx->block_vars);
9257 BLOCK_VARS (block) = ctx->block_vars;
9261 /* Expand code for an OpenMP taskgroup directive. */
9263 static void
9264 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9266 gimple stmt = gsi_stmt (*gsi_p);
9267 gcall *x;
9268 gbind *bind;
9269 tree block = make_node (BLOCK);
9271 bind = gimple_build_bind (NULL, NULL, block);
9272 gsi_replace (gsi_p, bind, true);
9273 gimple_bind_add_stmt (bind, stmt);
9275 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9277 gimple_bind_add_stmt (bind, x);
9279 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9280 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9281 gimple_omp_set_body (stmt, NULL);
9283 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9285 gimple_bind_append_vars (bind, ctx->block_vars);
9286 BLOCK_VARS (block) = ctx->block_vars;
9290 /* Expand code for an OpenMP ordered directive. */
9292 static void
9293 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9295 tree block;
9296 gimple stmt = gsi_stmt (*gsi_p);
9297 gcall *x;
9298 gbind *bind;
9300 push_gimplify_context ();
9302 block = make_node (BLOCK);
9303 bind = gimple_build_bind (NULL, NULL, block);
9304 gsi_replace (gsi_p, bind, true);
9305 gimple_bind_add_stmt (bind, stmt);
9307 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
9309 gimple_bind_add_stmt (bind, x);
9311 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9312 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9313 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9314 gimple_omp_set_body (stmt, NULL);
9316 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
9317 gimple_bind_add_stmt (bind, x);
9319 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9321 pop_gimplify_context (bind);
9323 gimple_bind_append_vars (bind, ctx->block_vars);
9324 BLOCK_VARS (block) = gimple_bind_vars (bind);
9328 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9329 substitution of a couple of function calls. But in the NAMED case,
9330 requires that languages coordinate a symbol name. It is therefore
9331 best put here in common code. */
9333 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
9335 static void
9336 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9338 tree block;
9339 tree name, lock, unlock;
9340 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
9341 gbind *bind;
9342 location_t loc = gimple_location (stmt);
9343 gimple_seq tbody;
9345 name = gimple_omp_critical_name (stmt);
9346 if (name)
9348 tree decl;
9350 if (!critical_name_mutexes)
9351 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
9353 tree *n = critical_name_mutexes->get (name);
9354 if (n == NULL)
9356 char *new_str;
9358 decl = create_tmp_var_raw (ptr_type_node, NULL);
9360 new_str = ACONCAT ((".gomp_critical_user_",
9361 IDENTIFIER_POINTER (name), NULL));
9362 DECL_NAME (decl) = get_identifier (new_str);
9363 TREE_PUBLIC (decl) = 1;
9364 TREE_STATIC (decl) = 1;
9365 DECL_COMMON (decl) = 1;
9366 DECL_ARTIFICIAL (decl) = 1;
9367 DECL_IGNORED_P (decl) = 1;
9369 /* If '#pragma omp critical' is inside target region, the symbol must
9370 be marked for offloading. */
9371 omp_context *octx;
9372 for (octx = ctx->outer; octx; octx = octx->outer)
9373 if (is_targetreg_ctx (octx))
9375 varpool_node::get_create (decl)->offloadable = 1;
9376 break;
9379 varpool_node::finalize_decl (decl);
9381 critical_name_mutexes->put (name, decl);
9383 else
9384 decl = *n;
9386 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
9387 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
9389 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
9390 unlock = build_call_expr_loc (loc, unlock, 1,
9391 build_fold_addr_expr_loc (loc, decl));
9393 else
9395 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
9396 lock = build_call_expr_loc (loc, lock, 0);
9398 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
9399 unlock = build_call_expr_loc (loc, unlock, 0);
9402 push_gimplify_context ();
9404 block = make_node (BLOCK);
9405 bind = gimple_build_bind (NULL, NULL, block);
9406 gsi_replace (gsi_p, bind, true);
9407 gimple_bind_add_stmt (bind, stmt);
9409 tbody = gimple_bind_body (bind);
9410 gimplify_and_add (lock, &tbody);
9411 gimple_bind_set_body (bind, tbody);
9413 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9414 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9415 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9416 gimple_omp_set_body (stmt, NULL);
9418 tbody = gimple_bind_body (bind);
9419 gimplify_and_add (unlock, &tbody);
9420 gimple_bind_set_body (bind, tbody);
9422 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9424 pop_gimplify_context (bind);
9425 gimple_bind_append_vars (bind, ctx->block_vars);
9426 BLOCK_VARS (block) = gimple_bind_vars (bind);
9430 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9431 for a lastprivate clause. Given a loop control predicate of (V
9432 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9433 is appended to *DLIST, iterator initialization is appended to
9434 *BODY_P. */
9436 static void
9437 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
9438 gimple_seq *dlist, struct omp_context *ctx)
9440 tree clauses, cond, vinit;
9441 enum tree_code cond_code;
9442 gimple_seq stmts;
9444 cond_code = fd->loop.cond_code;
9445 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
9447 /* When possible, use a strict equality expression. This can let VRP
9448 type optimizations deduce the value and remove a copy. */
9449 if (tree_fits_shwi_p (fd->loop.step))
9451 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
9452 if (step == 1 || step == -1)
9453 cond_code = EQ_EXPR;
9456 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
9458 clauses = gimple_omp_for_clauses (fd->for_stmt);
9459 stmts = NULL;
9460 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
9461 if (!gimple_seq_empty_p (stmts))
9463 gimple_seq_add_seq (&stmts, *dlist);
9464 *dlist = stmts;
9466 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9467 vinit = fd->loop.n1;
9468 if (cond_code == EQ_EXPR
9469 && tree_fits_shwi_p (fd->loop.n2)
9470 && ! integer_zerop (fd->loop.n2))
9471 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
9472 else
9473 vinit = unshare_expr (vinit);
9475 /* Initialize the iterator variable, so that threads that don't execute
9476 any iterations don't execute the lastprivate clauses by accident. */
9477 gimplify_assign (fd->loop.v, vinit, body_p);
9482 /* Lower code for an OpenMP loop directive. */
9484 static void
9485 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9487 tree *rhs_p, block;
9488 struct omp_for_data fd, *fdp = NULL;
9489 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
9490 gbind *new_stmt;
9491 gimple_seq omp_for_body, body, dlist;
9492 size_t i;
9494 push_gimplify_context ();
9496 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
9498 block = make_node (BLOCK);
9499 new_stmt = gimple_build_bind (NULL, NULL, block);
9500 /* Replace at gsi right away, so that 'stmt' is no member
9501 of a sequence anymore as we're going to add to to a different
9502 one below. */
9503 gsi_replace (gsi_p, new_stmt, true);
9505 /* Move declaration of temporaries in the loop body before we make
9506 it go away. */
9507 omp_for_body = gimple_omp_body (stmt);
9508 if (!gimple_seq_empty_p (omp_for_body)
9509 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9511 gbind *inner_bind
9512 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
9513 tree vars = gimple_bind_vars (inner_bind);
9514 gimple_bind_append_vars (new_stmt, vars);
9515 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9516 keep them on the inner_bind and it's block. */
9517 gimple_bind_set_vars (inner_bind, NULL_TREE);
9518 if (gimple_bind_block (inner_bind))
9519 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9522 if (gimple_omp_for_combined_into_p (stmt))
9524 extract_omp_for_data (stmt, &fd, NULL);
9525 fdp = &fd;
9527 /* We need two temporaries with fd.loop.v type (istart/iend)
9528 and then (fd.collapse - 1) temporaries with the same
9529 type for count2 ... countN-1 vars if not constant. */
9530 size_t count = 2;
9531 tree type = fd.iter_type;
9532 if (fd.collapse > 1
9533 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9534 count += fd.collapse - 1;
9535 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9536 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9537 tree clauses = *pc;
9538 if (parallel_for)
9539 outerc
9540 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9541 OMP_CLAUSE__LOOPTEMP_);
9542 for (i = 0; i < count; i++)
9544 tree temp;
9545 if (parallel_for)
9547 gcc_assert (outerc);
9548 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9549 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9550 OMP_CLAUSE__LOOPTEMP_);
9552 else
9554 temp = create_tmp_var (type, NULL);
9555 insert_decl_map (&ctx->outer->cb, temp, temp);
9557 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9558 OMP_CLAUSE_DECL (*pc) = temp;
9559 pc = &OMP_CLAUSE_CHAIN (*pc);
9561 *pc = clauses;
9564 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9565 dlist = NULL;
9566 body = NULL;
9567 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9568 fdp);
9569 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9571 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9573 /* Lower the header expressions. At this point, we can assume that
9574 the header is of the form:
9576 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9578 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9579 using the .omp_data_s mapping, if needed. */
9580 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9582 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9583 if (!is_gimple_min_invariant (*rhs_p))
9584 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9586 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9587 if (!is_gimple_min_invariant (*rhs_p))
9588 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9590 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9591 if (!is_gimple_min_invariant (*rhs_p))
9592 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9595 /* Once lowered, extract the bounds and clauses. */
9596 extract_omp_for_data (stmt, &fd, NULL);
9598 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9600 gimple_seq_add_stmt (&body, stmt);
9601 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9603 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9604 fd.loop.v));
9606 /* After the loop, add exit clauses. */
9607 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9609 if (ctx->cancellable)
9610 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9612 gimple_seq_add_seq (&body, dlist);
9614 body = maybe_catch_exception (body);
9616 /* Region exit marker goes at the end of the loop body. */
9617 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9618 maybe_add_implicit_barrier_cancel (ctx, &body);
9619 pop_gimplify_context (new_stmt);
9621 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9622 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9623 if (BLOCK_VARS (block))
9624 TREE_USED (block) = 1;
9626 gimple_bind_set_body (new_stmt, body);
9627 gimple_omp_set_body (stmt, NULL);
9628 gimple_omp_for_set_pre_body (stmt, NULL);
9631 /* Callback for walk_stmts. Check if the current statement only contains
9632 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9634 static tree
9635 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9636 bool *handled_ops_p,
9637 struct walk_stmt_info *wi)
9639 int *info = (int *) wi->info;
9640 gimple stmt = gsi_stmt (*gsi_p);
9642 *handled_ops_p = true;
9643 switch (gimple_code (stmt))
9645 WALK_SUBSTMTS;
9647 case GIMPLE_OMP_FOR:
9648 case GIMPLE_OMP_SECTIONS:
9649 *info = *info == 0 ? 1 : -1;
9650 break;
9651 default:
9652 *info = -1;
9653 break;
9655 return NULL;
9658 struct omp_taskcopy_context
9660 /* This field must be at the beginning, as we do "inheritance": Some
9661 callback functions for tree-inline.c (e.g., omp_copy_decl)
9662 receive a copy_body_data pointer that is up-casted to an
9663 omp_context pointer. */
9664 copy_body_data cb;
9665 omp_context *ctx;
9668 static tree
9669 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9671 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9673 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9674 return create_tmp_var (TREE_TYPE (var), NULL);
9676 return var;
9679 static tree
9680 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9682 tree name, new_fields = NULL, type, f;
9684 type = lang_hooks.types.make_type (RECORD_TYPE);
9685 name = DECL_NAME (TYPE_NAME (orig_type));
9686 name = build_decl (gimple_location (tcctx->ctx->stmt),
9687 TYPE_DECL, name, type);
9688 TYPE_NAME (type) = name;
9690 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9692 tree new_f = copy_node (f);
9693 DECL_CONTEXT (new_f) = type;
9694 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9695 TREE_CHAIN (new_f) = new_fields;
9696 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9697 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9698 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9699 &tcctx->cb, NULL);
9700 new_fields = new_f;
9701 tcctx->cb.decl_map->put (f, new_f);
9703 TYPE_FIELDS (type) = nreverse (new_fields);
9704 layout_type (type);
9705 return type;
9708 /* Create task copyfn. */
9710 static void
9711 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
9713 struct function *child_cfun;
9714 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9715 tree record_type, srecord_type, bind, list;
9716 bool record_needs_remap = false, srecord_needs_remap = false;
9717 splay_tree_node n;
9718 struct omp_taskcopy_context tcctx;
9719 location_t loc = gimple_location (task_stmt);
9721 child_fn = gimple_omp_task_copy_fn (task_stmt);
9722 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9723 gcc_assert (child_cfun->cfg == NULL);
9724 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9726 /* Reset DECL_CONTEXT on function arguments. */
9727 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9728 DECL_CONTEXT (t) = child_fn;
9730 /* Populate the function. */
9731 push_gimplify_context ();
9732 push_cfun (child_cfun);
9734 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9735 TREE_SIDE_EFFECTS (bind) = 1;
9736 list = NULL;
9737 DECL_SAVED_TREE (child_fn) = bind;
9738 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9740 /* Remap src and dst argument types if needed. */
9741 record_type = ctx->record_type;
9742 srecord_type = ctx->srecord_type;
9743 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9744 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9746 record_needs_remap = true;
9747 break;
9749 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9750 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9752 srecord_needs_remap = true;
9753 break;
9756 if (record_needs_remap || srecord_needs_remap)
9758 memset (&tcctx, '\0', sizeof (tcctx));
9759 tcctx.cb.src_fn = ctx->cb.src_fn;
9760 tcctx.cb.dst_fn = child_fn;
9761 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
9762 gcc_checking_assert (tcctx.cb.src_node);
9763 tcctx.cb.dst_node = tcctx.cb.src_node;
9764 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9765 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9766 tcctx.cb.eh_lp_nr = 0;
9767 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9768 tcctx.cb.decl_map = new hash_map<tree, tree>;
9769 tcctx.ctx = ctx;
9771 if (record_needs_remap)
9772 record_type = task_copyfn_remap_type (&tcctx, record_type);
9773 if (srecord_needs_remap)
9774 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9776 else
9777 tcctx.cb.decl_map = NULL;
9779 arg = DECL_ARGUMENTS (child_fn);
9780 TREE_TYPE (arg) = build_pointer_type (record_type);
9781 sarg = DECL_CHAIN (arg);
9782 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9784 /* First pass: initialize temporaries used in record_type and srecord_type
9785 sizes and field offsets. */
9786 if (tcctx.cb.decl_map)
9787 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9788 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9790 tree *p;
9792 decl = OMP_CLAUSE_DECL (c);
9793 p = tcctx.cb.decl_map->get (decl);
9794 if (p == NULL)
9795 continue;
9796 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9797 sf = (tree) n->value;
9798 sf = *tcctx.cb.decl_map->get (sf);
9799 src = build_simple_mem_ref_loc (loc, sarg);
9800 src = omp_build_component_ref (src, sf);
9801 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9802 append_to_statement_list (t, &list);
9805 /* Second pass: copy shared var pointers and copy construct non-VLA
9806 firstprivate vars. */
9807 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9808 switch (OMP_CLAUSE_CODE (c))
9810 case OMP_CLAUSE_SHARED:
9811 decl = OMP_CLAUSE_DECL (c);
9812 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9813 if (n == NULL)
9814 break;
9815 f = (tree) n->value;
9816 if (tcctx.cb.decl_map)
9817 f = *tcctx.cb.decl_map->get (f);
9818 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9819 sf = (tree) n->value;
9820 if (tcctx.cb.decl_map)
9821 sf = *tcctx.cb.decl_map->get (sf);
9822 src = build_simple_mem_ref_loc (loc, sarg);
9823 src = omp_build_component_ref (src, sf);
9824 dst = build_simple_mem_ref_loc (loc, arg);
9825 dst = omp_build_component_ref (dst, f);
9826 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9827 append_to_statement_list (t, &list);
9828 break;
9829 case OMP_CLAUSE_FIRSTPRIVATE:
9830 decl = OMP_CLAUSE_DECL (c);
9831 if (is_variable_sized (decl))
9832 break;
9833 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9834 if (n == NULL)
9835 break;
9836 f = (tree) n->value;
9837 if (tcctx.cb.decl_map)
9838 f = *tcctx.cb.decl_map->get (f);
9839 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9840 if (n != NULL)
9842 sf = (tree) n->value;
9843 if (tcctx.cb.decl_map)
9844 sf = *tcctx.cb.decl_map->get (sf);
9845 src = build_simple_mem_ref_loc (loc, sarg);
9846 src = omp_build_component_ref (src, sf);
9847 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9848 src = build_simple_mem_ref_loc (loc, src);
9850 else
9851 src = decl;
9852 dst = build_simple_mem_ref_loc (loc, arg);
9853 dst = omp_build_component_ref (dst, f);
9854 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9855 append_to_statement_list (t, &list);
9856 break;
9857 case OMP_CLAUSE_PRIVATE:
9858 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9859 break;
9860 decl = OMP_CLAUSE_DECL (c);
9861 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9862 f = (tree) n->value;
9863 if (tcctx.cb.decl_map)
9864 f = *tcctx.cb.decl_map->get (f);
9865 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9866 if (n != NULL)
9868 sf = (tree) n->value;
9869 if (tcctx.cb.decl_map)
9870 sf = *tcctx.cb.decl_map->get (sf);
9871 src = build_simple_mem_ref_loc (loc, sarg);
9872 src = omp_build_component_ref (src, sf);
9873 if (use_pointer_for_field (decl, NULL))
9874 src = build_simple_mem_ref_loc (loc, src);
9876 else
9877 src = decl;
9878 dst = build_simple_mem_ref_loc (loc, arg);
9879 dst = omp_build_component_ref (dst, f);
9880 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9881 append_to_statement_list (t, &list);
9882 break;
9883 default:
9884 break;
9887 /* Last pass: handle VLA firstprivates. */
9888 if (tcctx.cb.decl_map)
9889 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9890 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9892 tree ind, ptr, df;
9894 decl = OMP_CLAUSE_DECL (c);
9895 if (!is_variable_sized (decl))
9896 continue;
9897 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9898 if (n == NULL)
9899 continue;
9900 f = (tree) n->value;
9901 f = *tcctx.cb.decl_map->get (f);
9902 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9903 ind = DECL_VALUE_EXPR (decl);
9904 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9905 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9906 n = splay_tree_lookup (ctx->sfield_map,
9907 (splay_tree_key) TREE_OPERAND (ind, 0));
9908 sf = (tree) n->value;
9909 sf = *tcctx.cb.decl_map->get (sf);
9910 src = build_simple_mem_ref_loc (loc, sarg);
9911 src = omp_build_component_ref (src, sf);
9912 src = build_simple_mem_ref_loc (loc, src);
9913 dst = build_simple_mem_ref_loc (loc, arg);
9914 dst = omp_build_component_ref (dst, f);
9915 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9916 append_to_statement_list (t, &list);
9917 n = splay_tree_lookup (ctx->field_map,
9918 (splay_tree_key) TREE_OPERAND (ind, 0));
9919 df = (tree) n->value;
9920 df = *tcctx.cb.decl_map->get (df);
9921 ptr = build_simple_mem_ref_loc (loc, arg);
9922 ptr = omp_build_component_ref (ptr, df);
9923 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9924 build_fold_addr_expr_loc (loc, dst));
9925 append_to_statement_list (t, &list);
9928 t = build1 (RETURN_EXPR, void_type_node, NULL);
9929 append_to_statement_list (t, &list);
9931 if (tcctx.cb.decl_map)
9932 delete tcctx.cb.decl_map;
9933 pop_gimplify_context (NULL);
9934 BIND_EXPR_BODY (bind) = list;
9935 pop_cfun ();
9938 static void
9939 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9941 tree c, clauses;
9942 gimple g;
9943 size_t n_in = 0, n_out = 0, idx = 2, i;
9945 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9946 OMP_CLAUSE_DEPEND);
9947 gcc_assert (clauses);
9948 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9949 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9950 switch (OMP_CLAUSE_DEPEND_KIND (c))
9952 case OMP_CLAUSE_DEPEND_IN:
9953 n_in++;
9954 break;
9955 case OMP_CLAUSE_DEPEND_OUT:
9956 case OMP_CLAUSE_DEPEND_INOUT:
9957 n_out++;
9958 break;
9959 default:
9960 gcc_unreachable ();
9962 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9963 tree array = create_tmp_var (type, NULL);
9964 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9965 NULL_TREE);
9966 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9967 gimple_seq_add_stmt (iseq, g);
9968 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9969 NULL_TREE);
9970 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9971 gimple_seq_add_stmt (iseq, g);
9972 for (i = 0; i < 2; i++)
9974 if ((i ? n_in : n_out) == 0)
9975 continue;
9976 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9977 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9978 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9980 tree t = OMP_CLAUSE_DECL (c);
9981 t = fold_convert (ptr_type_node, t);
9982 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9983 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9984 NULL_TREE, NULL_TREE);
9985 g = gimple_build_assign (r, t);
9986 gimple_seq_add_stmt (iseq, g);
9989 tree *p = gimple_omp_task_clauses_ptr (stmt);
9990 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9991 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9992 OMP_CLAUSE_CHAIN (c) = *p;
9993 *p = c;
9994 tree clobber = build_constructor (type, NULL);
9995 TREE_THIS_VOLATILE (clobber) = 1;
9996 g = gimple_build_assign (array, clobber);
9997 gimple_seq_add_stmt (oseq, g);
10000 /* Lower the OpenMP parallel or task directive in the current statement
10001 in GSI_P. CTX holds context information for the directive. */
10003 static void
10004 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10006 tree clauses;
10007 tree child_fn, t;
10008 gimple stmt = gsi_stmt (*gsi_p);
10009 gbind *par_bind, *bind, *dep_bind = NULL;
10010 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
10011 location_t loc = gimple_location (stmt);
10013 clauses = gimple_omp_taskreg_clauses (stmt);
10014 par_bind
10015 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
10016 par_body = gimple_bind_body (par_bind);
10017 child_fn = ctx->cb.dst_fn;
10018 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
10019 && !gimple_omp_parallel_combined_p (stmt))
10021 struct walk_stmt_info wi;
10022 int ws_num = 0;
10024 memset (&wi, 0, sizeof (wi));
10025 wi.info = &ws_num;
10026 wi.val_only = true;
10027 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
10028 if (ws_num == 1)
10029 gimple_omp_parallel_set_combined_p (stmt, true);
10031 gimple_seq dep_ilist = NULL;
10032 gimple_seq dep_olist = NULL;
10033 if (gimple_code (stmt) == GIMPLE_OMP_TASK
10034 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
10036 push_gimplify_context ();
10037 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
10038 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
10041 if (ctx->srecord_type)
10042 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
10044 push_gimplify_context ();
10046 par_olist = NULL;
10047 par_ilist = NULL;
10048 par_rlist = NULL;
10049 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
10050 lower_omp (&par_body, ctx);
10051 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
10052 lower_reduction_clauses (clauses, &par_rlist, ctx);
10054 /* Declare all the variables created by mapping and the variables
10055 declared in the scope of the parallel body. */
10056 record_vars_into (ctx->block_vars, child_fn);
10057 record_vars_into (gimple_bind_vars (par_bind), child_fn);
10059 if (ctx->record_type)
10061 ctx->sender_decl
10062 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
10063 : ctx->record_type, ".omp_data_o");
10064 DECL_NAMELESS (ctx->sender_decl) = 1;
10065 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10066 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
10069 olist = NULL;
10070 ilist = NULL;
10071 lower_send_clauses (clauses, &ilist, &olist, ctx);
10072 lower_send_shared_vars (&ilist, &olist, ctx);
10074 if (ctx->record_type)
10076 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
10077 TREE_THIS_VOLATILE (clobber) = 1;
10078 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10079 clobber));
10082 /* Once all the expansions are done, sequence all the different
10083 fragments inside gimple_omp_body. */
10085 new_body = NULL;
10087 if (ctx->record_type)
10089 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10090 /* fixup_child_record_type might have changed receiver_decl's type. */
10091 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10092 gimple_seq_add_stmt (&new_body,
10093 gimple_build_assign (ctx->receiver_decl, t));
10096 gimple_seq_add_seq (&new_body, par_ilist);
10097 gimple_seq_add_seq (&new_body, par_body);
10098 gimple_seq_add_seq (&new_body, par_rlist);
10099 if (ctx->cancellable)
10100 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10101 gimple_seq_add_seq (&new_body, par_olist);
10102 new_body = maybe_catch_exception (new_body);
10103 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10104 gimple_omp_set_body (stmt, new_body);
10106 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
10107 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
10108 gimple_bind_add_seq (bind, ilist);
10109 gimple_bind_add_stmt (bind, stmt);
10110 gimple_bind_add_seq (bind, olist);
10112 pop_gimplify_context (NULL);
10114 if (dep_bind)
10116 gimple_bind_add_seq (dep_bind, dep_ilist);
10117 gimple_bind_add_stmt (dep_bind, bind);
10118 gimple_bind_add_seq (dep_bind, dep_olist);
10119 pop_gimplify_context (dep_bind);
10123 /* Lower the OpenMP target directive in the current statement
10124 in GSI_P. CTX holds context information for the directive. */
10126 static void
10127 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10129 tree clauses;
10130 tree child_fn, t, c;
10131 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
10132 gbind *tgt_bind = NULL, *bind;
10133 gimple_seq tgt_body = NULL, olist, ilist, new_body;
10134 location_t loc = gimple_location (stmt);
10135 int kind = gimple_omp_target_kind (stmt);
10136 unsigned int map_cnt = 0;
10138 clauses = gimple_omp_target_clauses (stmt);
10139 if (kind == GF_OMP_TARGET_KIND_REGION)
10141 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
10142 tgt_body = gimple_bind_body (tgt_bind);
10144 else if (kind == GF_OMP_TARGET_KIND_DATA)
10145 tgt_body = gimple_omp_body (stmt);
10146 child_fn = ctx->cb.dst_fn;
10148 push_gimplify_context ();
10150 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10151 switch (OMP_CLAUSE_CODE (c))
10153 tree var, x;
10155 default:
10156 break;
10157 case OMP_CLAUSE_MAP:
10158 case OMP_CLAUSE_TO:
10159 case OMP_CLAUSE_FROM:
10160 var = OMP_CLAUSE_DECL (c);
10161 if (!DECL_P (var))
10163 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10164 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10165 map_cnt++;
10166 continue;
10169 if (DECL_SIZE (var)
10170 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
10172 tree var2 = DECL_VALUE_EXPR (var);
10173 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
10174 var2 = TREE_OPERAND (var2, 0);
10175 gcc_assert (DECL_P (var2));
10176 var = var2;
10179 if (!maybe_lookup_field (var, ctx))
10180 continue;
10182 if (kind == GF_OMP_TARGET_KIND_REGION)
10184 x = build_receiver_ref (var, true, ctx);
10185 tree new_var = lookup_decl (var, ctx);
10186 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10187 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10188 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10189 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
10190 x = build_simple_mem_ref (x);
10191 SET_DECL_VALUE_EXPR (new_var, x);
10192 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
10194 map_cnt++;
10197 if (kind == GF_OMP_TARGET_KIND_REGION)
10199 target_nesting_level++;
10200 lower_omp (&tgt_body, ctx);
10201 target_nesting_level--;
10203 else if (kind == GF_OMP_TARGET_KIND_DATA)
10204 lower_omp (&tgt_body, ctx);
10206 if (kind == GF_OMP_TARGET_KIND_REGION)
10208 /* Declare all the variables created by mapping and the variables
10209 declared in the scope of the target body. */
10210 record_vars_into (ctx->block_vars, child_fn);
10211 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
10214 olist = NULL;
10215 ilist = NULL;
10216 if (ctx->record_type)
10218 ctx->sender_decl
10219 = create_tmp_var (ctx->record_type, ".omp_data_arr");
10220 DECL_NAMELESS (ctx->sender_decl) = 1;
10221 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10222 t = make_tree_vec (3);
10223 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
10224 TREE_VEC_ELT (t, 1)
10225 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
10226 ".omp_data_sizes");
10227 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
10228 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
10229 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
10230 TREE_VEC_ELT (t, 2)
10231 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
10232 map_cnt),
10233 ".omp_data_kinds");
10234 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
10235 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
10236 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
10237 gimple_omp_target_set_data_arg (stmt, t);
10239 vec<constructor_elt, va_gc> *vsize;
10240 vec<constructor_elt, va_gc> *vkind;
10241 vec_alloc (vsize, map_cnt);
10242 vec_alloc (vkind, map_cnt);
10243 unsigned int map_idx = 0;
10245 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10246 switch (OMP_CLAUSE_CODE (c))
10248 tree ovar, nc;
10250 default:
10251 break;
10252 case OMP_CLAUSE_MAP:
10253 case OMP_CLAUSE_TO:
10254 case OMP_CLAUSE_FROM:
10255 nc = c;
10256 ovar = OMP_CLAUSE_DECL (c);
10257 if (!DECL_P (ovar))
10259 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10260 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10262 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
10263 == get_base_address (ovar));
10264 nc = OMP_CLAUSE_CHAIN (c);
10265 ovar = OMP_CLAUSE_DECL (nc);
10267 else
10269 tree x = build_sender_ref (ovar, ctx);
10270 tree v
10271 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
10272 gimplify_assign (x, v, &ilist);
10273 nc = NULL_TREE;
10276 else
10278 if (DECL_SIZE (ovar)
10279 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
10281 tree ovar2 = DECL_VALUE_EXPR (ovar);
10282 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
10283 ovar2 = TREE_OPERAND (ovar2, 0);
10284 gcc_assert (DECL_P (ovar2));
10285 ovar = ovar2;
10287 if (!maybe_lookup_field (ovar, ctx))
10288 continue;
10291 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
10292 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
10293 talign = DECL_ALIGN_UNIT (ovar);
10294 if (nc)
10296 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
10297 tree x = build_sender_ref (ovar, ctx);
10298 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10299 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10300 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10301 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
10303 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10304 tree avar
10305 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
10306 mark_addressable (avar);
10307 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
10308 talign = DECL_ALIGN_UNIT (avar);
10309 avar = build_fold_addr_expr (avar);
10310 gimplify_assign (x, avar, &ilist);
10312 else if (is_gimple_reg (var))
10314 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10315 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
10316 mark_addressable (avar);
10317 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
10318 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
10319 gimplify_assign (avar, var, &ilist);
10320 avar = build_fold_addr_expr (avar);
10321 gimplify_assign (x, avar, &ilist);
10322 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
10323 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
10324 && !TYPE_READONLY (TREE_TYPE (var)))
10326 x = build_sender_ref (ovar, ctx);
10327 x = build_simple_mem_ref (x);
10328 gimplify_assign (var, x, &olist);
10331 else
10333 var = build_fold_addr_expr (var);
10334 gimplify_assign (x, var, &ilist);
10337 tree s = OMP_CLAUSE_SIZE (c);
10338 if (s == NULL_TREE)
10339 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
10340 s = fold_convert (size_type_node, s);
10341 tree purpose = size_int (map_idx++);
10342 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
10343 if (TREE_CODE (s) != INTEGER_CST)
10344 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
10346 unsigned char tkind = 0;
10347 switch (OMP_CLAUSE_CODE (c))
10349 case OMP_CLAUSE_MAP:
10350 tkind = OMP_CLAUSE_MAP_KIND (c);
10351 break;
10352 case OMP_CLAUSE_TO:
10353 tkind = OMP_CLAUSE_MAP_TO;
10354 break;
10355 case OMP_CLAUSE_FROM:
10356 tkind = OMP_CLAUSE_MAP_FROM;
10357 break;
10358 default:
10359 gcc_unreachable ();
10361 talign = ceil_log2 (talign);
10362 tkind |= talign << 3;
10363 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
10364 build_int_cst (unsigned_char_type_node,
10365 tkind));
10366 if (nc && nc != c)
10367 c = nc;
10370 gcc_assert (map_idx == map_cnt);
10372 DECL_INITIAL (TREE_VEC_ELT (t, 1))
10373 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
10374 DECL_INITIAL (TREE_VEC_ELT (t, 2))
10375 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
10376 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
10378 gimple_seq initlist = NULL;
10379 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
10380 TREE_VEC_ELT (t, 1)),
10381 &initlist, true, NULL_TREE);
10382 gimple_seq_add_seq (&ilist, initlist);
10384 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
10385 NULL);
10386 TREE_THIS_VOLATILE (clobber) = 1;
10387 gimple_seq_add_stmt (&olist,
10388 gimple_build_assign (TREE_VEC_ELT (t, 1),
10389 clobber));
10392 tree clobber = build_constructor (ctx->record_type, NULL);
10393 TREE_THIS_VOLATILE (clobber) = 1;
10394 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10395 clobber));
10398 /* Once all the expansions are done, sequence all the different
10399 fragments inside gimple_omp_body. */
10401 new_body = NULL;
10403 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
10405 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10406 /* fixup_child_record_type might have changed receiver_decl's type. */
10407 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10408 gimple_seq_add_stmt (&new_body,
10409 gimple_build_assign (ctx->receiver_decl, t));
10412 if (kind == GF_OMP_TARGET_KIND_REGION)
10414 gimple_seq_add_seq (&new_body, tgt_body);
10415 new_body = maybe_catch_exception (new_body);
10417 else if (kind == GF_OMP_TARGET_KIND_DATA)
10418 new_body = tgt_body;
10419 if (kind != GF_OMP_TARGET_KIND_UPDATE)
10421 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10422 gimple_omp_set_body (stmt, new_body);
10425 bind = gimple_build_bind (NULL, NULL,
10426 tgt_bind ? gimple_bind_block (tgt_bind)
10427 : NULL_TREE);
10428 gsi_replace (gsi_p, bind, true);
10429 gimple_bind_add_seq (bind, ilist);
10430 gimple_bind_add_stmt (bind, stmt);
10431 gimple_bind_add_seq (bind, olist);
10433 pop_gimplify_context (NULL);
10436 /* Expand code for an OpenMP teams directive. */
10438 static void
10439 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10441 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
10442 push_gimplify_context ();
10444 tree block = make_node (BLOCK);
10445 gbind *bind = gimple_build_bind (NULL, NULL, block);
10446 gsi_replace (gsi_p, bind, true);
10447 gimple_seq bind_body = NULL;
10448 gimple_seq dlist = NULL;
10449 gimple_seq olist = NULL;
10451 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10452 OMP_CLAUSE_NUM_TEAMS);
10453 if (num_teams == NULL_TREE)
10454 num_teams = build_int_cst (unsigned_type_node, 0);
10455 else
10457 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
10458 num_teams = fold_convert (unsigned_type_node, num_teams);
10459 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
10461 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10462 OMP_CLAUSE_THREAD_LIMIT);
10463 if (thread_limit == NULL_TREE)
10464 thread_limit = build_int_cst (unsigned_type_node, 0);
10465 else
10467 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10468 thread_limit = fold_convert (unsigned_type_node, thread_limit);
10469 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
10470 fb_rvalue);
10473 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
10474 &bind_body, &dlist, ctx, NULL);
10475 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
10476 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
10477 gimple_seq_add_stmt (&bind_body, teams_stmt);
10479 location_t loc = gimple_location (teams_stmt);
10480 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
10481 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10482 gimple_set_location (call, loc);
10483 gimple_seq_add_stmt (&bind_body, call);
10485 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10486 gimple_omp_set_body (teams_stmt, NULL);
10487 gimple_seq_add_seq (&bind_body, olist);
10488 gimple_seq_add_seq (&bind_body, dlist);
10489 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10490 gimple_bind_set_body (bind, bind_body);
10492 pop_gimplify_context (bind);
10494 gimple_bind_append_vars (bind, ctx->block_vars);
10495 BLOCK_VARS (block) = ctx->block_vars;
10496 if (BLOCK_VARS (block))
10497 TREE_USED (block) = 1;
10501 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10502 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10503 of OpenMP context, but with task_shared_vars set. */
10505 static tree
10506 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10507 void *data)
10509 tree t = *tp;
10511 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10512 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
10513 return t;
10515 if (task_shared_vars
10516 && DECL_P (t)
10517 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10518 return t;
10520 /* If a global variable has been privatized, TREE_CONSTANT on
10521 ADDR_EXPR might be wrong. */
10522 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10523 recompute_tree_invariant_for_addr_expr (t);
10525 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10526 return NULL_TREE;
10529 static void
10530 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10532 gimple stmt = gsi_stmt (*gsi_p);
10533 struct walk_stmt_info wi;
10534 gcall *call_stmt;
10536 if (gimple_has_location (stmt))
10537 input_location = gimple_location (stmt);
10539 if (task_shared_vars)
10540 memset (&wi, '\0', sizeof (wi));
10542 /* If we have issued syntax errors, avoid doing any heavy lifting.
10543 Just replace the OpenMP directives with a NOP to avoid
10544 confusing RTL expansion. */
10545 if (seen_error () && is_gimple_omp (stmt))
10547 gsi_replace (gsi_p, gimple_build_nop (), true);
10548 return;
10551 switch (gimple_code (stmt))
10553 case GIMPLE_COND:
10555 gcond *cond_stmt = as_a <gcond *> (stmt);
10556 if ((ctx || task_shared_vars)
10557 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
10558 lower_omp_regimplify_p,
10559 ctx ? NULL : &wi, NULL)
10560 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
10561 lower_omp_regimplify_p,
10562 ctx ? NULL : &wi, NULL)))
10563 gimple_regimplify_operands (cond_stmt, gsi_p);
10565 break;
10566 case GIMPLE_CATCH:
10567 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
10568 break;
10569 case GIMPLE_EH_FILTER:
10570 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10571 break;
10572 case GIMPLE_TRY:
10573 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10574 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10575 break;
10576 case GIMPLE_TRANSACTION:
10577 lower_omp (gimple_transaction_body_ptr (
10578 as_a <gtransaction *> (stmt)),
10579 ctx);
10580 break;
10581 case GIMPLE_BIND:
10582 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
10583 break;
10584 case GIMPLE_OMP_PARALLEL:
10585 case GIMPLE_OMP_TASK:
10586 ctx = maybe_lookup_ctx (stmt);
10587 gcc_assert (ctx);
10588 if (ctx->cancellable)
10589 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10590 lower_omp_taskreg (gsi_p, ctx);
10591 break;
10592 case GIMPLE_OMP_FOR:
10593 ctx = maybe_lookup_ctx (stmt);
10594 gcc_assert (ctx);
10595 if (ctx->cancellable)
10596 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10597 lower_omp_for (gsi_p, ctx);
10598 break;
10599 case GIMPLE_OMP_SECTIONS:
10600 ctx = maybe_lookup_ctx (stmt);
10601 gcc_assert (ctx);
10602 if (ctx->cancellable)
10603 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10604 lower_omp_sections (gsi_p, ctx);
10605 break;
10606 case GIMPLE_OMP_SINGLE:
10607 ctx = maybe_lookup_ctx (stmt);
10608 gcc_assert (ctx);
10609 lower_omp_single (gsi_p, ctx);
10610 break;
10611 case GIMPLE_OMP_MASTER:
10612 ctx = maybe_lookup_ctx (stmt);
10613 gcc_assert (ctx);
10614 lower_omp_master (gsi_p, ctx);
10615 break;
10616 case GIMPLE_OMP_TASKGROUP:
10617 ctx = maybe_lookup_ctx (stmt);
10618 gcc_assert (ctx);
10619 lower_omp_taskgroup (gsi_p, ctx);
10620 break;
10621 case GIMPLE_OMP_ORDERED:
10622 ctx = maybe_lookup_ctx (stmt);
10623 gcc_assert (ctx);
10624 lower_omp_ordered (gsi_p, ctx);
10625 break;
10626 case GIMPLE_OMP_CRITICAL:
10627 ctx = maybe_lookup_ctx (stmt);
10628 gcc_assert (ctx);
10629 lower_omp_critical (gsi_p, ctx);
10630 break;
10631 case GIMPLE_OMP_ATOMIC_LOAD:
10632 if ((ctx || task_shared_vars)
10633 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
10634 as_a <gomp_atomic_load *> (stmt)),
10635 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10636 gimple_regimplify_operands (stmt, gsi_p);
10637 break;
10638 case GIMPLE_OMP_TARGET:
10639 ctx = maybe_lookup_ctx (stmt);
10640 gcc_assert (ctx);
10641 lower_omp_target (gsi_p, ctx);
10642 break;
10643 case GIMPLE_OMP_TEAMS:
10644 ctx = maybe_lookup_ctx (stmt);
10645 gcc_assert (ctx);
10646 lower_omp_teams (gsi_p, ctx);
10647 break;
10648 case GIMPLE_CALL:
10649 tree fndecl;
10650 call_stmt = as_a <gcall *> (stmt);
10651 fndecl = gimple_call_fndecl (call_stmt);
10652 if (fndecl
10653 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10654 switch (DECL_FUNCTION_CODE (fndecl))
10656 case BUILT_IN_GOMP_BARRIER:
10657 if (ctx == NULL)
10658 break;
10659 /* FALLTHRU */
10660 case BUILT_IN_GOMP_CANCEL:
10661 case BUILT_IN_GOMP_CANCELLATION_POINT:
10662 omp_context *cctx;
10663 cctx = ctx;
10664 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10665 cctx = cctx->outer;
10666 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
10667 if (!cctx->cancellable)
10669 if (DECL_FUNCTION_CODE (fndecl)
10670 == BUILT_IN_GOMP_CANCELLATION_POINT)
10672 stmt = gimple_build_nop ();
10673 gsi_replace (gsi_p, stmt, false);
10675 break;
10677 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10679 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10680 gimple_call_set_fndecl (call_stmt, fndecl);
10681 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
10683 tree lhs;
10684 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
10685 gimple_call_set_lhs (call_stmt, lhs);
10686 tree fallthru_label;
10687 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10688 gimple g;
10689 g = gimple_build_label (fallthru_label);
10690 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10691 g = gimple_build_cond (NE_EXPR, lhs,
10692 fold_convert (TREE_TYPE (lhs),
10693 boolean_false_node),
10694 cctx->cancel_label, fallthru_label);
10695 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10696 break;
10697 default:
10698 break;
10700 /* FALLTHRU */
10701 default:
10702 if ((ctx || task_shared_vars)
10703 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10704 ctx ? NULL : &wi))
10706 /* Just remove clobbers, this should happen only if we have
10707 "privatized" local addressable variables in SIMD regions,
10708 the clobber isn't needed in that case and gimplifying address
10709 of the ARRAY_REF into a pointer and creating MEM_REF based
10710 clobber would create worse code than we get with the clobber
10711 dropped. */
10712 if (gimple_clobber_p (stmt))
10714 gsi_replace (gsi_p, gimple_build_nop (), true);
10715 break;
10717 gimple_regimplify_operands (stmt, gsi_p);
10719 break;
10723 static void
10724 lower_omp (gimple_seq *body, omp_context *ctx)
10726 location_t saved_location = input_location;
10727 gimple_stmt_iterator gsi;
10728 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10729 lower_omp_1 (&gsi, ctx);
10730 /* During gimplification, we have not always invoked fold_stmt
10731 (gimplify.c:maybe_fold_stmt); call it now. */
10732 if (target_nesting_level)
10733 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10734 fold_stmt (&gsi);
10735 input_location = saved_location;
10738 /* Main entry point. */
10740 static unsigned int
10741 execute_lower_omp (void)
10743 gimple_seq body;
10744 int i;
10745 omp_context *ctx;
10747 /* This pass always runs, to provide PROP_gimple_lomp.
10748 But there is nothing to do unless -fopenmp is given. */
10749 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10750 return 0;
10752 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10753 delete_omp_context);
10755 body = gimple_body (current_function_decl);
10756 scan_omp (&body, NULL);
10757 gcc_assert (taskreg_nesting_level == 0);
10758 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
10759 finish_taskreg_scan (ctx);
10760 taskreg_contexts.release ();
10762 if (all_contexts->root)
10764 if (task_shared_vars)
10765 push_gimplify_context ();
10766 lower_omp (&body, NULL);
10767 if (task_shared_vars)
10768 pop_gimplify_context (NULL);
10771 if (all_contexts)
10773 splay_tree_delete (all_contexts);
10774 all_contexts = NULL;
10776 BITMAP_FREE (task_shared_vars);
10777 return 0;
10780 namespace {
10782 const pass_data pass_data_lower_omp =
10784 GIMPLE_PASS, /* type */
10785 "omplower", /* name */
10786 OPTGROUP_NONE, /* optinfo_flags */
10787 TV_NONE, /* tv_id */
10788 PROP_gimple_any, /* properties_required */
10789 PROP_gimple_lomp, /* properties_provided */
10790 0, /* properties_destroyed */
10791 0, /* todo_flags_start */
10792 0, /* todo_flags_finish */
10795 class pass_lower_omp : public gimple_opt_pass
10797 public:
10798 pass_lower_omp (gcc::context *ctxt)
10799 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10802 /* opt_pass methods: */
10803 virtual unsigned int execute (function *) { return execute_lower_omp (); }
10805 }; // class pass_lower_omp
10807 } // anon namespace
10809 gimple_opt_pass *
10810 make_pass_lower_omp (gcc::context *ctxt)
10812 return new pass_lower_omp (ctxt);
10815 /* The following is a utility to diagnose OpenMP structured block violations.
10816 It is not part of the "omplower" pass, as that's invoked too late. It
10817 should be invoked by the respective front ends after gimplification. */
10819 static splay_tree all_labels;
10821 /* Check for mismatched contexts and generate an error if needed. Return
10822 true if an error is detected. */
10824 static bool
10825 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10826 gimple branch_ctx, gimple label_ctx)
10828 if (label_ctx == branch_ctx)
10829 return false;
10833 Previously we kept track of the label's entire context in diagnose_sb_[12]
10834 so we could traverse it and issue a correct "exit" or "enter" error
10835 message upon a structured block violation.
10837 We built the context by building a list with tree_cons'ing, but there is
10838 no easy counterpart in gimple tuples. It seems like far too much work
10839 for issuing exit/enter error messages. If someone really misses the
10840 distinct error message... patches welcome.
10843 #if 0
10844 /* Try to avoid confusing the user by producing and error message
10845 with correct "exit" or "enter" verbiage. We prefer "exit"
10846 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10847 if (branch_ctx == NULL)
10848 exit_p = false;
10849 else
10851 while (label_ctx)
10853 if (TREE_VALUE (label_ctx) == branch_ctx)
10855 exit_p = false;
10856 break;
10858 label_ctx = TREE_CHAIN (label_ctx);
10862 if (exit_p)
10863 error ("invalid exit from OpenMP structured block");
10864 else
10865 error ("invalid entry to OpenMP structured block");
10866 #endif
10868 bool cilkplus_block = false;
10869 if (flag_cilkplus)
10871 if ((branch_ctx
10872 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10873 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10874 || (label_ctx
10875 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10876 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10877 cilkplus_block = true;
10880 /* If it's obvious we have an invalid entry, be specific about the error. */
10881 if (branch_ctx == NULL)
10883 if (cilkplus_block)
10884 error ("invalid entry to Cilk Plus structured block");
10885 else
10886 error ("invalid entry to OpenMP structured block");
10888 else
10890 /* Otherwise, be vague and lazy, but efficient. */
10891 if (cilkplus_block)
10892 error ("invalid branch to/from a Cilk Plus structured block");
10893 else
10894 error ("invalid branch to/from an OpenMP structured block");
10897 gsi_replace (gsi_p, gimple_build_nop (), false);
10898 return true;
10901 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10902 where each label is found. */
10904 static tree
10905 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10906 struct walk_stmt_info *wi)
10908 gimple context = (gimple) wi->info;
10909 gimple inner_context;
10910 gimple stmt = gsi_stmt (*gsi_p);
10912 *handled_ops_p = true;
10914 switch (gimple_code (stmt))
10916 WALK_SUBSTMTS;
10918 case GIMPLE_OMP_PARALLEL:
10919 case GIMPLE_OMP_TASK:
10920 case GIMPLE_OMP_SECTIONS:
10921 case GIMPLE_OMP_SINGLE:
10922 case GIMPLE_OMP_SECTION:
10923 case GIMPLE_OMP_MASTER:
10924 case GIMPLE_OMP_ORDERED:
10925 case GIMPLE_OMP_CRITICAL:
10926 case GIMPLE_OMP_TARGET:
10927 case GIMPLE_OMP_TEAMS:
10928 case GIMPLE_OMP_TASKGROUP:
10929 /* The minimal context here is just the current OMP construct. */
10930 inner_context = stmt;
10931 wi->info = inner_context;
10932 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10933 wi->info = context;
10934 break;
10936 case GIMPLE_OMP_FOR:
10937 inner_context = stmt;
10938 wi->info = inner_context;
10939 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10940 walk them. */
10941 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10942 diagnose_sb_1, NULL, wi);
10943 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10944 wi->info = context;
10945 break;
10947 case GIMPLE_LABEL:
10948 splay_tree_insert (all_labels,
10949 (splay_tree_key) gimple_label_label (
10950 as_a <glabel *> (stmt)),
10951 (splay_tree_value) context);
10952 break;
10954 default:
10955 break;
10958 return NULL_TREE;
10961 /* Pass 2: Check each branch and see if its context differs from that of
10962 the destination label's context. */
10964 static tree
10965 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10966 struct walk_stmt_info *wi)
10968 gimple context = (gimple) wi->info;
10969 splay_tree_node n;
10970 gimple stmt = gsi_stmt (*gsi_p);
10972 *handled_ops_p = true;
10974 switch (gimple_code (stmt))
10976 WALK_SUBSTMTS;
10978 case GIMPLE_OMP_PARALLEL:
10979 case GIMPLE_OMP_TASK:
10980 case GIMPLE_OMP_SECTIONS:
10981 case GIMPLE_OMP_SINGLE:
10982 case GIMPLE_OMP_SECTION:
10983 case GIMPLE_OMP_MASTER:
10984 case GIMPLE_OMP_ORDERED:
10985 case GIMPLE_OMP_CRITICAL:
10986 case GIMPLE_OMP_TARGET:
10987 case GIMPLE_OMP_TEAMS:
10988 case GIMPLE_OMP_TASKGROUP:
10989 wi->info = stmt;
10990 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10991 wi->info = context;
10992 break;
10994 case GIMPLE_OMP_FOR:
10995 wi->info = stmt;
10996 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10997 walk them. */
10998 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10999 diagnose_sb_2, NULL, wi);
11000 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
11001 wi->info = context;
11002 break;
11004 case GIMPLE_COND:
11006 gcond *cond_stmt = as_a <gcond *> (stmt);
11007 tree lab = gimple_cond_true_label (cond_stmt);
11008 if (lab)
11010 n = splay_tree_lookup (all_labels,
11011 (splay_tree_key) lab);
11012 diagnose_sb_0 (gsi_p, context,
11013 n ? (gimple) n->value : NULL);
11015 lab = gimple_cond_false_label (cond_stmt);
11016 if (lab)
11018 n = splay_tree_lookup (all_labels,
11019 (splay_tree_key) lab);
11020 diagnose_sb_0 (gsi_p, context,
11021 n ? (gimple) n->value : NULL);
11024 break;
11026 case GIMPLE_GOTO:
11028 tree lab = gimple_goto_dest (stmt);
11029 if (TREE_CODE (lab) != LABEL_DECL)
11030 break;
11032 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
11033 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
11035 break;
11037 case GIMPLE_SWITCH:
11039 gswitch *switch_stmt = as_a <gswitch *> (stmt);
11040 unsigned int i;
11041 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
11043 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
11044 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
11045 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
11046 break;
11049 break;
11051 case GIMPLE_RETURN:
11052 diagnose_sb_0 (gsi_p, context, NULL);
11053 break;
11055 default:
11056 break;
11059 return NULL_TREE;
11062 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
11063 codes. */
11064 bool
11065 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
11066 int *region_idx)
11068 gimple last = last_stmt (bb);
11069 enum gimple_code code = gimple_code (last);
11070 struct omp_region *cur_region = *region;
11071 bool fallthru = false;
11073 switch (code)
11075 case GIMPLE_OMP_PARALLEL:
11076 case GIMPLE_OMP_TASK:
11077 case GIMPLE_OMP_FOR:
11078 case GIMPLE_OMP_SINGLE:
11079 case GIMPLE_OMP_TEAMS:
11080 case GIMPLE_OMP_MASTER:
11081 case GIMPLE_OMP_TASKGROUP:
11082 case GIMPLE_OMP_ORDERED:
11083 case GIMPLE_OMP_CRITICAL:
11084 case GIMPLE_OMP_SECTION:
11085 cur_region = new_omp_region (bb, code, cur_region);
11086 fallthru = true;
11087 break;
11089 case GIMPLE_OMP_TARGET:
11090 cur_region = new_omp_region (bb, code, cur_region);
11091 fallthru = true;
11092 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
11093 cur_region = cur_region->outer;
11094 break;
11096 case GIMPLE_OMP_SECTIONS:
11097 cur_region = new_omp_region (bb, code, cur_region);
11098 fallthru = true;
11099 break;
11101 case GIMPLE_OMP_SECTIONS_SWITCH:
11102 fallthru = false;
11103 break;
11105 case GIMPLE_OMP_ATOMIC_LOAD:
11106 case GIMPLE_OMP_ATOMIC_STORE:
11107 fallthru = true;
11108 break;
11110 case GIMPLE_OMP_RETURN:
11111 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
11112 somewhere other than the next block. This will be
11113 created later. */
11114 cur_region->exit = bb;
11115 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
11116 cur_region = cur_region->outer;
11117 break;
11119 case GIMPLE_OMP_CONTINUE:
11120 cur_region->cont = bb;
11121 switch (cur_region->type)
11123 case GIMPLE_OMP_FOR:
11124 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11125 succs edges as abnormal to prevent splitting
11126 them. */
11127 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
11128 /* Make the loopback edge. */
11129 make_edge (bb, single_succ (cur_region->entry),
11130 EDGE_ABNORMAL);
11132 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11133 corresponds to the case that the body of the loop
11134 is not executed at all. */
11135 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
11136 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
11137 fallthru = false;
11138 break;
11140 case GIMPLE_OMP_SECTIONS:
11141 /* Wire up the edges into and out of the nested sections. */
11143 basic_block switch_bb = single_succ (cur_region->entry);
11145 struct omp_region *i;
11146 for (i = cur_region->inner; i ; i = i->next)
11148 gcc_assert (i->type == GIMPLE_OMP_SECTION);
11149 make_edge (switch_bb, i->entry, 0);
11150 make_edge (i->exit, bb, EDGE_FALLTHRU);
11153 /* Make the loopback edge to the block with
11154 GIMPLE_OMP_SECTIONS_SWITCH. */
11155 make_edge (bb, switch_bb, 0);
11157 /* Make the edge from the switch to exit. */
11158 make_edge (switch_bb, bb->next_bb, 0);
11159 fallthru = false;
11161 break;
11163 default:
11164 gcc_unreachable ();
11166 break;
11168 default:
11169 gcc_unreachable ();
11172 if (*region != cur_region)
11174 *region = cur_region;
11175 if (cur_region)
11176 *region_idx = cur_region->entry->index;
11177 else
11178 *region_idx = 0;
11181 return fallthru;
11184 static unsigned int
11185 diagnose_omp_structured_block_errors (void)
11187 struct walk_stmt_info wi;
11188 gimple_seq body = gimple_body (current_function_decl);
11190 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
11192 memset (&wi, 0, sizeof (wi));
11193 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
11195 memset (&wi, 0, sizeof (wi));
11196 wi.want_locations = true;
11197 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
11199 gimple_set_body (current_function_decl, body);
11201 splay_tree_delete (all_labels);
11202 all_labels = NULL;
11204 return 0;
11207 namespace {
11209 const pass_data pass_data_diagnose_omp_blocks =
11211 GIMPLE_PASS, /* type */
11212 "*diagnose_omp_blocks", /* name */
11213 OPTGROUP_NONE, /* optinfo_flags */
11214 TV_NONE, /* tv_id */
11215 PROP_gimple_any, /* properties_required */
11216 0, /* properties_provided */
11217 0, /* properties_destroyed */
11218 0, /* todo_flags_start */
11219 0, /* todo_flags_finish */
11222 class pass_diagnose_omp_blocks : public gimple_opt_pass
11224 public:
11225 pass_diagnose_omp_blocks (gcc::context *ctxt)
11226 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
11229 /* opt_pass methods: */
11230 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
11231 virtual unsigned int execute (function *)
11233 return diagnose_omp_structured_block_errors ();
11236 }; // class pass_diagnose_omp_blocks
11238 } // anon namespace
11240 gimple_opt_pass *
11241 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
11243 return new pass_diagnose_omp_blocks (ctxt);
11246 /* SIMD clone supporting code. */
11248 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11249 of arguments to reserve space for. */
11251 static struct cgraph_simd_clone *
11252 simd_clone_struct_alloc (int nargs)
11254 struct cgraph_simd_clone *clone_info;
11255 size_t len = (sizeof (struct cgraph_simd_clone)
11256 + nargs * sizeof (struct cgraph_simd_clone_arg));
11257 clone_info = (struct cgraph_simd_clone *)
11258 ggc_internal_cleared_alloc (len);
11259 return clone_info;
11262 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11264 static inline void
11265 simd_clone_struct_copy (struct cgraph_simd_clone *to,
11266 struct cgraph_simd_clone *from)
11268 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
11269 + ((from->nargs - from->inbranch)
11270 * sizeof (struct cgraph_simd_clone_arg))));
11273 /* Return vector of parameter types of function FNDECL. This uses
11274 TYPE_ARG_TYPES if available, otherwise falls back to types of
11275 DECL_ARGUMENTS types. */
11277 vec<tree>
11278 simd_clone_vector_of_formal_parm_types (tree fndecl)
11280 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
11281 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
11282 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
11283 unsigned int i;
11284 tree arg;
11285 FOR_EACH_VEC_ELT (args, i, arg)
11286 args[i] = TREE_TYPE (args[i]);
11287 return args;
11290 /* Given a simd function in NODE, extract the simd specific
11291 information from the OMP clauses passed in CLAUSES, and return
11292 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11293 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11294 otherwise set to FALSE. */
11296 static struct cgraph_simd_clone *
11297 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
11298 bool *inbranch_specified)
11300 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
11301 tree t;
11302 int n;
11303 *inbranch_specified = false;
11305 n = args.length ();
11306 if (n > 0 && args.last () == void_type_node)
11307 n--;
11309 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11310 be cloned have a distinctive artificial label in addition to "omp
11311 declare simd". */
11312 bool cilk_clone
11313 = (flag_cilkplus
11314 && lookup_attribute ("cilk simd function",
11315 DECL_ATTRIBUTES (node->decl)));
11317 /* Allocate one more than needed just in case this is an in-branch
11318 clone which will require a mask argument. */
11319 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
11320 clone_info->nargs = n;
11321 clone_info->cilk_elemental = cilk_clone;
11323 if (!clauses)
11325 args.release ();
11326 return clone_info;
11328 clauses = TREE_VALUE (clauses);
11329 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
11330 return clone_info;
11332 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
11334 switch (OMP_CLAUSE_CODE (t))
11336 case OMP_CLAUSE_INBRANCH:
11337 clone_info->inbranch = 1;
11338 *inbranch_specified = true;
11339 break;
11340 case OMP_CLAUSE_NOTINBRANCH:
11341 clone_info->inbranch = 0;
11342 *inbranch_specified = true;
11343 break;
11344 case OMP_CLAUSE_SIMDLEN:
11345 clone_info->simdlen
11346 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
11347 break;
11348 case OMP_CLAUSE_LINEAR:
11350 tree decl = OMP_CLAUSE_DECL (t);
11351 tree step = OMP_CLAUSE_LINEAR_STEP (t);
11352 int argno = TREE_INT_CST_LOW (decl);
11353 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
11355 clone_info->args[argno].arg_type
11356 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
11357 clone_info->args[argno].linear_step = tree_to_shwi (step);
11358 gcc_assert (clone_info->args[argno].linear_step >= 0
11359 && clone_info->args[argno].linear_step < n);
11361 else
11363 if (POINTER_TYPE_P (args[argno]))
11364 step = fold_convert (ssizetype, step);
11365 if (!tree_fits_shwi_p (step))
11367 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11368 "ignoring large linear step");
11369 args.release ();
11370 return NULL;
11372 else if (integer_zerop (step))
11374 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11375 "ignoring zero linear step");
11376 args.release ();
11377 return NULL;
11379 else
11381 clone_info->args[argno].arg_type
11382 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
11383 clone_info->args[argno].linear_step = tree_to_shwi (step);
11386 break;
11388 case OMP_CLAUSE_UNIFORM:
11390 tree decl = OMP_CLAUSE_DECL (t);
11391 int argno = tree_to_uhwi (decl);
11392 clone_info->args[argno].arg_type
11393 = SIMD_CLONE_ARG_TYPE_UNIFORM;
11394 break;
11396 case OMP_CLAUSE_ALIGNED:
11398 tree decl = OMP_CLAUSE_DECL (t);
11399 int argno = tree_to_uhwi (decl);
11400 clone_info->args[argno].alignment
11401 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
11402 break;
11404 default:
11405 break;
11408 args.release ();
11409 return clone_info;
11412 /* Given a SIMD clone in NODE, calculate the characteristic data
11413 type and return the coresponding type. The characteristic data
11414 type is computed as described in the Intel Vector ABI. */
11416 static tree
11417 simd_clone_compute_base_data_type (struct cgraph_node *node,
11418 struct cgraph_simd_clone *clone_info)
11420 tree type = integer_type_node;
11421 tree fndecl = node->decl;
11423 /* a) For non-void function, the characteristic data type is the
11424 return type. */
11425 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
11426 type = TREE_TYPE (TREE_TYPE (fndecl));
11428 /* b) If the function has any non-uniform, non-linear parameters,
11429 then the characteristic data type is the type of the first
11430 such parameter. */
11431 else
11433 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
11434 for (unsigned int i = 0; i < clone_info->nargs; ++i)
11435 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
11437 type = map[i];
11438 break;
11440 map.release ();
11443 /* c) If the characteristic data type determined by a) or b) above
11444 is struct, union, or class type which is pass-by-value (except
11445 for the type that maps to the built-in complex data type), the
11446 characteristic data type is int. */
11447 if (RECORD_OR_UNION_TYPE_P (type)
11448 && !aggregate_value_p (type, NULL)
11449 && TREE_CODE (type) != COMPLEX_TYPE)
11450 return integer_type_node;
11452 /* d) If none of the above three classes is applicable, the
11453 characteristic data type is int. */
11455 return type;
11457 /* e) For Intel Xeon Phi native and offload compilation, if the
11458 resulting characteristic data type is 8-bit or 16-bit integer
11459 data type, the characteristic data type is int. */
11460 /* Well, we don't handle Xeon Phi yet. */
11463 static tree
11464 simd_clone_mangle (struct cgraph_node *node,
11465 struct cgraph_simd_clone *clone_info)
11467 char vecsize_mangle = clone_info->vecsize_mangle;
11468 char mask = clone_info->inbranch ? 'M' : 'N';
11469 unsigned int simdlen = clone_info->simdlen;
11470 unsigned int n;
11471 pretty_printer pp;
11473 gcc_assert (vecsize_mangle && simdlen);
11475 pp_string (&pp, "_ZGV");
11476 pp_character (&pp, vecsize_mangle);
11477 pp_character (&pp, mask);
11478 pp_decimal_int (&pp, simdlen);
11480 for (n = 0; n < clone_info->nargs; ++n)
11482 struct cgraph_simd_clone_arg arg = clone_info->args[n];
11484 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
11485 pp_character (&pp, 'u');
11486 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11488 gcc_assert (arg.linear_step != 0);
11489 pp_character (&pp, 'l');
11490 if (arg.linear_step > 1)
11491 pp_unsigned_wide_integer (&pp, arg.linear_step);
11492 else if (arg.linear_step < 0)
11494 pp_character (&pp, 'n');
11495 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
11496 arg.linear_step));
11499 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11501 pp_character (&pp, 's');
11502 pp_unsigned_wide_integer (&pp, arg.linear_step);
11504 else
11505 pp_character (&pp, 'v');
11506 if (arg.alignment)
11508 pp_character (&pp, 'a');
11509 pp_decimal_int (&pp, arg.alignment);
11513 pp_underscore (&pp);
11514 pp_string (&pp,
11515 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11516 const char *str = pp_formatted_text (&pp);
11518 /* If there already is a SIMD clone with the same mangled name, don't
11519 add another one. This can happen e.g. for
11520 #pragma omp declare simd
11521 #pragma omp declare simd simdlen(8)
11522 int foo (int, int);
11523 if the simdlen is assumed to be 8 for the first one, etc. */
11524 for (struct cgraph_node *clone = node->simd_clones; clone;
11525 clone = clone->simdclone->next_clone)
11526 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11527 str) == 0)
11528 return NULL_TREE;
11530 return get_identifier (str);
11533 /* Create a simd clone of OLD_NODE and return it. */
11535 static struct cgraph_node *
11536 simd_clone_create (struct cgraph_node *old_node)
11538 struct cgraph_node *new_node;
11539 if (old_node->definition)
11541 if (!old_node->has_gimple_body_p ())
11542 return NULL;
11543 old_node->get_body ();
11544 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
11545 false, NULL, NULL,
11546 "simdclone");
11548 else
11550 tree old_decl = old_node->decl;
11551 tree new_decl = copy_node (old_node->decl);
11552 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11553 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11554 SET_DECL_RTL (new_decl, NULL);
11555 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11556 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11557 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
11558 symtab->call_cgraph_insertion_hooks (new_node);
11560 if (new_node == NULL)
11561 return new_node;
11563 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11565 /* The function cgraph_function_versioning () will force the new
11566 symbol local. Undo this, and inherit external visability from
11567 the old node. */
11568 new_node->local.local = old_node->local.local;
11569 new_node->externally_visible = old_node->externally_visible;
11571 return new_node;
11574 /* Adjust the return type of the given function to its appropriate
11575 vector counterpart. Returns a simd array to be used throughout the
11576 function as a return value. */
11578 static tree
11579 simd_clone_adjust_return_type (struct cgraph_node *node)
11581 tree fndecl = node->decl;
11582 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11583 unsigned int veclen;
11584 tree t;
11586 /* Adjust the function return type. */
11587 if (orig_rettype == void_type_node)
11588 return NULL_TREE;
11589 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11590 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11591 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11592 veclen = node->simdclone->vecsize_int;
11593 else
11594 veclen = node->simdclone->vecsize_float;
11595 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11596 if (veclen > node->simdclone->simdlen)
11597 veclen = node->simdclone->simdlen;
11598 if (veclen == node->simdclone->simdlen)
11599 TREE_TYPE (TREE_TYPE (fndecl))
11600 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11601 node->simdclone->simdlen);
11602 else
11604 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11605 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11606 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11608 if (!node->definition)
11609 return NULL_TREE;
11611 t = DECL_RESULT (fndecl);
11612 /* Adjust the DECL_RESULT. */
11613 gcc_assert (TREE_TYPE (t) != void_type_node);
11614 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11615 relayout_decl (t);
11617 tree atype = build_array_type_nelts (orig_rettype,
11618 node->simdclone->simdlen);
11619 if (veclen != node->simdclone->simdlen)
11620 return build1 (VIEW_CONVERT_EXPR, atype, t);
11622 /* Set up a SIMD array to use as the return value. */
11623 tree retval = create_tmp_var_raw (atype, "retval");
11624 gimple_add_tmp_var (retval);
11625 return retval;
11628 /* Each vector argument has a corresponding array to be used locally
11629 as part of the eventual loop. Create such temporary array and
11630 return it.
11632 PREFIX is the prefix to be used for the temporary.
11634 TYPE is the inner element type.
11636 SIMDLEN is the number of elements. */
11638 static tree
11639 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11641 tree atype = build_array_type_nelts (type, simdlen);
11642 tree avar = create_tmp_var_raw (atype, prefix);
11643 gimple_add_tmp_var (avar);
11644 return avar;
11647 /* Modify the function argument types to their corresponding vector
11648 counterparts if appropriate. Also, create one array for each simd
11649 argument to be used locally when using the function arguments as
11650 part of the loop.
11652 NODE is the function whose arguments are to be adjusted.
11654 Returns an adjustment vector that will be filled describing how the
11655 argument types will be adjusted. */
11657 static ipa_parm_adjustment_vec
11658 simd_clone_adjust_argument_types (struct cgraph_node *node)
11660 vec<tree> args;
11661 ipa_parm_adjustment_vec adjustments;
11663 if (node->definition)
11664 args = ipa_get_vector_of_formal_parms (node->decl);
11665 else
11666 args = simd_clone_vector_of_formal_parm_types (node->decl);
11667 adjustments.create (args.length ());
11668 unsigned i, j, veclen;
11669 struct ipa_parm_adjustment adj;
11670 for (i = 0; i < node->simdclone->nargs; ++i)
11672 memset (&adj, 0, sizeof (adj));
11673 tree parm = args[i];
11674 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11675 adj.base_index = i;
11676 adj.base = parm;
11678 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11679 node->simdclone->args[i].orig_type = parm_type;
11681 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11683 /* No adjustment necessary for scalar arguments. */
11684 adj.op = IPA_PARM_OP_COPY;
11686 else
11688 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11689 veclen = node->simdclone->vecsize_int;
11690 else
11691 veclen = node->simdclone->vecsize_float;
11692 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11693 if (veclen > node->simdclone->simdlen)
11694 veclen = node->simdclone->simdlen;
11695 adj.arg_prefix = "simd";
11696 adj.type = build_vector_type (parm_type, veclen);
11697 node->simdclone->args[i].vector_type = adj.type;
11698 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11700 adjustments.safe_push (adj);
11701 if (j == veclen)
11703 memset (&adj, 0, sizeof (adj));
11704 adj.op = IPA_PARM_OP_NEW;
11705 adj.arg_prefix = "simd";
11706 adj.base_index = i;
11707 adj.type = node->simdclone->args[i].vector_type;
11711 if (node->definition)
11712 node->simdclone->args[i].simd_array
11713 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11714 parm_type, node->simdclone->simdlen);
11716 adjustments.safe_push (adj);
11719 if (node->simdclone->inbranch)
11721 tree base_type
11722 = simd_clone_compute_base_data_type (node->simdclone->origin,
11723 node->simdclone);
11725 memset (&adj, 0, sizeof (adj));
11726 adj.op = IPA_PARM_OP_NEW;
11727 adj.arg_prefix = "mask";
11729 adj.base_index = i;
11730 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11731 veclen = node->simdclone->vecsize_int;
11732 else
11733 veclen = node->simdclone->vecsize_float;
11734 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11735 if (veclen > node->simdclone->simdlen)
11736 veclen = node->simdclone->simdlen;
11737 adj.type = build_vector_type (base_type, veclen);
11738 adjustments.safe_push (adj);
11740 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11741 adjustments.safe_push (adj);
11743 /* We have previously allocated one extra entry for the mask. Use
11744 it and fill it. */
11745 struct cgraph_simd_clone *sc = node->simdclone;
11746 sc->nargs++;
11747 if (node->definition)
11749 sc->args[i].orig_arg
11750 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11751 sc->args[i].simd_array
11752 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11754 sc->args[i].orig_type = base_type;
11755 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11758 if (node->definition)
11759 ipa_modify_formal_parameters (node->decl, adjustments);
11760 else
11762 tree new_arg_types = NULL_TREE, new_reversed;
11763 bool last_parm_void = false;
11764 if (args.length () > 0 && args.last () == void_type_node)
11765 last_parm_void = true;
11767 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11768 j = adjustments.length ();
11769 for (i = 0; i < j; i++)
11771 struct ipa_parm_adjustment *adj = &adjustments[i];
11772 tree ptype;
11773 if (adj->op == IPA_PARM_OP_COPY)
11774 ptype = args[adj->base_index];
11775 else
11776 ptype = adj->type;
11777 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11779 new_reversed = nreverse (new_arg_types);
11780 if (last_parm_void)
11782 if (new_reversed)
11783 TREE_CHAIN (new_arg_types) = void_list_node;
11784 else
11785 new_reversed = void_list_node;
11788 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11789 TYPE_ARG_TYPES (new_type) = new_reversed;
11790 TREE_TYPE (node->decl) = new_type;
11792 adjustments.release ();
11794 args.release ();
11795 return adjustments;
11798 /* Initialize and copy the function arguments in NODE to their
11799 corresponding local simd arrays. Returns a fresh gimple_seq with
11800 the instruction sequence generated. */
11802 static gimple_seq
11803 simd_clone_init_simd_arrays (struct cgraph_node *node,
11804 ipa_parm_adjustment_vec adjustments)
11806 gimple_seq seq = NULL;
11807 unsigned i = 0, j = 0, k;
11809 for (tree arg = DECL_ARGUMENTS (node->decl);
11810 arg;
11811 arg = DECL_CHAIN (arg), i++, j++)
11813 if (adjustments[j].op == IPA_PARM_OP_COPY)
11814 continue;
11816 node->simdclone->args[i].vector_arg = arg;
11818 tree array = node->simdclone->args[i].simd_array;
11819 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11821 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11822 tree ptr = build_fold_addr_expr (array);
11823 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11824 build_int_cst (ptype, 0));
11825 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11826 gimplify_and_add (t, &seq);
11828 else
11830 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11831 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11832 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11834 tree ptr = build_fold_addr_expr (array);
11835 int elemsize;
11836 if (k)
11838 arg = DECL_CHAIN (arg);
11839 j++;
11841 elemsize
11842 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11843 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11844 build_int_cst (ptype, k * elemsize));
11845 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11846 gimplify_and_add (t, &seq);
11850 return seq;
11853 /* Callback info for ipa_simd_modify_stmt_ops below. */
11855 struct modify_stmt_info {
11856 ipa_parm_adjustment_vec adjustments;
11857 gimple stmt;
11858 /* True if the parent statement was modified by
11859 ipa_simd_modify_stmt_ops. */
11860 bool modified;
11863 /* Callback for walk_gimple_op.
11865 Adjust operands from a given statement as specified in the
11866 adjustments vector in the callback data. */
11868 static tree
11869 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11871 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11872 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11873 tree *orig_tp = tp;
11874 if (TREE_CODE (*tp) == ADDR_EXPR)
11875 tp = &TREE_OPERAND (*tp, 0);
11876 struct ipa_parm_adjustment *cand = NULL;
11877 if (TREE_CODE (*tp) == PARM_DECL)
11878 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11879 else
11881 if (TYPE_P (*tp))
11882 *walk_subtrees = 0;
11885 tree repl = NULL_TREE;
11886 if (cand)
11887 repl = unshare_expr (cand->new_decl);
11888 else
11890 if (tp != orig_tp)
11892 *walk_subtrees = 0;
11893 bool modified = info->modified;
11894 info->modified = false;
11895 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11896 if (!info->modified)
11898 info->modified = modified;
11899 return NULL_TREE;
11901 info->modified = modified;
11902 repl = *tp;
11904 else
11905 return NULL_TREE;
11908 if (tp != orig_tp)
11910 repl = build_fold_addr_expr (repl);
11911 gimple stmt;
11912 if (is_gimple_debug (info->stmt))
11914 tree vexpr = make_node (DEBUG_EXPR_DECL);
11915 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
11916 DECL_ARTIFICIAL (vexpr) = 1;
11917 TREE_TYPE (vexpr) = TREE_TYPE (repl);
11918 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
11919 repl = vexpr;
11921 else
11923 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl),
11924 NULL), repl);
11925 repl = gimple_assign_lhs (stmt);
11927 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11928 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11929 *orig_tp = repl;
11931 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11933 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11934 *tp = vce;
11936 else
11937 *tp = repl;
11939 info->modified = true;
11940 return NULL_TREE;
11943 /* Traverse the function body and perform all modifications as
11944 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11945 modified such that the replacement/reduction value will now be an
11946 offset into the corresponding simd_array.
11948 This function will replace all function argument uses with their
11949 corresponding simd array elements, and ajust the return values
11950 accordingly. */
11952 static void
11953 ipa_simd_modify_function_body (struct cgraph_node *node,
11954 ipa_parm_adjustment_vec adjustments,
11955 tree retval_array, tree iter)
11957 basic_block bb;
11958 unsigned int i, j, l;
11960 /* Re-use the adjustments array, but this time use it to replace
11961 every function argument use to an offset into the corresponding
11962 simd_array. */
11963 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11965 if (!node->simdclone->args[i].vector_arg)
11966 continue;
11968 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11969 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11970 adjustments[j].new_decl
11971 = build4 (ARRAY_REF,
11972 basetype,
11973 node->simdclone->args[i].simd_array,
11974 iter,
11975 NULL_TREE, NULL_TREE);
11976 if (adjustments[j].op == IPA_PARM_OP_NONE
11977 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11978 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11981 l = adjustments.length ();
11982 for (i = 1; i < num_ssa_names; i++)
11984 tree name = ssa_name (i);
11985 if (name
11986 && SSA_NAME_VAR (name)
11987 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11989 for (j = 0; j < l; j++)
11990 if (SSA_NAME_VAR (name) == adjustments[j].base
11991 && adjustments[j].new_decl)
11993 tree base_var;
11994 if (adjustments[j].new_ssa_base == NULL_TREE)
11996 base_var
11997 = copy_var_decl (adjustments[j].base,
11998 DECL_NAME (adjustments[j].base),
11999 TREE_TYPE (adjustments[j].base));
12000 adjustments[j].new_ssa_base = base_var;
12002 else
12003 base_var = adjustments[j].new_ssa_base;
12004 if (SSA_NAME_IS_DEFAULT_DEF (name))
12006 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12007 gimple_stmt_iterator gsi = gsi_after_labels (bb);
12008 tree new_decl = unshare_expr (adjustments[j].new_decl);
12009 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
12010 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
12011 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
12012 gimple stmt = gimple_build_assign (name, new_decl);
12013 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
12015 else
12016 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
12021 struct modify_stmt_info info;
12022 info.adjustments = adjustments;
12024 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
12026 gimple_stmt_iterator gsi;
12028 gsi = gsi_start_bb (bb);
12029 while (!gsi_end_p (gsi))
12031 gimple stmt = gsi_stmt (gsi);
12032 info.stmt = stmt;
12033 struct walk_stmt_info wi;
12035 memset (&wi, 0, sizeof (wi));
12036 info.modified = false;
12037 wi.info = &info;
12038 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
12040 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
12042 tree retval = gimple_return_retval (return_stmt);
12043 if (!retval)
12045 gsi_remove (&gsi, true);
12046 continue;
12049 /* Replace `return foo' with `retval_array[iter] = foo'. */
12050 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
12051 retval_array, iter, NULL, NULL);
12052 stmt = gimple_build_assign (ref, retval);
12053 gsi_replace (&gsi, stmt, true);
12054 info.modified = true;
12057 if (info.modified)
12059 update_stmt (stmt);
12060 if (maybe_clean_eh_stmt (stmt))
12061 gimple_purge_dead_eh_edges (gimple_bb (stmt));
12063 gsi_next (&gsi);
12068 /* Adjust the argument types in NODE to their appropriate vector
12069 counterparts. */
12071 static void
12072 simd_clone_adjust (struct cgraph_node *node)
12074 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
12076 targetm.simd_clone.adjust (node);
12078 tree retval = simd_clone_adjust_return_type (node);
12079 ipa_parm_adjustment_vec adjustments
12080 = simd_clone_adjust_argument_types (node);
12082 push_gimplify_context ();
12084 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
12086 /* Adjust all uses of vector arguments accordingly. Adjust all
12087 return values accordingly. */
12088 tree iter = create_tmp_var (unsigned_type_node, "iter");
12089 tree iter1 = make_ssa_name (iter, NULL);
12090 tree iter2 = make_ssa_name (iter, NULL);
12091 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
12093 /* Initialize the iteration variable. */
12094 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12095 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
12096 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
12097 /* Insert the SIMD array and iv initialization at function
12098 entry. */
12099 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
12101 pop_gimplify_context (NULL);
12103 /* Create a new BB right before the original exit BB, to hold the
12104 iteration increment and the condition/branch. */
12105 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
12106 basic_block incr_bb = create_empty_bb (orig_exit);
12107 add_bb_to_loop (incr_bb, body_bb->loop_father);
12108 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
12109 flag. Set it now to be a FALLTHRU_EDGE. */
12110 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
12111 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
12112 for (unsigned i = 0;
12113 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
12115 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
12116 redirect_edge_succ (e, incr_bb);
12118 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
12119 e->probability = REG_BR_PROB_BASE;
12120 gsi = gsi_last_bb (incr_bb);
12121 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
12122 build_int_cst (unsigned_type_node,
12123 1));
12124 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12126 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12127 struct loop *loop = alloc_loop ();
12128 cfun->has_force_vectorize_loops = true;
12129 loop->safelen = node->simdclone->simdlen;
12130 loop->force_vectorize = true;
12131 loop->header = body_bb;
12133 /* Branch around the body if the mask applies. */
12134 if (node->simdclone->inbranch)
12136 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
12137 tree mask_array
12138 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
12139 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
12140 tree aref = build4 (ARRAY_REF,
12141 TREE_TYPE (TREE_TYPE (mask_array)),
12142 mask_array, iter1,
12143 NULL, NULL);
12144 g = gimple_build_assign (mask, aref);
12145 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12146 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
12147 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
12149 aref = build1 (VIEW_CONVERT_EXPR,
12150 build_nonstandard_integer_type (bitsize, 0), mask);
12151 mask = make_ssa_name (TREE_TYPE (aref), NULL);
12152 g = gimple_build_assign (mask, aref);
12153 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12156 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
12157 NULL, NULL);
12158 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12159 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
12160 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
12163 /* Generate the condition. */
12164 g = gimple_build_cond (LT_EXPR,
12165 iter2,
12166 build_int_cst (unsigned_type_node,
12167 node->simdclone->simdlen),
12168 NULL, NULL);
12169 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12170 e = split_block (incr_bb, gsi_stmt (gsi));
12171 basic_block latch_bb = e->dest;
12172 basic_block new_exit_bb;
12173 new_exit_bb = split_block (latch_bb, NULL)->dest;
12174 loop->latch = latch_bb;
12176 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
12178 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
12179 /* The successor of incr_bb is already pointing to latch_bb; just
12180 change the flags.
12181 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12182 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
12184 gphi *phi = create_phi_node (iter1, body_bb);
12185 edge preheader_edge = find_edge (entry_bb, body_bb);
12186 edge latch_edge = single_succ_edge (latch_bb);
12187 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
12188 UNKNOWN_LOCATION);
12189 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12191 /* Generate the new return. */
12192 gsi = gsi_last_bb (new_exit_bb);
12193 if (retval
12194 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
12195 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
12196 retval = TREE_OPERAND (retval, 0);
12197 else if (retval)
12199 retval = build1 (VIEW_CONVERT_EXPR,
12200 TREE_TYPE (TREE_TYPE (node->decl)),
12201 retval);
12202 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
12203 false, GSI_CONTINUE_LINKING);
12205 g = gimple_build_return (retval);
12206 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12208 /* Handle aligned clauses by replacing default defs of the aligned
12209 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12210 lhs. Handle linear by adding PHIs. */
12211 for (unsigned i = 0; i < node->simdclone->nargs; i++)
12212 if (node->simdclone->args[i].alignment
12213 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
12214 && (node->simdclone->args[i].alignment
12215 & (node->simdclone->args[i].alignment - 1)) == 0
12216 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
12217 == POINTER_TYPE)
12219 unsigned int alignment = node->simdclone->args[i].alignment;
12220 tree orig_arg = node->simdclone->args[i].orig_arg;
12221 tree def = ssa_default_def (cfun, orig_arg);
12222 if (def && !has_zero_uses (def))
12224 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
12225 gimple_seq seq = NULL;
12226 bool need_cvt = false;
12227 gcall *call
12228 = gimple_build_call (fn, 2, def, size_int (alignment));
12229 g = call;
12230 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
12231 ptr_type_node))
12232 need_cvt = true;
12233 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
12234 gimple_call_set_lhs (g, t);
12235 gimple_seq_add_stmt_without_update (&seq, g);
12236 if (need_cvt)
12238 t = make_ssa_name (orig_arg, NULL);
12239 g = gimple_build_assign_with_ops (NOP_EXPR, t,
12240 gimple_call_lhs (g));
12241 gimple_seq_add_stmt_without_update (&seq, g);
12243 gsi_insert_seq_on_edge_immediate
12244 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
12246 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12247 int freq = compute_call_stmt_bb_frequency (current_function_decl,
12248 entry_bb);
12249 node->create_edge (cgraph_node::get_create (fn),
12250 call, entry_bb->count, freq);
12252 imm_use_iterator iter;
12253 use_operand_p use_p;
12254 gimple use_stmt;
12255 tree repl = gimple_get_lhs (g);
12256 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12257 if (is_gimple_debug (use_stmt) || use_stmt == call)
12258 continue;
12259 else
12260 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12261 SET_USE (use_p, repl);
12264 else if (node->simdclone->args[i].arg_type
12265 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12267 tree orig_arg = node->simdclone->args[i].orig_arg;
12268 tree def = ssa_default_def (cfun, orig_arg);
12269 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12270 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
12271 if (def && !has_zero_uses (def))
12273 iter1 = make_ssa_name (orig_arg, NULL);
12274 iter2 = make_ssa_name (orig_arg, NULL);
12275 phi = create_phi_node (iter1, body_bb);
12276 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
12277 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12278 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12279 ? PLUS_EXPR : POINTER_PLUS_EXPR;
12280 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12281 ? TREE_TYPE (orig_arg) : sizetype;
12282 tree addcst
12283 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
12284 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
12285 gsi = gsi_last_bb (incr_bb);
12286 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12288 imm_use_iterator iter;
12289 use_operand_p use_p;
12290 gimple use_stmt;
12291 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12292 if (use_stmt == phi)
12293 continue;
12294 else
12295 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12296 SET_USE (use_p, iter1);
12300 calculate_dominance_info (CDI_DOMINATORS);
12301 add_loop (loop, loop->header->loop_father);
12302 update_ssa (TODO_update_ssa);
12304 pop_cfun ();
12307 /* If the function in NODE is tagged as an elemental SIMD function,
12308 create the appropriate SIMD clones. */
12310 static void
12311 expand_simd_clones (struct cgraph_node *node)
12313 tree attr = lookup_attribute ("omp declare simd",
12314 DECL_ATTRIBUTES (node->decl));
12315 if (attr == NULL_TREE
12316 || node->global.inlined_to
12317 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
12318 return;
12320 /* Ignore
12321 #pragma omp declare simd
12322 extern int foo ();
12323 in C, there we don't know the argument types at all. */
12324 if (!node->definition
12325 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
12326 return;
12330 /* Start with parsing the "omp declare simd" attribute(s). */
12331 bool inbranch_clause_specified;
12332 struct cgraph_simd_clone *clone_info
12333 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
12334 &inbranch_clause_specified);
12335 if (clone_info == NULL)
12336 continue;
12338 int orig_simdlen = clone_info->simdlen;
12339 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
12340 /* The target can return 0 (no simd clones should be created),
12341 1 (just one ISA of simd clones should be created) or higher
12342 count of ISA variants. In that case, clone_info is initialized
12343 for the first ISA variant. */
12344 int count
12345 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
12346 base_type, 0);
12347 if (count == 0)
12348 continue;
12350 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12351 also create one inbranch and one !inbranch clone of it. */
12352 for (int i = 0; i < count * 2; i++)
12354 struct cgraph_simd_clone *clone = clone_info;
12355 if (inbranch_clause_specified && (i & 1) != 0)
12356 continue;
12358 if (i != 0)
12360 clone = simd_clone_struct_alloc (clone_info->nargs
12361 + ((i & 1) != 0));
12362 simd_clone_struct_copy (clone, clone_info);
12363 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12364 and simd_clone_adjust_argument_types did to the first
12365 clone's info. */
12366 clone->nargs -= clone_info->inbranch;
12367 clone->simdlen = orig_simdlen;
12368 /* And call the target hook again to get the right ISA. */
12369 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
12370 base_type,
12371 i / 2);
12372 if ((i & 1) != 0)
12373 clone->inbranch = 1;
12376 /* simd_clone_mangle might fail if such a clone has been created
12377 already. */
12378 tree id = simd_clone_mangle (node, clone);
12379 if (id == NULL_TREE)
12380 continue;
12382 /* Only when we are sure we want to create the clone actually
12383 clone the function (or definitions) or create another
12384 extern FUNCTION_DECL (for prototypes without definitions). */
12385 struct cgraph_node *n = simd_clone_create (node);
12386 if (n == NULL)
12387 continue;
12389 n->simdclone = clone;
12390 clone->origin = node;
12391 clone->next_clone = NULL;
12392 if (node->simd_clones == NULL)
12394 clone->prev_clone = n;
12395 node->simd_clones = n;
12397 else
12399 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
12400 clone->prev_clone->simdclone->next_clone = n;
12401 node->simd_clones->simdclone->prev_clone = n;
12403 symtab->change_decl_assembler_name (n->decl, id);
12404 /* And finally adjust the return type, parameters and for
12405 definitions also function body. */
12406 if (node->definition)
12407 simd_clone_adjust (n);
12408 else
12410 simd_clone_adjust_return_type (n);
12411 simd_clone_adjust_argument_types (n);
12415 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
12418 /* Entry point for IPA simd clone creation pass. */
12420 static unsigned int
12421 ipa_omp_simd_clone (void)
12423 struct cgraph_node *node;
12424 FOR_EACH_FUNCTION (node)
12425 expand_simd_clones (node);
12426 return 0;
12429 namespace {
12431 const pass_data pass_data_omp_simd_clone =
12433 SIMPLE_IPA_PASS, /* type */
12434 "simdclone", /* name */
12435 OPTGROUP_NONE, /* optinfo_flags */
12436 TV_NONE, /* tv_id */
12437 ( PROP_ssa | PROP_cfg ), /* properties_required */
12438 0, /* properties_provided */
12439 0, /* properties_destroyed */
12440 0, /* todo_flags_start */
12441 0, /* todo_flags_finish */
12444 class pass_omp_simd_clone : public simple_ipa_opt_pass
12446 public:
12447 pass_omp_simd_clone(gcc::context *ctxt)
12448 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
12451 /* opt_pass methods: */
12452 virtual bool gate (function *);
12453 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
12456 bool
12457 pass_omp_simd_clone::gate (function *)
12459 return ((flag_openmp || flag_openmp_simd
12460 || flag_cilkplus
12461 || (in_lto_p && !flag_wpa))
12462 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
12465 } // anon namespace
12467 simple_ipa_opt_pass *
12468 make_pass_omp_simd_clone (gcc::context *ctxt)
12470 return new pass_omp_simd_clone (ctxt);
12473 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
12474 adds their addresses and sizes to constructor-vector V_CTOR. */
12475 static void
12476 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
12477 vec<constructor_elt, va_gc> *v_ctor)
12479 unsigned len = vec_safe_length (v_decls);
12480 for (unsigned i = 0; i < len; i++)
12482 tree it = (*v_decls)[i];
12483 bool is_function = TREE_CODE (it) != VAR_DECL;
12485 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
12486 if (!is_function)
12487 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
12488 fold_convert (const_ptr_type_node,
12489 DECL_SIZE_UNIT (it)));
12493 /* Create new symbols containing (address, size) pairs for global variables,
12494 marked with "omp declare target" attribute, as well as addresses for the
12495 functions, which are outlined target regions. */
12496 void
12497 omp_finish_file (void)
12499 unsigned num_funcs = vec_safe_length (offload_funcs);
12500 unsigned num_vars = vec_safe_length (offload_vars);
12502 if (num_funcs == 0 && num_vars == 0)
12503 return;
12505 if (targetm_common.have_named_sections)
12507 vec<constructor_elt, va_gc> *v_f, *v_v;
12508 vec_alloc (v_f, num_funcs);
12509 vec_alloc (v_v, num_vars * 2);
12511 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
12512 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
12514 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
12515 num_vars * 2);
12516 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
12517 num_funcs);
12518 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
12519 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
12520 tree ctor_v = build_constructor (vars_decl_type, v_v);
12521 tree ctor_f = build_constructor (funcs_decl_type, v_f);
12522 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
12523 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
12524 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
12525 get_identifier (".offload_func_table"),
12526 funcs_decl_type);
12527 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
12528 get_identifier (".offload_var_table"),
12529 vars_decl_type);
12530 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
12531 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
12532 otherwise a joint table in a binary will contain padding between
12533 tables from multiple object files. */
12534 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
12535 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
12536 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
12537 DECL_INITIAL (funcs_decl) = ctor_f;
12538 DECL_INITIAL (vars_decl) = ctor_v;
12539 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
12540 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
12542 varpool_node::finalize_decl (vars_decl);
12543 varpool_node::finalize_decl (funcs_decl);
12545 else
12547 for (unsigned i = 0; i < num_funcs; i++)
12549 tree it = (*offload_funcs)[i];
12550 targetm.record_offload_symbol (it);
12552 for (unsigned i = 0; i < num_vars; i++)
12554 tree it = (*offload_vars)[i];
12555 targetm.record_offload_symbol (it);
12560 #include "gt-omp-low.h"