2015-01-13 Paolo Carlini <paolo.carlini@oracle.com>
[official-gcc.git] / gcc / omp-low.c
blobeaad52aed3bc4f5dd5be314ab5512be6f8a4cdf4
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-2015 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 "hash-set.h"
29 #include "machmode.h"
30 #include "vec.h"
31 #include "double-int.h"
32 #include "input.h"
33 #include "alias.h"
34 #include "symtab.h"
35 #include "wide-int.h"
36 #include "inchash.h"
37 #include "tree.h"
38 #include "fold-const.h"
39 #include "stringpool.h"
40 #include "stor-layout.h"
41 #include "rtl.h"
42 #include "predict.h"
43 #include "hard-reg-set.h"
44 #include "input.h"
45 #include "function.h"
46 #include "dominance.h"
47 #include "cfg.h"
48 #include "cfganal.h"
49 #include "basic-block.h"
50 #include "tree-ssa-alias.h"
51 #include "internal-fn.h"
52 #include "gimple-fold.h"
53 #include "gimple-expr.h"
54 #include "is-a.h"
55 #include "gimple.h"
56 #include "gimplify.h"
57 #include "gimple-iterator.h"
58 #include "gimplify-me.h"
59 #include "gimple-walk.h"
60 #include "tree-iterator.h"
61 #include "tree-inline.h"
62 #include "langhooks.h"
63 #include "diagnostic-core.h"
64 #include "gimple-ssa.h"
65 #include "hash-map.h"
66 #include "plugin-api.h"
67 #include "ipa-ref.h"
68 #include "cgraph.h"
69 #include "tree-cfg.h"
70 #include "tree-phinodes.h"
71 #include "ssa-iterators.h"
72 #include "tree-ssanames.h"
73 #include "tree-into-ssa.h"
74 #include "expr.h"
75 #include "tree-dfa.h"
76 #include "tree-ssa.h"
77 #include "flags.h"
78 #include "expr.h"
79 #include "tree-pass.h"
80 #include "except.h"
81 #include "splay-tree.h"
82 #include "insn-codes.h"
83 #include "optabs.h"
84 #include "cfgloop.h"
85 #include "target.h"
86 #include "common/common-target.h"
87 #include "omp-low.h"
88 #include "gimple-low.h"
89 #include "tree-cfgcleanup.h"
90 #include "pretty-print.h"
91 #include "alloc-pool.h"
92 #include "symbol-summary.h"
93 #include "ipa-prop.h"
94 #include "tree-nested.h"
95 #include "tree-eh.h"
96 #include "cilk.h"
97 #include "context.h"
98 #include "lto-section-names.h"
101 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
102 phases. The first phase scans the function looking for OMP statements
103 and then for variables that must be replaced to satisfy data sharing
104 clauses. The second phase expands code for the constructs, as well as
105 re-gimplifying things when variables have been replaced with complex
106 expressions.
108 Final code generation is done by pass_expand_omp. The flowgraph is
109 scanned for parallel regions which are then moved to a new
110 function, to be invoked by the thread library. */
112 /* Parallel region information. Every parallel and workshare
113 directive is enclosed between two markers, the OMP_* directive
114 and a corresponding OMP_RETURN statement. */
116 struct omp_region
118 /* The enclosing region. */
119 struct omp_region *outer;
121 /* First child region. */
122 struct omp_region *inner;
124 /* Next peer region. */
125 struct omp_region *next;
127 /* Block containing the omp directive as its last stmt. */
128 basic_block entry;
130 /* Block containing the OMP_RETURN as its last stmt. */
131 basic_block exit;
133 /* Block containing the OMP_CONTINUE as its last stmt. */
134 basic_block cont;
136 /* If this is a combined parallel+workshare region, this is a list
137 of additional arguments needed by the combined parallel+workshare
138 library call. */
139 vec<tree, va_gc> *ws_args;
141 /* The code for the omp directive of this region. */
142 enum gimple_code type;
144 /* Schedule kind, only used for OMP_FOR type regions. */
145 enum omp_clause_schedule_kind sched_kind;
147 /* True if this is a combined parallel+workshare region. */
148 bool is_combined_parallel;
151 /* Context structure. Used to store information about each parallel
152 directive in the code. */
154 typedef struct omp_context
156 /* This field must be at the beginning, as we do "inheritance": Some
157 callback functions for tree-inline.c (e.g., omp_copy_decl)
158 receive a copy_body_data pointer that is up-casted to an
159 omp_context pointer. */
160 copy_body_data cb;
162 /* The tree of contexts corresponding to the encountered constructs. */
163 struct omp_context *outer;
164 gimple stmt;
166 /* Map variables to fields in a structure that allows communication
167 between sending and receiving threads. */
168 splay_tree field_map;
169 tree record_type;
170 tree sender_decl;
171 tree receiver_decl;
173 /* These are used just by task contexts, if task firstprivate fn is
174 needed. srecord_type is used to communicate from the thread
175 that encountered the task construct to task firstprivate fn,
176 record_type is allocated by GOMP_task, initialized by task firstprivate
177 fn and passed to the task body fn. */
178 splay_tree sfield_map;
179 tree srecord_type;
181 /* A chain of variables to add to the top-level block surrounding the
182 construct. In the case of a parallel, this is in the child function. */
183 tree block_vars;
185 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
186 barriers should jump to during omplower pass. */
187 tree cancel_label;
189 /* What to do with variables with implicitly determined sharing
190 attributes. */
191 enum omp_clause_default_kind default_kind;
193 /* Nesting depth of this context. Used to beautify error messages re
194 invalid gotos. The outermost ctx is depth 1, with depth 0 being
195 reserved for the main body of the function. */
196 int depth;
198 /* True if this parallel directive is nested within another. */
199 bool is_nested;
201 /* True if this construct can be cancelled. */
202 bool cancellable;
203 } omp_context;
206 struct omp_for_data_loop
208 tree v, n1, n2, step;
209 enum tree_code cond_code;
212 /* A structure describing the main elements of a parallel loop. */
214 struct omp_for_data
216 struct omp_for_data_loop loop;
217 tree chunk_size;
218 gomp_for *for_stmt;
219 tree pre, iter_type;
220 int collapse;
221 bool have_nowait, have_ordered;
222 enum omp_clause_schedule_kind sched_kind;
223 struct omp_for_data_loop *loops;
227 static splay_tree all_contexts;
228 static int taskreg_nesting_level;
229 static int target_nesting_level;
230 static struct omp_region *root_omp_region;
231 static bitmap task_shared_vars;
232 static vec<omp_context *> taskreg_contexts;
234 static void scan_omp (gimple_seq *, omp_context *);
235 static tree scan_omp_1_op (tree *, int *, void *);
237 #define WALK_SUBSTMTS \
238 case GIMPLE_BIND: \
239 case GIMPLE_TRY: \
240 case GIMPLE_CATCH: \
241 case GIMPLE_EH_FILTER: \
242 case GIMPLE_TRANSACTION: \
243 /* The sub-statements for these should be walked. */ \
244 *handled_ops_p = false; \
245 break;
247 /* Holds offload tables with decls. */
248 vec<tree, va_gc> *offload_funcs, *offload_vars;
250 /* Convenience function for calling scan_omp_1_op on tree operands. */
252 static inline tree
253 scan_omp_op (tree *tp, omp_context *ctx)
255 struct walk_stmt_info wi;
257 memset (&wi, 0, sizeof (wi));
258 wi.info = ctx;
259 wi.want_locations = true;
261 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
264 static void lower_omp (gimple_seq *, omp_context *);
265 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
266 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
268 /* Find an OpenMP clause of type KIND within CLAUSES. */
270 tree
271 find_omp_clause (tree clauses, enum omp_clause_code kind)
273 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
274 if (OMP_CLAUSE_CODE (clauses) == kind)
275 return clauses;
277 return NULL_TREE;
280 /* Return true if CTX is for an omp parallel. */
282 static inline bool
283 is_parallel_ctx (omp_context *ctx)
285 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
289 /* Return true if CTX is for an omp target region. */
291 static inline bool
292 is_targetreg_ctx (omp_context *ctx)
294 return gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
295 && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION;
299 /* Return true if CTX is for an omp task. */
301 static inline bool
302 is_task_ctx (omp_context *ctx)
304 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
308 /* Return true if CTX is for an omp parallel or omp task. */
310 static inline bool
311 is_taskreg_ctx (omp_context *ctx)
313 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
314 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
318 /* Return true if REGION is a combined parallel+workshare region. */
320 static inline bool
321 is_combined_parallel (struct omp_region *region)
323 return region->is_combined_parallel;
327 /* Extract the header elements of parallel loop FOR_STMT and store
328 them into *FD. */
330 static void
331 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
332 struct omp_for_data_loop *loops)
334 tree t, var, *collapse_iter, *collapse_count;
335 tree count = NULL_TREE, iter_type = long_integer_type_node;
336 struct omp_for_data_loop *loop;
337 int i;
338 struct omp_for_data_loop dummy_loop;
339 location_t loc = gimple_location (for_stmt);
340 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
341 bool distribute = gimple_omp_for_kind (for_stmt)
342 == GF_OMP_FOR_KIND_DISTRIBUTE;
344 fd->for_stmt = for_stmt;
345 fd->pre = NULL;
346 fd->collapse = gimple_omp_for_collapse (for_stmt);
347 if (fd->collapse > 1)
348 fd->loops = loops;
349 else
350 fd->loops = &fd->loop;
352 fd->have_nowait = distribute || simd;
353 fd->have_ordered = false;
354 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
355 fd->chunk_size = NULL_TREE;
356 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
357 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
358 collapse_iter = NULL;
359 collapse_count = NULL;
361 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
362 switch (OMP_CLAUSE_CODE (t))
364 case OMP_CLAUSE_NOWAIT:
365 fd->have_nowait = true;
366 break;
367 case OMP_CLAUSE_ORDERED:
368 fd->have_ordered = true;
369 break;
370 case OMP_CLAUSE_SCHEDULE:
371 gcc_assert (!distribute);
372 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
373 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
374 break;
375 case OMP_CLAUSE_DIST_SCHEDULE:
376 gcc_assert (distribute);
377 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
378 break;
379 case OMP_CLAUSE_COLLAPSE:
380 if (fd->collapse > 1)
382 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
383 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
385 break;
386 default:
387 break;
390 /* FIXME: for now map schedule(auto) to schedule(static).
391 There should be analysis to determine whether all iterations
392 are approximately the same amount of work (then schedule(static)
393 is best) or if it varies (then schedule(dynamic,N) is better). */
394 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
396 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
397 gcc_assert (fd->chunk_size == NULL);
399 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
400 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
401 gcc_assert (fd->chunk_size == NULL);
402 else if (fd->chunk_size == NULL)
404 /* We only need to compute a default chunk size for ordered
405 static loops and dynamic loops. */
406 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
407 || fd->have_ordered)
408 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
409 ? integer_zero_node : integer_one_node;
412 for (i = 0; i < fd->collapse; i++)
414 if (fd->collapse == 1)
415 loop = &fd->loop;
416 else if (loops != NULL)
417 loop = loops + i;
418 else
419 loop = &dummy_loop;
421 loop->v = gimple_omp_for_index (for_stmt, i);
422 gcc_assert (SSA_VAR_P (loop->v));
423 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
424 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
425 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
426 loop->n1 = gimple_omp_for_initial (for_stmt, i);
428 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
429 loop->n2 = gimple_omp_for_final (for_stmt, i);
430 switch (loop->cond_code)
432 case LT_EXPR:
433 case GT_EXPR:
434 break;
435 case NE_EXPR:
436 gcc_assert (gimple_omp_for_kind (for_stmt)
437 == GF_OMP_FOR_KIND_CILKSIMD
438 || (gimple_omp_for_kind (for_stmt)
439 == GF_OMP_FOR_KIND_CILKFOR));
440 break;
441 case LE_EXPR:
442 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
443 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
444 else
445 loop->n2 = fold_build2_loc (loc,
446 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
447 build_int_cst (TREE_TYPE (loop->n2), 1));
448 loop->cond_code = LT_EXPR;
449 break;
450 case GE_EXPR:
451 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
452 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
453 else
454 loop->n2 = fold_build2_loc (loc,
455 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
456 build_int_cst (TREE_TYPE (loop->n2), 1));
457 loop->cond_code = GT_EXPR;
458 break;
459 default:
460 gcc_unreachable ();
463 t = gimple_omp_for_incr (for_stmt, i);
464 gcc_assert (TREE_OPERAND (t, 0) == var);
465 switch (TREE_CODE (t))
467 case PLUS_EXPR:
468 loop->step = TREE_OPERAND (t, 1);
469 break;
470 case POINTER_PLUS_EXPR:
471 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
472 break;
473 case MINUS_EXPR:
474 loop->step = TREE_OPERAND (t, 1);
475 loop->step = fold_build1_loc (loc,
476 NEGATE_EXPR, TREE_TYPE (loop->step),
477 loop->step);
478 break;
479 default:
480 gcc_unreachable ();
483 if (simd
484 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
485 && !fd->have_ordered))
487 if (fd->collapse == 1)
488 iter_type = TREE_TYPE (loop->v);
489 else if (i == 0
490 || TYPE_PRECISION (iter_type)
491 < TYPE_PRECISION (TREE_TYPE (loop->v)))
492 iter_type
493 = build_nonstandard_integer_type
494 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
496 else if (iter_type != long_long_unsigned_type_node)
498 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
499 iter_type = long_long_unsigned_type_node;
500 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
501 && TYPE_PRECISION (TREE_TYPE (loop->v))
502 >= TYPE_PRECISION (iter_type))
504 tree n;
506 if (loop->cond_code == LT_EXPR)
507 n = fold_build2_loc (loc,
508 PLUS_EXPR, TREE_TYPE (loop->v),
509 loop->n2, loop->step);
510 else
511 n = loop->n1;
512 if (TREE_CODE (n) != INTEGER_CST
513 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
514 iter_type = long_long_unsigned_type_node;
516 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
517 > TYPE_PRECISION (iter_type))
519 tree n1, n2;
521 if (loop->cond_code == LT_EXPR)
523 n1 = loop->n1;
524 n2 = fold_build2_loc (loc,
525 PLUS_EXPR, TREE_TYPE (loop->v),
526 loop->n2, loop->step);
528 else
530 n1 = fold_build2_loc (loc,
531 MINUS_EXPR, TREE_TYPE (loop->v),
532 loop->n2, loop->step);
533 n2 = loop->n1;
535 if (TREE_CODE (n1) != INTEGER_CST
536 || TREE_CODE (n2) != INTEGER_CST
537 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
538 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
539 iter_type = long_long_unsigned_type_node;
543 if (collapse_count && *collapse_count == NULL)
545 t = fold_binary (loop->cond_code, boolean_type_node,
546 fold_convert (TREE_TYPE (loop->v), loop->n1),
547 fold_convert (TREE_TYPE (loop->v), loop->n2));
548 if (t && integer_zerop (t))
549 count = build_zero_cst (long_long_unsigned_type_node);
550 else if ((i == 0 || count != NULL_TREE)
551 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
552 && TREE_CONSTANT (loop->n1)
553 && TREE_CONSTANT (loop->n2)
554 && TREE_CODE (loop->step) == INTEGER_CST)
556 tree itype = TREE_TYPE (loop->v);
558 if (POINTER_TYPE_P (itype))
559 itype = signed_type_for (itype);
560 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
561 t = fold_build2_loc (loc,
562 PLUS_EXPR, itype,
563 fold_convert_loc (loc, itype, loop->step), t);
564 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
565 fold_convert_loc (loc, itype, loop->n2));
566 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
567 fold_convert_loc (loc, itype, loop->n1));
568 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
569 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
570 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
571 fold_build1_loc (loc, NEGATE_EXPR, itype,
572 fold_convert_loc (loc, itype,
573 loop->step)));
574 else
575 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
576 fold_convert_loc (loc, itype, loop->step));
577 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
578 if (count != NULL_TREE)
579 count = fold_build2_loc (loc,
580 MULT_EXPR, long_long_unsigned_type_node,
581 count, t);
582 else
583 count = t;
584 if (TREE_CODE (count) != INTEGER_CST)
585 count = NULL_TREE;
587 else if (count && !integer_zerop (count))
588 count = NULL_TREE;
592 if (count
593 && !simd
594 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
595 || fd->have_ordered))
597 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
598 iter_type = long_long_unsigned_type_node;
599 else
600 iter_type = long_integer_type_node;
602 else if (collapse_iter && *collapse_iter != NULL)
603 iter_type = TREE_TYPE (*collapse_iter);
604 fd->iter_type = iter_type;
605 if (collapse_iter && *collapse_iter == NULL)
606 *collapse_iter = create_tmp_var (iter_type, ".iter");
607 if (collapse_count && *collapse_count == NULL)
609 if (count)
610 *collapse_count = fold_convert_loc (loc, iter_type, count);
611 else
612 *collapse_count = create_tmp_var (iter_type, ".count");
615 if (fd->collapse > 1)
617 fd->loop.v = *collapse_iter;
618 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
619 fd->loop.n2 = *collapse_count;
620 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
621 fd->loop.cond_code = LT_EXPR;
626 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
627 is the immediate dominator of PAR_ENTRY_BB, return true if there
628 are no data dependencies that would prevent expanding the parallel
629 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
631 When expanding a combined parallel+workshare region, the call to
632 the child function may need additional arguments in the case of
633 GIMPLE_OMP_FOR regions. In some cases, these arguments are
634 computed out of variables passed in from the parent to the child
635 via 'struct .omp_data_s'. For instance:
637 #pragma omp parallel for schedule (guided, i * 4)
638 for (j ...)
640 Is lowered into:
642 # BLOCK 2 (PAR_ENTRY_BB)
643 .omp_data_o.i = i;
644 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
646 # BLOCK 3 (WS_ENTRY_BB)
647 .omp_data_i = &.omp_data_o;
648 D.1667 = .omp_data_i->i;
649 D.1598 = D.1667 * 4;
650 #pragma omp for schedule (guided, D.1598)
652 When we outline the parallel region, the call to the child function
653 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
654 that value is computed *after* the call site. So, in principle we
655 cannot do the transformation.
657 To see whether the code in WS_ENTRY_BB blocks the combined
658 parallel+workshare call, we collect all the variables used in the
659 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
660 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
661 call.
663 FIXME. If we had the SSA form built at this point, we could merely
664 hoist the code in block 3 into block 2 and be done with it. But at
665 this point we don't have dataflow information and though we could
666 hack something up here, it is really not worth the aggravation. */
668 static bool
669 workshare_safe_to_combine_p (basic_block ws_entry_bb)
671 struct omp_for_data fd;
672 gimple ws_stmt = last_stmt (ws_entry_bb);
674 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
675 return true;
677 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
679 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
681 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
682 return false;
683 if (fd.iter_type != long_integer_type_node)
684 return false;
686 /* FIXME. We give up too easily here. If any of these arguments
687 are not constants, they will likely involve variables that have
688 been mapped into fields of .omp_data_s for sharing with the child
689 function. With appropriate data flow, it would be possible to
690 see through this. */
691 if (!is_gimple_min_invariant (fd.loop.n1)
692 || !is_gimple_min_invariant (fd.loop.n2)
693 || !is_gimple_min_invariant (fd.loop.step)
694 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
695 return false;
697 return true;
701 /* Collect additional arguments needed to emit a combined
702 parallel+workshare call. WS_STMT is the workshare directive being
703 expanded. */
705 static vec<tree, va_gc> *
706 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
708 tree t;
709 location_t loc = gimple_location (ws_stmt);
710 vec<tree, va_gc> *ws_args;
712 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
714 struct omp_for_data fd;
715 tree n1, n2;
717 extract_omp_for_data (for_stmt, &fd, NULL);
718 n1 = fd.loop.n1;
719 n2 = fd.loop.n2;
721 if (gimple_omp_for_combined_into_p (for_stmt))
723 tree innerc
724 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
725 OMP_CLAUSE__LOOPTEMP_);
726 gcc_assert (innerc);
727 n1 = OMP_CLAUSE_DECL (innerc);
728 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
729 OMP_CLAUSE__LOOPTEMP_);
730 gcc_assert (innerc);
731 n2 = OMP_CLAUSE_DECL (innerc);
734 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
736 t = fold_convert_loc (loc, long_integer_type_node, n1);
737 ws_args->quick_push (t);
739 t = fold_convert_loc (loc, long_integer_type_node, n2);
740 ws_args->quick_push (t);
742 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
743 ws_args->quick_push (t);
745 if (fd.chunk_size)
747 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
748 ws_args->quick_push (t);
751 return ws_args;
753 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
755 /* Number of sections is equal to the number of edges from the
756 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
757 the exit of the sections region. */
758 basic_block bb = single_succ (gimple_bb (ws_stmt));
759 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
760 vec_alloc (ws_args, 1);
761 ws_args->quick_push (t);
762 return ws_args;
765 gcc_unreachable ();
769 /* Discover whether REGION is a combined parallel+workshare region. */
771 static void
772 determine_parallel_type (struct omp_region *region)
774 basic_block par_entry_bb, par_exit_bb;
775 basic_block ws_entry_bb, ws_exit_bb;
777 if (region == NULL || region->inner == NULL
778 || region->exit == NULL || region->inner->exit == NULL
779 || region->inner->cont == NULL)
780 return;
782 /* We only support parallel+for and parallel+sections. */
783 if (region->type != GIMPLE_OMP_PARALLEL
784 || (region->inner->type != GIMPLE_OMP_FOR
785 && region->inner->type != GIMPLE_OMP_SECTIONS))
786 return;
788 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
789 WS_EXIT_BB -> PAR_EXIT_BB. */
790 par_entry_bb = region->entry;
791 par_exit_bb = region->exit;
792 ws_entry_bb = region->inner->entry;
793 ws_exit_bb = region->inner->exit;
795 if (single_succ (par_entry_bb) == ws_entry_bb
796 && single_succ (ws_exit_bb) == par_exit_bb
797 && workshare_safe_to_combine_p (ws_entry_bb)
798 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
799 || (last_and_only_stmt (ws_entry_bb)
800 && last_and_only_stmt (par_exit_bb))))
802 gimple par_stmt = last_stmt (par_entry_bb);
803 gimple ws_stmt = last_stmt (ws_entry_bb);
805 if (region->inner->type == GIMPLE_OMP_FOR)
807 /* If this is a combined parallel loop, we need to determine
808 whether or not to use the combined library calls. There
809 are two cases where we do not apply the transformation:
810 static loops and any kind of ordered loop. In the first
811 case, we already open code the loop so there is no need
812 to do anything else. In the latter case, the combined
813 parallel loop call would still need extra synchronization
814 to implement ordered semantics, so there would not be any
815 gain in using the combined call. */
816 tree clauses = gimple_omp_for_clauses (ws_stmt);
817 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
818 if (c == NULL
819 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
820 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
822 region->is_combined_parallel = false;
823 region->inner->is_combined_parallel = false;
824 return;
828 region->is_combined_parallel = true;
829 region->inner->is_combined_parallel = true;
830 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
835 /* Return true if EXPR is variable sized. */
837 static inline bool
838 is_variable_sized (const_tree expr)
840 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
843 /* Return true if DECL is a reference type. */
845 static inline bool
846 is_reference (tree decl)
848 return lang_hooks.decls.omp_privatize_by_reference (decl);
851 /* Lookup variables in the decl or field splay trees. The "maybe" form
852 allows for the variable form to not have been entered, otherwise we
853 assert that the variable must have been entered. */
855 static inline tree
856 lookup_decl (tree var, omp_context *ctx)
858 tree *n = ctx->cb.decl_map->get (var);
859 return *n;
862 static inline tree
863 maybe_lookup_decl (const_tree var, omp_context *ctx)
865 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
866 return n ? *n : NULL_TREE;
869 static inline tree
870 lookup_field (tree var, omp_context *ctx)
872 splay_tree_node n;
873 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
874 return (tree) n->value;
877 static inline tree
878 lookup_sfield (tree var, omp_context *ctx)
880 splay_tree_node n;
881 n = splay_tree_lookup (ctx->sfield_map
882 ? ctx->sfield_map : ctx->field_map,
883 (splay_tree_key) var);
884 return (tree) n->value;
887 static inline tree
888 maybe_lookup_field (tree var, omp_context *ctx)
890 splay_tree_node n;
891 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
892 return n ? (tree) n->value : NULL_TREE;
895 /* Return true if DECL should be copied by pointer. SHARED_CTX is
896 the parallel context if DECL is to be shared. */
898 static bool
899 use_pointer_for_field (tree decl, omp_context *shared_ctx)
901 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
902 return true;
904 /* We can only use copy-in/copy-out semantics for shared variables
905 when we know the value is not accessible from an outer scope. */
906 if (shared_ctx)
908 /* ??? Trivially accessible from anywhere. But why would we even
909 be passing an address in this case? Should we simply assert
910 this to be false, or should we have a cleanup pass that removes
911 these from the list of mappings? */
912 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
913 return true;
915 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
916 without analyzing the expression whether or not its location
917 is accessible to anyone else. In the case of nested parallel
918 regions it certainly may be. */
919 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
920 return true;
922 /* Do not use copy-in/copy-out for variables that have their
923 address taken. */
924 if (TREE_ADDRESSABLE (decl))
925 return true;
927 /* lower_send_shared_vars only uses copy-in, but not copy-out
928 for these. */
929 if (TREE_READONLY (decl)
930 || ((TREE_CODE (decl) == RESULT_DECL
931 || TREE_CODE (decl) == PARM_DECL)
932 && DECL_BY_REFERENCE (decl)))
933 return false;
935 /* Disallow copy-in/out in nested parallel if
936 decl is shared in outer parallel, otherwise
937 each thread could store the shared variable
938 in its own copy-in location, making the
939 variable no longer really shared. */
940 if (shared_ctx->is_nested)
942 omp_context *up;
944 for (up = shared_ctx->outer; up; up = up->outer)
945 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
946 break;
948 if (up)
950 tree c;
952 for (c = gimple_omp_taskreg_clauses (up->stmt);
953 c; c = OMP_CLAUSE_CHAIN (c))
954 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
955 && OMP_CLAUSE_DECL (c) == decl)
956 break;
958 if (c)
959 goto maybe_mark_addressable_and_ret;
963 /* For tasks avoid using copy-in/out. As tasks can be
964 deferred or executed in different thread, when GOMP_task
965 returns, the task hasn't necessarily terminated. */
966 if (is_task_ctx (shared_ctx))
968 tree outer;
969 maybe_mark_addressable_and_ret:
970 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
971 if (is_gimple_reg (outer))
973 /* Taking address of OUTER in lower_send_shared_vars
974 might need regimplification of everything that uses the
975 variable. */
976 if (!task_shared_vars)
977 task_shared_vars = BITMAP_ALLOC (NULL);
978 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
979 TREE_ADDRESSABLE (outer) = 1;
981 return true;
985 return false;
988 /* Construct a new automatic decl similar to VAR. */
990 static tree
991 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
993 tree copy = copy_var_decl (var, name, type);
995 DECL_CONTEXT (copy) = current_function_decl;
996 DECL_CHAIN (copy) = ctx->block_vars;
997 ctx->block_vars = copy;
999 return copy;
1002 static tree
1003 omp_copy_decl_1 (tree var, omp_context *ctx)
1005 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1008 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1009 as appropriate. */
1010 static tree
1011 omp_build_component_ref (tree obj, tree field)
1013 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1014 if (TREE_THIS_VOLATILE (field))
1015 TREE_THIS_VOLATILE (ret) |= 1;
1016 if (TREE_READONLY (field))
1017 TREE_READONLY (ret) |= 1;
1018 return ret;
1021 /* Build tree nodes to access the field for VAR on the receiver side. */
1023 static tree
1024 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1026 tree x, field = lookup_field (var, ctx);
1028 /* If the receiver record type was remapped in the child function,
1029 remap the field into the new record type. */
1030 x = maybe_lookup_field (field, ctx);
1031 if (x != NULL)
1032 field = x;
1034 x = build_simple_mem_ref (ctx->receiver_decl);
1035 x = omp_build_component_ref (x, field);
1036 if (by_ref)
1037 x = build_simple_mem_ref (x);
1039 return x;
1042 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1043 of a parallel, this is a component reference; for workshare constructs
1044 this is some variable. */
1046 static tree
1047 build_outer_var_ref (tree var, omp_context *ctx)
1049 tree x;
1051 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1052 x = var;
1053 else if (is_variable_sized (var))
1055 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1056 x = build_outer_var_ref (x, ctx);
1057 x = build_simple_mem_ref (x);
1059 else if (is_taskreg_ctx (ctx))
1061 bool by_ref = use_pointer_for_field (var, NULL);
1062 x = build_receiver_ref (var, by_ref, ctx);
1064 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1065 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1067 /* #pragma omp simd isn't a worksharing construct, and can reference even
1068 private vars in its linear etc. clauses. */
1069 x = NULL_TREE;
1070 if (ctx->outer && is_taskreg_ctx (ctx))
1071 x = lookup_decl (var, ctx->outer);
1072 else if (ctx->outer)
1073 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1074 if (x == NULL_TREE)
1075 x = var;
1077 else if (ctx->outer)
1078 x = lookup_decl (var, ctx->outer);
1079 else if (is_reference (var))
1080 /* This can happen with orphaned constructs. If var is reference, it is
1081 possible it is shared and as such valid. */
1082 x = var;
1083 else
1084 gcc_unreachable ();
1086 if (is_reference (var))
1087 x = build_simple_mem_ref (x);
1089 return x;
1092 /* Build tree nodes to access the field for VAR on the sender side. */
1094 static tree
1095 build_sender_ref (tree var, omp_context *ctx)
1097 tree field = lookup_sfield (var, ctx);
1098 return omp_build_component_ref (ctx->sender_decl, field);
1101 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1103 static void
1104 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1106 tree field, type, sfield = NULL_TREE;
1108 gcc_assert ((mask & 1) == 0
1109 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1110 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1111 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1113 type = TREE_TYPE (var);
1114 if (mask & 4)
1116 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1117 type = build_pointer_type (build_pointer_type (type));
1119 else if (by_ref)
1120 type = build_pointer_type (type);
1121 else if ((mask & 3) == 1 && is_reference (var))
1122 type = TREE_TYPE (type);
1124 field = build_decl (DECL_SOURCE_LOCATION (var),
1125 FIELD_DECL, DECL_NAME (var), type);
1127 /* Remember what variable this field was created for. This does have a
1128 side effect of making dwarf2out ignore this member, so for helpful
1129 debugging we clear it later in delete_omp_context. */
1130 DECL_ABSTRACT_ORIGIN (field) = var;
1131 if (type == TREE_TYPE (var))
1133 DECL_ALIGN (field) = DECL_ALIGN (var);
1134 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1135 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1137 else
1138 DECL_ALIGN (field) = TYPE_ALIGN (type);
1140 if ((mask & 3) == 3)
1142 insert_field_into_struct (ctx->record_type, field);
1143 if (ctx->srecord_type)
1145 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1146 FIELD_DECL, DECL_NAME (var), type);
1147 DECL_ABSTRACT_ORIGIN (sfield) = var;
1148 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1149 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1150 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1151 insert_field_into_struct (ctx->srecord_type, sfield);
1154 else
1156 if (ctx->srecord_type == NULL_TREE)
1158 tree t;
1160 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1161 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1162 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1164 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1165 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1166 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1167 insert_field_into_struct (ctx->srecord_type, sfield);
1168 splay_tree_insert (ctx->sfield_map,
1169 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1170 (splay_tree_value) sfield);
1173 sfield = field;
1174 insert_field_into_struct ((mask & 1) ? ctx->record_type
1175 : ctx->srecord_type, field);
1178 if (mask & 1)
1179 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1180 (splay_tree_value) field);
1181 if ((mask & 2) && ctx->sfield_map)
1182 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1183 (splay_tree_value) sfield);
1186 static tree
1187 install_var_local (tree var, omp_context *ctx)
1189 tree new_var = omp_copy_decl_1 (var, ctx);
1190 insert_decl_map (&ctx->cb, var, new_var);
1191 return new_var;
1194 /* Adjust the replacement for DECL in CTX for the new context. This means
1195 copying the DECL_VALUE_EXPR, and fixing up the type. */
1197 static void
1198 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1200 tree new_decl, size;
1202 new_decl = lookup_decl (decl, ctx);
1204 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1206 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1207 && DECL_HAS_VALUE_EXPR_P (decl))
1209 tree ve = DECL_VALUE_EXPR (decl);
1210 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1211 SET_DECL_VALUE_EXPR (new_decl, ve);
1212 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1215 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1217 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1218 if (size == error_mark_node)
1219 size = TYPE_SIZE (TREE_TYPE (new_decl));
1220 DECL_SIZE (new_decl) = size;
1222 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1223 if (size == error_mark_node)
1224 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1225 DECL_SIZE_UNIT (new_decl) = size;
1229 /* The callback for remap_decl. Search all containing contexts for a
1230 mapping of the variable; this avoids having to duplicate the splay
1231 tree ahead of time. We know a mapping doesn't already exist in the
1232 given context. Create new mappings to implement default semantics. */
1234 static tree
1235 omp_copy_decl (tree var, copy_body_data *cb)
1237 omp_context *ctx = (omp_context *) cb;
1238 tree new_var;
1240 if (TREE_CODE (var) == LABEL_DECL)
1242 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1243 DECL_CONTEXT (new_var) = current_function_decl;
1244 insert_decl_map (&ctx->cb, var, new_var);
1245 return new_var;
1248 while (!is_taskreg_ctx (ctx))
1250 ctx = ctx->outer;
1251 if (ctx == NULL)
1252 return var;
1253 new_var = maybe_lookup_decl (var, ctx);
1254 if (new_var)
1255 return new_var;
1258 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1259 return var;
1261 return error_mark_node;
1265 /* Debugging dumps for parallel regions. */
1266 void dump_omp_region (FILE *, struct omp_region *, int);
1267 void debug_omp_region (struct omp_region *);
1268 void debug_all_omp_regions (void);
1270 /* Dump the parallel region tree rooted at REGION. */
1272 void
1273 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1275 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1276 gimple_code_name[region->type]);
1278 if (region->inner)
1279 dump_omp_region (file, region->inner, indent + 4);
1281 if (region->cont)
1283 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1284 region->cont->index);
1287 if (region->exit)
1288 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1289 region->exit->index);
1290 else
1291 fprintf (file, "%*s[no exit marker]\n", indent, "");
1293 if (region->next)
1294 dump_omp_region (file, region->next, indent);
1297 DEBUG_FUNCTION void
1298 debug_omp_region (struct omp_region *region)
1300 dump_omp_region (stderr, region, 0);
1303 DEBUG_FUNCTION void
1304 debug_all_omp_regions (void)
1306 dump_omp_region (stderr, root_omp_region, 0);
1310 /* Create a new parallel region starting at STMT inside region PARENT. */
1312 static struct omp_region *
1313 new_omp_region (basic_block bb, enum gimple_code type,
1314 struct omp_region *parent)
1316 struct omp_region *region = XCNEW (struct omp_region);
1318 region->outer = parent;
1319 region->entry = bb;
1320 region->type = type;
1322 if (parent)
1324 /* This is a nested region. Add it to the list of inner
1325 regions in PARENT. */
1326 region->next = parent->inner;
1327 parent->inner = region;
1329 else
1331 /* This is a toplevel region. Add it to the list of toplevel
1332 regions in ROOT_OMP_REGION. */
1333 region->next = root_omp_region;
1334 root_omp_region = region;
1337 return region;
1340 /* Release the memory associated with the region tree rooted at REGION. */
1342 static void
1343 free_omp_region_1 (struct omp_region *region)
1345 struct omp_region *i, *n;
1347 for (i = region->inner; i ; i = n)
1349 n = i->next;
1350 free_omp_region_1 (i);
1353 free (region);
1356 /* Release the memory for the entire omp region tree. */
1358 void
1359 free_omp_regions (void)
1361 struct omp_region *r, *n;
1362 for (r = root_omp_region; r ; r = n)
1364 n = r->next;
1365 free_omp_region_1 (r);
1367 root_omp_region = NULL;
1371 /* Create a new context, with OUTER_CTX being the surrounding context. */
1373 static omp_context *
1374 new_omp_context (gimple stmt, omp_context *outer_ctx)
1376 omp_context *ctx = XCNEW (omp_context);
1378 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1379 (splay_tree_value) ctx);
1380 ctx->stmt = stmt;
1382 if (outer_ctx)
1384 ctx->outer = outer_ctx;
1385 ctx->cb = outer_ctx->cb;
1386 ctx->cb.block = NULL;
1387 ctx->depth = outer_ctx->depth + 1;
1389 else
1391 ctx->cb.src_fn = current_function_decl;
1392 ctx->cb.dst_fn = current_function_decl;
1393 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1394 gcc_checking_assert (ctx->cb.src_node);
1395 ctx->cb.dst_node = ctx->cb.src_node;
1396 ctx->cb.src_cfun = cfun;
1397 ctx->cb.copy_decl = omp_copy_decl;
1398 ctx->cb.eh_lp_nr = 0;
1399 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1400 ctx->depth = 1;
1403 ctx->cb.decl_map = new hash_map<tree, tree>;
1405 return ctx;
1408 static gimple_seq maybe_catch_exception (gimple_seq);
1410 /* Finalize task copyfn. */
1412 static void
1413 finalize_task_copyfn (gomp_task *task_stmt)
1415 struct function *child_cfun;
1416 tree child_fn;
1417 gimple_seq seq = NULL, new_seq;
1418 gbind *bind;
1420 child_fn = gimple_omp_task_copy_fn (task_stmt);
1421 if (child_fn == NULL_TREE)
1422 return;
1424 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1425 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1427 push_cfun (child_cfun);
1428 bind = gimplify_body (child_fn, false);
1429 gimple_seq_add_stmt (&seq, bind);
1430 new_seq = maybe_catch_exception (seq);
1431 if (new_seq != seq)
1433 bind = gimple_build_bind (NULL, new_seq, NULL);
1434 seq = NULL;
1435 gimple_seq_add_stmt (&seq, bind);
1437 gimple_set_body (child_fn, seq);
1438 pop_cfun ();
1440 /* Inform the callgraph about the new function. */
1441 cgraph_node::add_new_function (child_fn, false);
1444 /* Destroy a omp_context data structures. Called through the splay tree
1445 value delete callback. */
1447 static void
1448 delete_omp_context (splay_tree_value value)
1450 omp_context *ctx = (omp_context *) value;
1452 delete ctx->cb.decl_map;
1454 if (ctx->field_map)
1455 splay_tree_delete (ctx->field_map);
1456 if (ctx->sfield_map)
1457 splay_tree_delete (ctx->sfield_map);
1459 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1460 it produces corrupt debug information. */
1461 if (ctx->record_type)
1463 tree t;
1464 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1465 DECL_ABSTRACT_ORIGIN (t) = NULL;
1467 if (ctx->srecord_type)
1469 tree t;
1470 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1471 DECL_ABSTRACT_ORIGIN (t) = NULL;
1474 if (is_task_ctx (ctx))
1475 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1477 XDELETE (ctx);
1480 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1481 context. */
1483 static void
1484 fixup_child_record_type (omp_context *ctx)
1486 tree f, type = ctx->record_type;
1488 /* ??? It isn't sufficient to just call remap_type here, because
1489 variably_modified_type_p doesn't work the way we expect for
1490 record types. Testing each field for whether it needs remapping
1491 and creating a new record by hand works, however. */
1492 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1493 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1494 break;
1495 if (f)
1497 tree name, new_fields = NULL;
1499 type = lang_hooks.types.make_type (RECORD_TYPE);
1500 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1501 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1502 TYPE_DECL, name, type);
1503 TYPE_NAME (type) = name;
1505 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1507 tree new_f = copy_node (f);
1508 DECL_CONTEXT (new_f) = type;
1509 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1510 DECL_CHAIN (new_f) = new_fields;
1511 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1512 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1513 &ctx->cb, NULL);
1514 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1515 &ctx->cb, NULL);
1516 new_fields = new_f;
1518 /* Arrange to be able to look up the receiver field
1519 given the sender field. */
1520 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1521 (splay_tree_value) new_f);
1523 TYPE_FIELDS (type) = nreverse (new_fields);
1524 layout_type (type);
1527 TREE_TYPE (ctx->receiver_decl)
1528 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1531 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1532 specified by CLAUSES. */
1534 static void
1535 scan_sharing_clauses (tree clauses, omp_context *ctx)
1537 tree c, decl;
1538 bool scan_array_reductions = false;
1540 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1542 bool by_ref;
1544 switch (OMP_CLAUSE_CODE (c))
1546 case OMP_CLAUSE_PRIVATE:
1547 decl = OMP_CLAUSE_DECL (c);
1548 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1549 goto do_private;
1550 else if (!is_variable_sized (decl))
1551 install_var_local (decl, ctx);
1552 break;
1554 case OMP_CLAUSE_SHARED:
1555 decl = OMP_CLAUSE_DECL (c);
1556 /* Ignore shared directives in teams construct. */
1557 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1559 /* Global variables don't need to be copied,
1560 the receiver side will use them directly. */
1561 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1562 if (is_global_var (odecl))
1563 break;
1564 insert_decl_map (&ctx->cb, decl, odecl);
1565 break;
1567 gcc_assert (is_taskreg_ctx (ctx));
1568 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1569 || !is_variable_sized (decl));
1570 /* Global variables don't need to be copied,
1571 the receiver side will use them directly. */
1572 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1573 break;
1574 by_ref = use_pointer_for_field (decl, ctx);
1575 if (! TREE_READONLY (decl)
1576 || TREE_ADDRESSABLE (decl)
1577 || by_ref
1578 || is_reference (decl))
1580 install_var_field (decl, by_ref, 3, ctx);
1581 install_var_local (decl, ctx);
1582 break;
1584 /* We don't need to copy const scalar vars back. */
1585 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1586 goto do_private;
1588 case OMP_CLAUSE_LASTPRIVATE:
1589 /* Let the corresponding firstprivate clause create
1590 the variable. */
1591 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1592 break;
1593 /* FALLTHRU */
1595 case OMP_CLAUSE_FIRSTPRIVATE:
1596 case OMP_CLAUSE_REDUCTION:
1597 case OMP_CLAUSE_LINEAR:
1598 decl = OMP_CLAUSE_DECL (c);
1599 do_private:
1600 if (is_variable_sized (decl))
1602 if (is_task_ctx (ctx))
1603 install_var_field (decl, false, 1, ctx);
1604 break;
1606 else if (is_taskreg_ctx (ctx))
1608 bool global
1609 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1610 by_ref = use_pointer_for_field (decl, NULL);
1612 if (is_task_ctx (ctx)
1613 && (global || by_ref || is_reference (decl)))
1615 install_var_field (decl, false, 1, ctx);
1616 if (!global)
1617 install_var_field (decl, by_ref, 2, ctx);
1619 else if (!global)
1620 install_var_field (decl, by_ref, 3, ctx);
1622 install_var_local (decl, ctx);
1623 break;
1625 case OMP_CLAUSE__LOOPTEMP_:
1626 gcc_assert (is_parallel_ctx (ctx));
1627 decl = OMP_CLAUSE_DECL (c);
1628 install_var_field (decl, false, 3, ctx);
1629 install_var_local (decl, ctx);
1630 break;
1632 case OMP_CLAUSE_COPYPRIVATE:
1633 case OMP_CLAUSE_COPYIN:
1634 decl = OMP_CLAUSE_DECL (c);
1635 by_ref = use_pointer_for_field (decl, NULL);
1636 install_var_field (decl, by_ref, 3, ctx);
1637 break;
1639 case OMP_CLAUSE_DEFAULT:
1640 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1641 break;
1643 case OMP_CLAUSE_FINAL:
1644 case OMP_CLAUSE_IF:
1645 case OMP_CLAUSE_NUM_THREADS:
1646 case OMP_CLAUSE_NUM_TEAMS:
1647 case OMP_CLAUSE_THREAD_LIMIT:
1648 case OMP_CLAUSE_DEVICE:
1649 case OMP_CLAUSE_SCHEDULE:
1650 case OMP_CLAUSE_DIST_SCHEDULE:
1651 case OMP_CLAUSE_DEPEND:
1652 case OMP_CLAUSE__CILK_FOR_COUNT_:
1653 if (ctx->outer)
1654 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1655 break;
1657 case OMP_CLAUSE_TO:
1658 case OMP_CLAUSE_FROM:
1659 case OMP_CLAUSE_MAP:
1660 if (ctx->outer)
1661 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1662 decl = OMP_CLAUSE_DECL (c);
1663 /* Global variables with "omp declare target" attribute
1664 don't need to be copied, the receiver side will use them
1665 directly. */
1666 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1667 && DECL_P (decl)
1668 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1669 && varpool_node::get_create (decl)->offloadable)
1670 break;
1671 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1672 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1674 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1675 #pragma omp target data, there is nothing to map for
1676 those. */
1677 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1678 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1679 break;
1681 if (DECL_P (decl))
1683 if (DECL_SIZE (decl)
1684 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1686 tree decl2 = DECL_VALUE_EXPR (decl);
1687 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1688 decl2 = TREE_OPERAND (decl2, 0);
1689 gcc_assert (DECL_P (decl2));
1690 install_var_field (decl2, true, 3, ctx);
1691 install_var_local (decl2, ctx);
1692 install_var_local (decl, ctx);
1694 else
1696 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1697 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1698 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1699 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1700 install_var_field (decl, true, 7, ctx);
1701 else
1702 install_var_field (decl, true, 3, ctx);
1703 if (gimple_omp_target_kind (ctx->stmt)
1704 == GF_OMP_TARGET_KIND_REGION)
1705 install_var_local (decl, ctx);
1708 else
1710 tree base = get_base_address (decl);
1711 tree nc = OMP_CLAUSE_CHAIN (c);
1712 if (DECL_P (base)
1713 && nc != NULL_TREE
1714 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1715 && OMP_CLAUSE_DECL (nc) == base
1716 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1717 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1719 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1720 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1722 else
1724 if (ctx->outer)
1726 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1727 decl = OMP_CLAUSE_DECL (c);
1729 gcc_assert (!splay_tree_lookup (ctx->field_map,
1730 (splay_tree_key) decl));
1731 tree field
1732 = build_decl (OMP_CLAUSE_LOCATION (c),
1733 FIELD_DECL, NULL_TREE, ptr_type_node);
1734 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1735 insert_field_into_struct (ctx->record_type, field);
1736 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1737 (splay_tree_value) field);
1740 break;
1742 case OMP_CLAUSE_NOWAIT:
1743 case OMP_CLAUSE_ORDERED:
1744 case OMP_CLAUSE_COLLAPSE:
1745 case OMP_CLAUSE_UNTIED:
1746 case OMP_CLAUSE_MERGEABLE:
1747 case OMP_CLAUSE_PROC_BIND:
1748 case OMP_CLAUSE_SAFELEN:
1749 break;
1751 case OMP_CLAUSE_ALIGNED:
1752 decl = OMP_CLAUSE_DECL (c);
1753 if (is_global_var (decl)
1754 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1755 install_var_local (decl, ctx);
1756 break;
1758 default:
1759 gcc_unreachable ();
1763 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1765 switch (OMP_CLAUSE_CODE (c))
1767 case OMP_CLAUSE_LASTPRIVATE:
1768 /* Let the corresponding firstprivate clause create
1769 the variable. */
1770 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1771 scan_array_reductions = true;
1772 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1773 break;
1774 /* FALLTHRU */
1776 case OMP_CLAUSE_PRIVATE:
1777 case OMP_CLAUSE_FIRSTPRIVATE:
1778 case OMP_CLAUSE_REDUCTION:
1779 case OMP_CLAUSE_LINEAR:
1780 decl = OMP_CLAUSE_DECL (c);
1781 if (is_variable_sized (decl))
1782 install_var_local (decl, ctx);
1783 fixup_remapped_decl (decl, ctx,
1784 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1785 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1786 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1787 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1788 scan_array_reductions = true;
1789 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1790 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1791 scan_array_reductions = true;
1792 break;
1794 case OMP_CLAUSE_SHARED:
1795 /* Ignore shared directives in teams construct. */
1796 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1797 break;
1798 decl = OMP_CLAUSE_DECL (c);
1799 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1800 fixup_remapped_decl (decl, ctx, false);
1801 break;
1803 case OMP_CLAUSE_MAP:
1804 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1805 break;
1806 decl = OMP_CLAUSE_DECL (c);
1807 if (DECL_P (decl)
1808 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1809 && varpool_node::get_create (decl)->offloadable)
1810 break;
1811 if (DECL_P (decl))
1813 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1814 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1815 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1817 tree new_decl = lookup_decl (decl, ctx);
1818 TREE_TYPE (new_decl)
1819 = remap_type (TREE_TYPE (decl), &ctx->cb);
1821 else if (DECL_SIZE (decl)
1822 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1824 tree decl2 = DECL_VALUE_EXPR (decl);
1825 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1826 decl2 = TREE_OPERAND (decl2, 0);
1827 gcc_assert (DECL_P (decl2));
1828 fixup_remapped_decl (decl2, ctx, false);
1829 fixup_remapped_decl (decl, ctx, true);
1831 else
1832 fixup_remapped_decl (decl, ctx, false);
1834 break;
1836 case OMP_CLAUSE_COPYPRIVATE:
1837 case OMP_CLAUSE_COPYIN:
1838 case OMP_CLAUSE_DEFAULT:
1839 case OMP_CLAUSE_IF:
1840 case OMP_CLAUSE_NUM_THREADS:
1841 case OMP_CLAUSE_NUM_TEAMS:
1842 case OMP_CLAUSE_THREAD_LIMIT:
1843 case OMP_CLAUSE_DEVICE:
1844 case OMP_CLAUSE_SCHEDULE:
1845 case OMP_CLAUSE_DIST_SCHEDULE:
1846 case OMP_CLAUSE_NOWAIT:
1847 case OMP_CLAUSE_ORDERED:
1848 case OMP_CLAUSE_COLLAPSE:
1849 case OMP_CLAUSE_UNTIED:
1850 case OMP_CLAUSE_FINAL:
1851 case OMP_CLAUSE_MERGEABLE:
1852 case OMP_CLAUSE_PROC_BIND:
1853 case OMP_CLAUSE_SAFELEN:
1854 case OMP_CLAUSE_ALIGNED:
1855 case OMP_CLAUSE_DEPEND:
1856 case OMP_CLAUSE__LOOPTEMP_:
1857 case OMP_CLAUSE_TO:
1858 case OMP_CLAUSE_FROM:
1859 case OMP_CLAUSE__CILK_FOR_COUNT_:
1860 break;
1862 default:
1863 gcc_unreachable ();
1867 if (scan_array_reductions)
1868 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1869 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1870 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1872 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1873 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1875 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1876 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1877 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1878 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1879 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1880 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1883 /* Create a new name for omp child function. Returns an identifier. If
1884 IS_CILK_FOR is true then the suffix for the child function is
1885 "_cilk_for_fn." */
1887 static tree
1888 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1890 if (is_cilk_for)
1891 return clone_function_name (current_function_decl, "_cilk_for_fn");
1892 return clone_function_name (current_function_decl,
1893 task_copy ? "_omp_cpyfn" : "_omp_fn");
1896 /* Returns the type of the induction variable for the child function for
1897 _Cilk_for and the types for _high and _low variables based on TYPE. */
1899 static tree
1900 cilk_for_check_loop_diff_type (tree type)
1902 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
1904 if (TYPE_UNSIGNED (type))
1905 return uint32_type_node;
1906 else
1907 return integer_type_node;
1909 else
1911 if (TYPE_UNSIGNED (type))
1912 return uint64_type_node;
1913 else
1914 return long_long_integer_type_node;
1918 /* Build a decl for the omp child function. It'll not contain a body
1919 yet, just the bare decl. */
1921 static void
1922 create_omp_child_function (omp_context *ctx, bool task_copy)
1924 tree decl, type, name, t;
1926 tree cilk_for_count
1927 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
1928 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1929 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
1930 tree cilk_var_type = NULL_TREE;
1932 name = create_omp_child_function_name (task_copy,
1933 cilk_for_count != NULL_TREE);
1934 if (task_copy)
1935 type = build_function_type_list (void_type_node, ptr_type_node,
1936 ptr_type_node, NULL_TREE);
1937 else if (cilk_for_count)
1939 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
1940 cilk_var_type = cilk_for_check_loop_diff_type (type);
1941 type = build_function_type_list (void_type_node, ptr_type_node,
1942 cilk_var_type, cilk_var_type, NULL_TREE);
1944 else
1945 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1947 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1949 if (!task_copy)
1950 ctx->cb.dst_fn = decl;
1951 else
1952 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1954 TREE_STATIC (decl) = 1;
1955 TREE_USED (decl) = 1;
1956 DECL_ARTIFICIAL (decl) = 1;
1957 DECL_IGNORED_P (decl) = 0;
1958 TREE_PUBLIC (decl) = 0;
1959 DECL_UNINLINABLE (decl) = 1;
1960 DECL_EXTERNAL (decl) = 0;
1961 DECL_CONTEXT (decl) = NULL_TREE;
1962 DECL_INITIAL (decl) = make_node (BLOCK);
1963 if (cgraph_node::get (current_function_decl)->offloadable)
1964 cgraph_node::get_create (decl)->offloadable = 1;
1965 else
1967 omp_context *octx;
1968 for (octx = ctx; octx; octx = octx->outer)
1969 if (is_targetreg_ctx (octx))
1971 cgraph_node::get_create (decl)->offloadable = 1;
1972 #ifdef ENABLE_OFFLOADING
1973 g->have_offload = true;
1974 #endif
1975 break;
1979 t = build_decl (DECL_SOURCE_LOCATION (decl),
1980 RESULT_DECL, NULL_TREE, void_type_node);
1981 DECL_ARTIFICIAL (t) = 1;
1982 DECL_IGNORED_P (t) = 1;
1983 DECL_CONTEXT (t) = decl;
1984 DECL_RESULT (decl) = t;
1986 /* _Cilk_for's child function requires two extra parameters called
1987 __low and __high that are set the by Cilk runtime when it calls this
1988 function. */
1989 if (cilk_for_count)
1991 t = build_decl (DECL_SOURCE_LOCATION (decl),
1992 PARM_DECL, get_identifier ("__high"), cilk_var_type);
1993 DECL_ARTIFICIAL (t) = 1;
1994 DECL_NAMELESS (t) = 1;
1995 DECL_ARG_TYPE (t) = ptr_type_node;
1996 DECL_CONTEXT (t) = current_function_decl;
1997 TREE_USED (t) = 1;
1998 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1999 DECL_ARGUMENTS (decl) = t;
2001 t = build_decl (DECL_SOURCE_LOCATION (decl),
2002 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2003 DECL_ARTIFICIAL (t) = 1;
2004 DECL_NAMELESS (t) = 1;
2005 DECL_ARG_TYPE (t) = ptr_type_node;
2006 DECL_CONTEXT (t) = current_function_decl;
2007 TREE_USED (t) = 1;
2008 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2009 DECL_ARGUMENTS (decl) = t;
2012 tree data_name = get_identifier (".omp_data_i");
2013 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2014 ptr_type_node);
2015 DECL_ARTIFICIAL (t) = 1;
2016 DECL_NAMELESS (t) = 1;
2017 DECL_ARG_TYPE (t) = ptr_type_node;
2018 DECL_CONTEXT (t) = current_function_decl;
2019 TREE_USED (t) = 1;
2020 if (cilk_for_count)
2021 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2022 DECL_ARGUMENTS (decl) = t;
2023 if (!task_copy)
2024 ctx->receiver_decl = t;
2025 else
2027 t = build_decl (DECL_SOURCE_LOCATION (decl),
2028 PARM_DECL, get_identifier (".omp_data_o"),
2029 ptr_type_node);
2030 DECL_ARTIFICIAL (t) = 1;
2031 DECL_NAMELESS (t) = 1;
2032 DECL_ARG_TYPE (t) = ptr_type_node;
2033 DECL_CONTEXT (t) = current_function_decl;
2034 TREE_USED (t) = 1;
2035 TREE_ADDRESSABLE (t) = 1;
2036 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2037 DECL_ARGUMENTS (decl) = t;
2040 /* Allocate memory for the function structure. The call to
2041 allocate_struct_function clobbers CFUN, so we need to restore
2042 it afterward. */
2043 push_struct_function (decl);
2044 cfun->function_end_locus = gimple_location (ctx->stmt);
2045 pop_cfun ();
2048 /* Callback for walk_gimple_seq. Check if combined parallel
2049 contains gimple_omp_for_combined_into_p OMP_FOR. */
2051 static tree
2052 find_combined_for (gimple_stmt_iterator *gsi_p,
2053 bool *handled_ops_p,
2054 struct walk_stmt_info *wi)
2056 gimple stmt = gsi_stmt (*gsi_p);
2058 *handled_ops_p = true;
2059 switch (gimple_code (stmt))
2061 WALK_SUBSTMTS;
2063 case GIMPLE_OMP_FOR:
2064 if (gimple_omp_for_combined_into_p (stmt)
2065 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2067 wi->info = stmt;
2068 return integer_zero_node;
2070 break;
2071 default:
2072 break;
2074 return NULL;
2077 /* Scan an OpenMP parallel directive. */
2079 static void
2080 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2082 omp_context *ctx;
2083 tree name;
2084 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2086 /* Ignore parallel directives with empty bodies, unless there
2087 are copyin clauses. */
2088 if (optimize > 0
2089 && empty_body_p (gimple_omp_body (stmt))
2090 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2091 OMP_CLAUSE_COPYIN) == NULL)
2093 gsi_replace (gsi, gimple_build_nop (), false);
2094 return;
2097 if (gimple_omp_parallel_combined_p (stmt))
2099 struct walk_stmt_info wi;
2101 memset (&wi, 0, sizeof (wi));
2102 wi.val_only = true;
2103 walk_gimple_seq (gimple_omp_body (stmt),
2104 find_combined_for, NULL, &wi);
2105 if (wi.info)
2107 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2108 struct omp_for_data fd;
2109 extract_omp_for_data (for_stmt, &fd, NULL);
2110 /* We need two temporaries with fd.loop.v type (istart/iend)
2111 and then (fd.collapse - 1) temporaries with the same
2112 type for count2 ... countN-1 vars if not constant. */
2113 size_t count = 2, i;
2114 tree type = fd.iter_type;
2115 if (fd.collapse > 1
2116 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2117 count += fd.collapse - 1;
2118 for (i = 0; i < count; i++)
2120 tree temp = create_tmp_var (type);
2121 tree c = build_omp_clause (UNKNOWN_LOCATION,
2122 OMP_CLAUSE__LOOPTEMP_);
2123 insert_decl_map (&outer_ctx->cb, temp, temp);
2124 OMP_CLAUSE_DECL (c) = temp;
2125 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2126 gimple_omp_parallel_set_clauses (stmt, c);
2131 ctx = new_omp_context (stmt, outer_ctx);
2132 taskreg_contexts.safe_push (ctx);
2133 if (taskreg_nesting_level > 1)
2134 ctx->is_nested = true;
2135 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2136 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2137 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2138 name = create_tmp_var_name (".omp_data_s");
2139 name = build_decl (gimple_location (stmt),
2140 TYPE_DECL, name, ctx->record_type);
2141 DECL_ARTIFICIAL (name) = 1;
2142 DECL_NAMELESS (name) = 1;
2143 TYPE_NAME (ctx->record_type) = name;
2144 create_omp_child_function (ctx, false);
2145 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2147 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2148 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2150 if (TYPE_FIELDS (ctx->record_type) == NULL)
2151 ctx->record_type = ctx->receiver_decl = NULL;
2154 /* Scan an OpenMP task directive. */
2156 static void
2157 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2159 omp_context *ctx;
2160 tree name, t;
2161 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2163 /* Ignore task directives with empty bodies. */
2164 if (optimize > 0
2165 && empty_body_p (gimple_omp_body (stmt)))
2167 gsi_replace (gsi, gimple_build_nop (), false);
2168 return;
2171 ctx = new_omp_context (stmt, outer_ctx);
2172 taskreg_contexts.safe_push (ctx);
2173 if (taskreg_nesting_level > 1)
2174 ctx->is_nested = true;
2175 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2176 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2177 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2178 name = create_tmp_var_name (".omp_data_s");
2179 name = build_decl (gimple_location (stmt),
2180 TYPE_DECL, name, ctx->record_type);
2181 DECL_ARTIFICIAL (name) = 1;
2182 DECL_NAMELESS (name) = 1;
2183 TYPE_NAME (ctx->record_type) = name;
2184 create_omp_child_function (ctx, false);
2185 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2187 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2189 if (ctx->srecord_type)
2191 name = create_tmp_var_name (".omp_data_a");
2192 name = build_decl (gimple_location (stmt),
2193 TYPE_DECL, name, ctx->srecord_type);
2194 DECL_ARTIFICIAL (name) = 1;
2195 DECL_NAMELESS (name) = 1;
2196 TYPE_NAME (ctx->srecord_type) = name;
2197 create_omp_child_function (ctx, true);
2200 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2202 if (TYPE_FIELDS (ctx->record_type) == NULL)
2204 ctx->record_type = ctx->receiver_decl = NULL;
2205 t = build_int_cst (long_integer_type_node, 0);
2206 gimple_omp_task_set_arg_size (stmt, t);
2207 t = build_int_cst (long_integer_type_node, 1);
2208 gimple_omp_task_set_arg_align (stmt, t);
2213 /* If any decls have been made addressable during scan_omp,
2214 adjust their fields if needed, and layout record types
2215 of parallel/task constructs. */
2217 static void
2218 finish_taskreg_scan (omp_context *ctx)
2220 if (ctx->record_type == NULL_TREE)
2221 return;
2223 /* If any task_shared_vars were needed, verify all
2224 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2225 statements if use_pointer_for_field hasn't changed
2226 because of that. If it did, update field types now. */
2227 if (task_shared_vars)
2229 tree c;
2231 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2232 c; c = OMP_CLAUSE_CHAIN (c))
2233 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2235 tree decl = OMP_CLAUSE_DECL (c);
2237 /* Global variables don't need to be copied,
2238 the receiver side will use them directly. */
2239 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2240 continue;
2241 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2242 || !use_pointer_for_field (decl, ctx))
2243 continue;
2244 tree field = lookup_field (decl, ctx);
2245 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2246 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2247 continue;
2248 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2249 TREE_THIS_VOLATILE (field) = 0;
2250 DECL_USER_ALIGN (field) = 0;
2251 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2252 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2253 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2254 if (ctx->srecord_type)
2256 tree sfield = lookup_sfield (decl, ctx);
2257 TREE_TYPE (sfield) = TREE_TYPE (field);
2258 TREE_THIS_VOLATILE (sfield) = 0;
2259 DECL_USER_ALIGN (sfield) = 0;
2260 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2261 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2262 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2267 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2269 layout_type (ctx->record_type);
2270 fixup_child_record_type (ctx);
2272 else
2274 location_t loc = gimple_location (ctx->stmt);
2275 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2276 /* Move VLA fields to the end. */
2277 p = &TYPE_FIELDS (ctx->record_type);
2278 while (*p)
2279 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2280 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2282 *q = *p;
2283 *p = TREE_CHAIN (*p);
2284 TREE_CHAIN (*q) = NULL_TREE;
2285 q = &TREE_CHAIN (*q);
2287 else
2288 p = &DECL_CHAIN (*p);
2289 *p = vla_fields;
2290 layout_type (ctx->record_type);
2291 fixup_child_record_type (ctx);
2292 if (ctx->srecord_type)
2293 layout_type (ctx->srecord_type);
2294 tree t = fold_convert_loc (loc, long_integer_type_node,
2295 TYPE_SIZE_UNIT (ctx->record_type));
2296 gimple_omp_task_set_arg_size (ctx->stmt, t);
2297 t = build_int_cst (long_integer_type_node,
2298 TYPE_ALIGN_UNIT (ctx->record_type));
2299 gimple_omp_task_set_arg_align (ctx->stmt, t);
2304 /* Scan an OpenMP loop directive. */
2306 static void
2307 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2309 omp_context *ctx;
2310 size_t i;
2312 ctx = new_omp_context (stmt, outer_ctx);
2314 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2316 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2317 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2319 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2320 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2321 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2322 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2324 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2327 /* Scan an OpenMP sections directive. */
2329 static void
2330 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2332 omp_context *ctx;
2334 ctx = new_omp_context (stmt, outer_ctx);
2335 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2336 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2339 /* Scan an OpenMP single directive. */
2341 static void
2342 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2344 omp_context *ctx;
2345 tree name;
2347 ctx = new_omp_context (stmt, outer_ctx);
2348 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2349 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2350 name = create_tmp_var_name (".omp_copy_s");
2351 name = build_decl (gimple_location (stmt),
2352 TYPE_DECL, name, ctx->record_type);
2353 TYPE_NAME (ctx->record_type) = name;
2355 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2356 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2358 if (TYPE_FIELDS (ctx->record_type) == NULL)
2359 ctx->record_type = NULL;
2360 else
2361 layout_type (ctx->record_type);
2364 /* Scan an OpenMP target{, data, update} directive. */
2366 static void
2367 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2369 omp_context *ctx;
2370 tree name;
2371 int kind = gimple_omp_target_kind (stmt);
2373 ctx = new_omp_context (stmt, outer_ctx);
2374 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2375 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2376 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2377 name = create_tmp_var_name (".omp_data_t");
2378 name = build_decl (gimple_location (stmt),
2379 TYPE_DECL, name, ctx->record_type);
2380 DECL_ARTIFICIAL (name) = 1;
2381 DECL_NAMELESS (name) = 1;
2382 TYPE_NAME (ctx->record_type) = name;
2383 if (kind == GF_OMP_TARGET_KIND_REGION)
2385 create_omp_child_function (ctx, false);
2386 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2389 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2390 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2392 if (TYPE_FIELDS (ctx->record_type) == NULL)
2393 ctx->record_type = ctx->receiver_decl = NULL;
2394 else
2396 TYPE_FIELDS (ctx->record_type)
2397 = nreverse (TYPE_FIELDS (ctx->record_type));
2398 #ifdef ENABLE_CHECKING
2399 tree field;
2400 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2401 for (field = TYPE_FIELDS (ctx->record_type);
2402 field;
2403 field = DECL_CHAIN (field))
2404 gcc_assert (DECL_ALIGN (field) == align);
2405 #endif
2406 layout_type (ctx->record_type);
2407 if (kind == GF_OMP_TARGET_KIND_REGION)
2408 fixup_child_record_type (ctx);
2412 /* Scan an OpenMP teams directive. */
2414 static void
2415 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2417 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2418 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2419 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2422 /* Check OpenMP nesting restrictions. */
2423 static bool
2424 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2426 if (ctx != NULL)
2428 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2429 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2431 error_at (gimple_location (stmt),
2432 "OpenMP constructs may not be nested inside simd region");
2433 return false;
2435 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2437 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2438 || (gimple_omp_for_kind (stmt)
2439 != GF_OMP_FOR_KIND_DISTRIBUTE))
2440 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2442 error_at (gimple_location (stmt),
2443 "only distribute or parallel constructs are allowed to "
2444 "be closely nested inside teams construct");
2445 return false;
2449 switch (gimple_code (stmt))
2451 case GIMPLE_OMP_FOR:
2452 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2453 return true;
2454 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2456 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2458 error_at (gimple_location (stmt),
2459 "distribute construct must be closely nested inside "
2460 "teams construct");
2461 return false;
2463 return true;
2465 /* FALLTHRU */
2466 case GIMPLE_CALL:
2467 if (is_gimple_call (stmt)
2468 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2469 == BUILT_IN_GOMP_CANCEL
2470 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2471 == BUILT_IN_GOMP_CANCELLATION_POINT))
2473 const char *bad = NULL;
2474 const char *kind = NULL;
2475 if (ctx == NULL)
2477 error_at (gimple_location (stmt), "orphaned %qs construct",
2478 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2479 == BUILT_IN_GOMP_CANCEL
2480 ? "#pragma omp cancel"
2481 : "#pragma omp cancellation point");
2482 return false;
2484 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2485 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2486 : 0)
2488 case 1:
2489 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2490 bad = "#pragma omp parallel";
2491 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2492 == BUILT_IN_GOMP_CANCEL
2493 && !integer_zerop (gimple_call_arg (stmt, 1)))
2494 ctx->cancellable = true;
2495 kind = "parallel";
2496 break;
2497 case 2:
2498 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2499 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2500 bad = "#pragma omp for";
2501 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2502 == BUILT_IN_GOMP_CANCEL
2503 && !integer_zerop (gimple_call_arg (stmt, 1)))
2505 ctx->cancellable = true;
2506 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2507 OMP_CLAUSE_NOWAIT))
2508 warning_at (gimple_location (stmt), 0,
2509 "%<#pragma omp cancel for%> inside "
2510 "%<nowait%> for construct");
2511 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2512 OMP_CLAUSE_ORDERED))
2513 warning_at (gimple_location (stmt), 0,
2514 "%<#pragma omp cancel for%> inside "
2515 "%<ordered%> for construct");
2517 kind = "for";
2518 break;
2519 case 4:
2520 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2521 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2522 bad = "#pragma omp sections";
2523 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2524 == BUILT_IN_GOMP_CANCEL
2525 && !integer_zerop (gimple_call_arg (stmt, 1)))
2527 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2529 ctx->cancellable = true;
2530 if (find_omp_clause (gimple_omp_sections_clauses
2531 (ctx->stmt),
2532 OMP_CLAUSE_NOWAIT))
2533 warning_at (gimple_location (stmt), 0,
2534 "%<#pragma omp cancel sections%> inside "
2535 "%<nowait%> sections construct");
2537 else
2539 gcc_assert (ctx->outer
2540 && gimple_code (ctx->outer->stmt)
2541 == GIMPLE_OMP_SECTIONS);
2542 ctx->outer->cancellable = true;
2543 if (find_omp_clause (gimple_omp_sections_clauses
2544 (ctx->outer->stmt),
2545 OMP_CLAUSE_NOWAIT))
2546 warning_at (gimple_location (stmt), 0,
2547 "%<#pragma omp cancel sections%> inside "
2548 "%<nowait%> sections construct");
2551 kind = "sections";
2552 break;
2553 case 8:
2554 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2555 bad = "#pragma omp task";
2556 else
2557 ctx->cancellable = true;
2558 kind = "taskgroup";
2559 break;
2560 default:
2561 error_at (gimple_location (stmt), "invalid arguments");
2562 return false;
2564 if (bad)
2566 error_at (gimple_location (stmt),
2567 "%<%s %s%> construct not closely nested inside of %qs",
2568 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2569 == BUILT_IN_GOMP_CANCEL
2570 ? "#pragma omp cancel"
2571 : "#pragma omp cancellation point", kind, bad);
2572 return false;
2575 /* FALLTHRU */
2576 case GIMPLE_OMP_SECTIONS:
2577 case GIMPLE_OMP_SINGLE:
2578 for (; ctx != NULL; ctx = ctx->outer)
2579 switch (gimple_code (ctx->stmt))
2581 case GIMPLE_OMP_FOR:
2582 case GIMPLE_OMP_SECTIONS:
2583 case GIMPLE_OMP_SINGLE:
2584 case GIMPLE_OMP_ORDERED:
2585 case GIMPLE_OMP_MASTER:
2586 case GIMPLE_OMP_TASK:
2587 case GIMPLE_OMP_CRITICAL:
2588 if (is_gimple_call (stmt))
2590 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2591 != BUILT_IN_GOMP_BARRIER)
2592 return true;
2593 error_at (gimple_location (stmt),
2594 "barrier region may not be closely nested inside "
2595 "of work-sharing, critical, ordered, master or "
2596 "explicit task region");
2597 return false;
2599 error_at (gimple_location (stmt),
2600 "work-sharing region may not be closely nested inside "
2601 "of work-sharing, critical, ordered, master or explicit "
2602 "task region");
2603 return false;
2604 case GIMPLE_OMP_PARALLEL:
2605 return true;
2606 default:
2607 break;
2609 break;
2610 case GIMPLE_OMP_MASTER:
2611 for (; ctx != NULL; ctx = ctx->outer)
2612 switch (gimple_code (ctx->stmt))
2614 case GIMPLE_OMP_FOR:
2615 case GIMPLE_OMP_SECTIONS:
2616 case GIMPLE_OMP_SINGLE:
2617 case GIMPLE_OMP_TASK:
2618 error_at (gimple_location (stmt),
2619 "master region may not be closely nested inside "
2620 "of work-sharing or explicit task region");
2621 return false;
2622 case GIMPLE_OMP_PARALLEL:
2623 return true;
2624 default:
2625 break;
2627 break;
2628 case GIMPLE_OMP_ORDERED:
2629 for (; ctx != NULL; ctx = ctx->outer)
2630 switch (gimple_code (ctx->stmt))
2632 case GIMPLE_OMP_CRITICAL:
2633 case GIMPLE_OMP_TASK:
2634 error_at (gimple_location (stmt),
2635 "ordered region may not be closely nested inside "
2636 "of critical or explicit task region");
2637 return false;
2638 case GIMPLE_OMP_FOR:
2639 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2640 OMP_CLAUSE_ORDERED) == NULL)
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;
2647 return true;
2648 case GIMPLE_OMP_PARALLEL:
2649 error_at (gimple_location (stmt),
2650 "ordered region must be closely nested inside "
2651 "a loop region with an ordered clause");
2652 return false;
2653 default:
2654 break;
2656 break;
2657 case GIMPLE_OMP_CRITICAL:
2659 tree this_stmt_name
2660 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2661 for (; ctx != NULL; ctx = ctx->outer)
2662 if (gomp_critical *other_crit
2663 = dyn_cast <gomp_critical *> (ctx->stmt))
2664 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2666 error_at (gimple_location (stmt),
2667 "critical region may not be nested inside a critical "
2668 "region with the same name");
2669 return false;
2672 break;
2673 case GIMPLE_OMP_TEAMS:
2674 if (ctx == NULL
2675 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2676 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2678 error_at (gimple_location (stmt),
2679 "teams construct not closely nested inside of target "
2680 "region");
2681 return false;
2683 break;
2684 case GIMPLE_OMP_TARGET:
2685 for (; ctx != NULL; ctx = ctx->outer)
2686 if (is_targetreg_ctx (ctx))
2688 const char *name;
2689 switch (gimple_omp_target_kind (stmt))
2691 case GF_OMP_TARGET_KIND_REGION: name = "target"; break;
2692 case GF_OMP_TARGET_KIND_DATA: name = "target data"; break;
2693 case GF_OMP_TARGET_KIND_UPDATE: name = "target update"; break;
2694 default: gcc_unreachable ();
2696 warning_at (gimple_location (stmt), 0,
2697 "%s construct inside of target region", name);
2699 break;
2700 default:
2701 break;
2703 return true;
2707 /* Helper function scan_omp.
2709 Callback for walk_tree or operators in walk_gimple_stmt used to
2710 scan for OpenMP directives in TP. */
2712 static tree
2713 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2715 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2716 omp_context *ctx = (omp_context *) wi->info;
2717 tree t = *tp;
2719 switch (TREE_CODE (t))
2721 case VAR_DECL:
2722 case PARM_DECL:
2723 case LABEL_DECL:
2724 case RESULT_DECL:
2725 if (ctx)
2726 *tp = remap_decl (t, &ctx->cb);
2727 break;
2729 default:
2730 if (ctx && TYPE_P (t))
2731 *tp = remap_type (t, &ctx->cb);
2732 else if (!DECL_P (t))
2734 *walk_subtrees = 1;
2735 if (ctx)
2737 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2738 if (tem != TREE_TYPE (t))
2740 if (TREE_CODE (t) == INTEGER_CST)
2741 *tp = wide_int_to_tree (tem, t);
2742 else
2743 TREE_TYPE (t) = tem;
2747 break;
2750 return NULL_TREE;
2753 /* Return true if FNDECL is a setjmp or a longjmp. */
2755 static bool
2756 setjmp_or_longjmp_p (const_tree fndecl)
2758 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2759 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2760 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2761 return true;
2763 tree declname = DECL_NAME (fndecl);
2764 if (!declname)
2765 return false;
2766 const char *name = IDENTIFIER_POINTER (declname);
2767 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2771 /* Helper function for scan_omp.
2773 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2774 the current statement in GSI. */
2776 static tree
2777 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2778 struct walk_stmt_info *wi)
2780 gimple stmt = gsi_stmt (*gsi);
2781 omp_context *ctx = (omp_context *) wi->info;
2783 if (gimple_has_location (stmt))
2784 input_location = gimple_location (stmt);
2786 /* Check the OpenMP nesting restrictions. */
2787 bool remove = false;
2788 if (is_gimple_omp (stmt))
2789 remove = !check_omp_nesting_restrictions (stmt, ctx);
2790 else if (is_gimple_call (stmt))
2792 tree fndecl = gimple_call_fndecl (stmt);
2793 if (fndecl)
2795 if (setjmp_or_longjmp_p (fndecl)
2796 && ctx
2797 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2798 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2800 remove = true;
2801 error_at (gimple_location (stmt),
2802 "setjmp/longjmp inside simd construct");
2804 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2805 switch (DECL_FUNCTION_CODE (fndecl))
2807 case BUILT_IN_GOMP_BARRIER:
2808 case BUILT_IN_GOMP_CANCEL:
2809 case BUILT_IN_GOMP_CANCELLATION_POINT:
2810 case BUILT_IN_GOMP_TASKYIELD:
2811 case BUILT_IN_GOMP_TASKWAIT:
2812 case BUILT_IN_GOMP_TASKGROUP_START:
2813 case BUILT_IN_GOMP_TASKGROUP_END:
2814 remove = !check_omp_nesting_restrictions (stmt, ctx);
2815 break;
2816 default:
2817 break;
2821 if (remove)
2823 stmt = gimple_build_nop ();
2824 gsi_replace (gsi, stmt, false);
2827 *handled_ops_p = true;
2829 switch (gimple_code (stmt))
2831 case GIMPLE_OMP_PARALLEL:
2832 taskreg_nesting_level++;
2833 scan_omp_parallel (gsi, ctx);
2834 taskreg_nesting_level--;
2835 break;
2837 case GIMPLE_OMP_TASK:
2838 taskreg_nesting_level++;
2839 scan_omp_task (gsi, ctx);
2840 taskreg_nesting_level--;
2841 break;
2843 case GIMPLE_OMP_FOR:
2844 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
2845 break;
2847 case GIMPLE_OMP_SECTIONS:
2848 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
2849 break;
2851 case GIMPLE_OMP_SINGLE:
2852 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
2853 break;
2855 case GIMPLE_OMP_SECTION:
2856 case GIMPLE_OMP_MASTER:
2857 case GIMPLE_OMP_TASKGROUP:
2858 case GIMPLE_OMP_ORDERED:
2859 case GIMPLE_OMP_CRITICAL:
2860 ctx = new_omp_context (stmt, ctx);
2861 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2862 break;
2864 case GIMPLE_OMP_TARGET:
2865 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
2866 break;
2868 case GIMPLE_OMP_TEAMS:
2869 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
2870 break;
2872 case GIMPLE_BIND:
2874 tree var;
2876 *handled_ops_p = false;
2877 if (ctx)
2878 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
2879 var ;
2880 var = DECL_CHAIN (var))
2881 insert_decl_map (&ctx->cb, var, var);
2883 break;
2884 default:
2885 *handled_ops_p = false;
2886 break;
2889 return NULL_TREE;
2893 /* Scan all the statements starting at the current statement. CTX
2894 contains context information about the OpenMP directives and
2895 clauses found during the scan. */
2897 static void
2898 scan_omp (gimple_seq *body_p, omp_context *ctx)
2900 location_t saved_location;
2901 struct walk_stmt_info wi;
2903 memset (&wi, 0, sizeof (wi));
2904 wi.info = ctx;
2905 wi.want_locations = true;
2907 saved_location = input_location;
2908 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2909 input_location = saved_location;
2912 /* Re-gimplification and code generation routines. */
2914 /* Build a call to GOMP_barrier. */
2916 static gimple
2917 build_omp_barrier (tree lhs)
2919 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2920 : BUILT_IN_GOMP_BARRIER);
2921 gcall *g = gimple_build_call (fndecl, 0);
2922 if (lhs)
2923 gimple_call_set_lhs (g, lhs);
2924 return g;
2927 /* If a context was created for STMT when it was scanned, return it. */
2929 static omp_context *
2930 maybe_lookup_ctx (gimple stmt)
2932 splay_tree_node n;
2933 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2934 return n ? (omp_context *) n->value : NULL;
2938 /* Find the mapping for DECL in CTX or the immediately enclosing
2939 context that has a mapping for DECL.
2941 If CTX is a nested parallel directive, we may have to use the decl
2942 mappings created in CTX's parent context. Suppose that we have the
2943 following parallel nesting (variable UIDs showed for clarity):
2945 iD.1562 = 0;
2946 #omp parallel shared(iD.1562) -> outer parallel
2947 iD.1562 = iD.1562 + 1;
2949 #omp parallel shared (iD.1562) -> inner parallel
2950 iD.1562 = iD.1562 - 1;
2952 Each parallel structure will create a distinct .omp_data_s structure
2953 for copying iD.1562 in/out of the directive:
2955 outer parallel .omp_data_s.1.i -> iD.1562
2956 inner parallel .omp_data_s.2.i -> iD.1562
2958 A shared variable mapping will produce a copy-out operation before
2959 the parallel directive and a copy-in operation after it. So, in
2960 this case we would have:
2962 iD.1562 = 0;
2963 .omp_data_o.1.i = iD.1562;
2964 #omp parallel shared(iD.1562) -> outer parallel
2965 .omp_data_i.1 = &.omp_data_o.1
2966 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2968 .omp_data_o.2.i = iD.1562; -> **
2969 #omp parallel shared(iD.1562) -> inner parallel
2970 .omp_data_i.2 = &.omp_data_o.2
2971 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2974 ** This is a problem. The symbol iD.1562 cannot be referenced
2975 inside the body of the outer parallel region. But since we are
2976 emitting this copy operation while expanding the inner parallel
2977 directive, we need to access the CTX structure of the outer
2978 parallel directive to get the correct mapping:
2980 .omp_data_o.2.i = .omp_data_i.1->i
2982 Since there may be other workshare or parallel directives enclosing
2983 the parallel directive, it may be necessary to walk up the context
2984 parent chain. This is not a problem in general because nested
2985 parallelism happens only rarely. */
2987 static tree
2988 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2990 tree t;
2991 omp_context *up;
2993 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2994 t = maybe_lookup_decl (decl, up);
2996 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2998 return t ? t : decl;
3002 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3003 in outer contexts. */
3005 static tree
3006 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3008 tree t = NULL;
3009 omp_context *up;
3011 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3012 t = maybe_lookup_decl (decl, up);
3014 return t ? t : decl;
3018 /* Construct the initialization value for reduction CLAUSE. */
3020 tree
3021 omp_reduction_init (tree clause, tree type)
3023 location_t loc = OMP_CLAUSE_LOCATION (clause);
3024 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3026 case PLUS_EXPR:
3027 case MINUS_EXPR:
3028 case BIT_IOR_EXPR:
3029 case BIT_XOR_EXPR:
3030 case TRUTH_OR_EXPR:
3031 case TRUTH_ORIF_EXPR:
3032 case TRUTH_XOR_EXPR:
3033 case NE_EXPR:
3034 return build_zero_cst (type);
3036 case MULT_EXPR:
3037 case TRUTH_AND_EXPR:
3038 case TRUTH_ANDIF_EXPR:
3039 case EQ_EXPR:
3040 return fold_convert_loc (loc, type, integer_one_node);
3042 case BIT_AND_EXPR:
3043 return fold_convert_loc (loc, type, integer_minus_one_node);
3045 case MAX_EXPR:
3046 if (SCALAR_FLOAT_TYPE_P (type))
3048 REAL_VALUE_TYPE max, min;
3049 if (HONOR_INFINITIES (type))
3051 real_inf (&max);
3052 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3054 else
3055 real_maxval (&min, 1, TYPE_MODE (type));
3056 return build_real (type, min);
3058 else
3060 gcc_assert (INTEGRAL_TYPE_P (type));
3061 return TYPE_MIN_VALUE (type);
3064 case MIN_EXPR:
3065 if (SCALAR_FLOAT_TYPE_P (type))
3067 REAL_VALUE_TYPE max;
3068 if (HONOR_INFINITIES (type))
3069 real_inf (&max);
3070 else
3071 real_maxval (&max, 0, TYPE_MODE (type));
3072 return build_real (type, max);
3074 else
3076 gcc_assert (INTEGRAL_TYPE_P (type));
3077 return TYPE_MAX_VALUE (type);
3080 default:
3081 gcc_unreachable ();
3085 /* Return alignment to be assumed for var in CLAUSE, which should be
3086 OMP_CLAUSE_ALIGNED. */
3088 static tree
3089 omp_clause_aligned_alignment (tree clause)
3091 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3092 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3094 /* Otherwise return implementation defined alignment. */
3095 unsigned int al = 1;
3096 machine_mode mode, vmode;
3097 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3098 if (vs)
3099 vs = 1 << floor_log2 (vs);
3100 static enum mode_class classes[]
3101 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3102 for (int i = 0; i < 4; i += 2)
3103 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3104 mode != VOIDmode;
3105 mode = GET_MODE_WIDER_MODE (mode))
3107 vmode = targetm.vectorize.preferred_simd_mode (mode);
3108 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3109 continue;
3110 while (vs
3111 && GET_MODE_SIZE (vmode) < vs
3112 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3113 vmode = GET_MODE_2XWIDER_MODE (vmode);
3115 tree type = lang_hooks.types.type_for_mode (mode, 1);
3116 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3117 continue;
3118 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3119 / GET_MODE_SIZE (mode));
3120 if (TYPE_MODE (type) != vmode)
3121 continue;
3122 if (TYPE_ALIGN_UNIT (type) > al)
3123 al = TYPE_ALIGN_UNIT (type);
3125 return build_int_cst (integer_type_node, al);
3128 /* Return maximum possible vectorization factor for the target. */
3130 static int
3131 omp_max_vf (void)
3133 if (!optimize
3134 || optimize_debug
3135 || !flag_tree_loop_optimize
3136 || (!flag_tree_loop_vectorize
3137 && (global_options_set.x_flag_tree_loop_vectorize
3138 || global_options_set.x_flag_tree_vectorize)))
3139 return 1;
3141 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3142 if (vs)
3144 vs = 1 << floor_log2 (vs);
3145 return vs;
3147 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3148 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3149 return GET_MODE_NUNITS (vqimode);
3150 return 1;
3153 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3154 privatization. */
3156 static bool
3157 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3158 tree &idx, tree &lane, tree &ivar, tree &lvar)
3160 if (max_vf == 0)
3162 max_vf = omp_max_vf ();
3163 if (max_vf > 1)
3165 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3166 OMP_CLAUSE_SAFELEN);
3167 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3168 max_vf = 1;
3169 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3170 max_vf) == -1)
3171 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3173 if (max_vf > 1)
3175 idx = create_tmp_var (unsigned_type_node);
3176 lane = create_tmp_var (unsigned_type_node);
3179 if (max_vf == 1)
3180 return false;
3182 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3183 tree avar = create_tmp_var_raw (atype);
3184 if (TREE_ADDRESSABLE (new_var))
3185 TREE_ADDRESSABLE (avar) = 1;
3186 DECL_ATTRIBUTES (avar)
3187 = tree_cons (get_identifier ("omp simd array"), NULL,
3188 DECL_ATTRIBUTES (avar));
3189 gimple_add_tmp_var (avar);
3190 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3191 NULL_TREE, NULL_TREE);
3192 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3193 NULL_TREE, NULL_TREE);
3194 if (DECL_P (new_var))
3196 SET_DECL_VALUE_EXPR (new_var, lvar);
3197 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3199 return true;
3202 /* Helper function of lower_rec_input_clauses. For a reference
3203 in simd reduction, add an underlying variable it will reference. */
3205 static void
3206 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3208 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3209 if (TREE_CONSTANT (z))
3211 const char *name = NULL;
3212 if (DECL_NAME (new_vard))
3213 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3215 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3216 gimple_add_tmp_var (z);
3217 TREE_ADDRESSABLE (z) = 1;
3218 z = build_fold_addr_expr_loc (loc, z);
3219 gimplify_assign (new_vard, z, ilist);
3223 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3224 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3225 private variables. Initialization statements go in ILIST, while calls
3226 to destructors go in DLIST. */
3228 static void
3229 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3230 omp_context *ctx, struct omp_for_data *fd)
3232 tree c, dtor, copyin_seq, x, ptr;
3233 bool copyin_by_ref = false;
3234 bool lastprivate_firstprivate = false;
3235 bool reduction_omp_orig_ref = false;
3236 int pass;
3237 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3238 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3239 int max_vf = 0;
3240 tree lane = NULL_TREE, idx = NULL_TREE;
3241 tree ivar = NULL_TREE, lvar = NULL_TREE;
3242 gimple_seq llist[2] = { NULL, NULL };
3244 copyin_seq = NULL;
3246 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3247 with data sharing clauses referencing variable sized vars. That
3248 is unnecessarily hard to support and very unlikely to result in
3249 vectorized code anyway. */
3250 if (is_simd)
3251 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3252 switch (OMP_CLAUSE_CODE (c))
3254 case OMP_CLAUSE_LINEAR:
3255 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3256 max_vf = 1;
3257 /* FALLTHRU */
3258 case OMP_CLAUSE_REDUCTION:
3259 case OMP_CLAUSE_PRIVATE:
3260 case OMP_CLAUSE_FIRSTPRIVATE:
3261 case OMP_CLAUSE_LASTPRIVATE:
3262 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3263 max_vf = 1;
3264 break;
3265 default:
3266 continue;
3269 /* Do all the fixed sized types in the first pass, and the variable sized
3270 types in the second pass. This makes sure that the scalar arguments to
3271 the variable sized types are processed before we use them in the
3272 variable sized operations. */
3273 for (pass = 0; pass < 2; ++pass)
3275 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3277 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3278 tree var, new_var;
3279 bool by_ref;
3280 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3282 switch (c_kind)
3284 case OMP_CLAUSE_PRIVATE:
3285 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3286 continue;
3287 break;
3288 case OMP_CLAUSE_SHARED:
3289 /* Ignore shared directives in teams construct. */
3290 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3291 continue;
3292 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3294 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3295 continue;
3297 case OMP_CLAUSE_FIRSTPRIVATE:
3298 case OMP_CLAUSE_COPYIN:
3299 case OMP_CLAUSE_LINEAR:
3300 break;
3301 case OMP_CLAUSE_REDUCTION:
3302 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3303 reduction_omp_orig_ref = true;
3304 break;
3305 case OMP_CLAUSE__LOOPTEMP_:
3306 /* Handle _looptemp_ clauses only on parallel. */
3307 if (fd)
3308 continue;
3309 break;
3310 case OMP_CLAUSE_LASTPRIVATE:
3311 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3313 lastprivate_firstprivate = true;
3314 if (pass != 0)
3315 continue;
3317 /* Even without corresponding firstprivate, if
3318 decl is Fortran allocatable, it needs outer var
3319 reference. */
3320 else if (pass == 0
3321 && lang_hooks.decls.omp_private_outer_ref
3322 (OMP_CLAUSE_DECL (c)))
3323 lastprivate_firstprivate = true;
3324 break;
3325 case OMP_CLAUSE_ALIGNED:
3326 if (pass == 0)
3327 continue;
3328 var = OMP_CLAUSE_DECL (c);
3329 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3330 && !is_global_var (var))
3332 new_var = maybe_lookup_decl (var, ctx);
3333 if (new_var == NULL_TREE)
3334 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3335 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3336 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3337 omp_clause_aligned_alignment (c));
3338 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3339 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3340 gimplify_and_add (x, ilist);
3342 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3343 && is_global_var (var))
3345 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3346 new_var = lookup_decl (var, ctx);
3347 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3348 t = build_fold_addr_expr_loc (clause_loc, t);
3349 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3350 t = build_call_expr_loc (clause_loc, t2, 2, t,
3351 omp_clause_aligned_alignment (c));
3352 t = fold_convert_loc (clause_loc, ptype, t);
3353 x = create_tmp_var (ptype);
3354 t = build2 (MODIFY_EXPR, ptype, x, t);
3355 gimplify_and_add (t, ilist);
3356 t = build_simple_mem_ref_loc (clause_loc, x);
3357 SET_DECL_VALUE_EXPR (new_var, t);
3358 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3360 continue;
3361 default:
3362 continue;
3365 new_var = var = OMP_CLAUSE_DECL (c);
3366 if (c_kind != OMP_CLAUSE_COPYIN)
3367 new_var = lookup_decl (var, ctx);
3369 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3371 if (pass != 0)
3372 continue;
3374 else if (is_variable_sized (var))
3376 /* For variable sized types, we need to allocate the
3377 actual storage here. Call alloca and store the
3378 result in the pointer decl that we created elsewhere. */
3379 if (pass == 0)
3380 continue;
3382 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3384 gcall *stmt;
3385 tree tmp, atmp;
3387 ptr = DECL_VALUE_EXPR (new_var);
3388 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3389 ptr = TREE_OPERAND (ptr, 0);
3390 gcc_assert (DECL_P (ptr));
3391 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3393 /* void *tmp = __builtin_alloca */
3394 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3395 stmt = gimple_build_call (atmp, 1, x);
3396 tmp = create_tmp_var_raw (ptr_type_node);
3397 gimple_add_tmp_var (tmp);
3398 gimple_call_set_lhs (stmt, tmp);
3400 gimple_seq_add_stmt (ilist, stmt);
3402 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3403 gimplify_assign (ptr, x, ilist);
3406 else if (is_reference (var))
3408 /* For references that are being privatized for Fortran,
3409 allocate new backing storage for the new pointer
3410 variable. This allows us to avoid changing all the
3411 code that expects a pointer to something that expects
3412 a direct variable. */
3413 if (pass == 0)
3414 continue;
3416 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3417 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3419 x = build_receiver_ref (var, false, ctx);
3420 x = build_fold_addr_expr_loc (clause_loc, x);
3422 else if (TREE_CONSTANT (x))
3424 /* For reduction in SIMD loop, defer adding the
3425 initialization of the reference, because if we decide
3426 to use SIMD array for it, the initilization could cause
3427 expansion ICE. */
3428 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3429 x = NULL_TREE;
3430 else
3432 const char *name = NULL;
3433 if (DECL_NAME (var))
3434 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3436 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3437 name);
3438 gimple_add_tmp_var (x);
3439 TREE_ADDRESSABLE (x) = 1;
3440 x = build_fold_addr_expr_loc (clause_loc, x);
3443 else
3445 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3446 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3449 if (x)
3451 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3452 gimplify_assign (new_var, x, ilist);
3455 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3457 else if (c_kind == OMP_CLAUSE_REDUCTION
3458 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3460 if (pass == 0)
3461 continue;
3463 else if (pass != 0)
3464 continue;
3466 switch (OMP_CLAUSE_CODE (c))
3468 case OMP_CLAUSE_SHARED:
3469 /* Ignore shared directives in teams construct. */
3470 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3471 continue;
3472 /* Shared global vars are just accessed directly. */
3473 if (is_global_var (new_var))
3474 break;
3475 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3476 needs to be delayed until after fixup_child_record_type so
3477 that we get the correct type during the dereference. */
3478 by_ref = use_pointer_for_field (var, ctx);
3479 x = build_receiver_ref (var, by_ref, ctx);
3480 SET_DECL_VALUE_EXPR (new_var, x);
3481 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3483 /* ??? If VAR is not passed by reference, and the variable
3484 hasn't been initialized yet, then we'll get a warning for
3485 the store into the omp_data_s structure. Ideally, we'd be
3486 able to notice this and not store anything at all, but
3487 we're generating code too early. Suppress the warning. */
3488 if (!by_ref)
3489 TREE_NO_WARNING (var) = 1;
3490 break;
3492 case OMP_CLAUSE_LASTPRIVATE:
3493 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3494 break;
3495 /* FALLTHRU */
3497 case OMP_CLAUSE_PRIVATE:
3498 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3499 x = build_outer_var_ref (var, ctx);
3500 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3502 if (is_task_ctx (ctx))
3503 x = build_receiver_ref (var, false, ctx);
3504 else
3505 x = build_outer_var_ref (var, ctx);
3507 else
3508 x = NULL;
3509 do_private:
3510 tree nx;
3511 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3512 if (is_simd)
3514 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3515 if ((TREE_ADDRESSABLE (new_var) || nx || y
3516 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3517 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3518 idx, lane, ivar, lvar))
3520 if (nx)
3521 x = lang_hooks.decls.omp_clause_default_ctor
3522 (c, unshare_expr (ivar), x);
3523 if (nx && x)
3524 gimplify_and_add (x, &llist[0]);
3525 if (y)
3527 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3528 if (y)
3530 gimple_seq tseq = NULL;
3532 dtor = y;
3533 gimplify_stmt (&dtor, &tseq);
3534 gimple_seq_add_seq (&llist[1], tseq);
3537 break;
3540 if (nx)
3541 gimplify_and_add (nx, ilist);
3542 /* FALLTHRU */
3544 do_dtor:
3545 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3546 if (x)
3548 gimple_seq tseq = NULL;
3550 dtor = x;
3551 gimplify_stmt (&dtor, &tseq);
3552 gimple_seq_add_seq (dlist, tseq);
3554 break;
3556 case OMP_CLAUSE_LINEAR:
3557 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3558 goto do_firstprivate;
3559 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3560 x = NULL;
3561 else
3562 x = build_outer_var_ref (var, ctx);
3563 goto do_private;
3565 case OMP_CLAUSE_FIRSTPRIVATE:
3566 if (is_task_ctx (ctx))
3568 if (is_reference (var) || is_variable_sized (var))
3569 goto do_dtor;
3570 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3571 ctx))
3572 || use_pointer_for_field (var, NULL))
3574 x = build_receiver_ref (var, false, ctx);
3575 SET_DECL_VALUE_EXPR (new_var, x);
3576 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3577 goto do_dtor;
3580 do_firstprivate:
3581 x = build_outer_var_ref (var, ctx);
3582 if (is_simd)
3584 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3585 && gimple_omp_for_combined_into_p (ctx->stmt))
3587 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3588 tree stept = TREE_TYPE (t);
3589 tree ct = find_omp_clause (clauses,
3590 OMP_CLAUSE__LOOPTEMP_);
3591 gcc_assert (ct);
3592 tree l = OMP_CLAUSE_DECL (ct);
3593 tree n1 = fd->loop.n1;
3594 tree step = fd->loop.step;
3595 tree itype = TREE_TYPE (l);
3596 if (POINTER_TYPE_P (itype))
3597 itype = signed_type_for (itype);
3598 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3599 if (TYPE_UNSIGNED (itype)
3600 && fd->loop.cond_code == GT_EXPR)
3601 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3602 fold_build1 (NEGATE_EXPR, itype, l),
3603 fold_build1 (NEGATE_EXPR,
3604 itype, step));
3605 else
3606 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3607 t = fold_build2 (MULT_EXPR, stept,
3608 fold_convert (stept, l), t);
3610 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3612 x = lang_hooks.decls.omp_clause_linear_ctor
3613 (c, new_var, x, t);
3614 gimplify_and_add (x, ilist);
3615 goto do_dtor;
3618 if (POINTER_TYPE_P (TREE_TYPE (x)))
3619 x = fold_build2 (POINTER_PLUS_EXPR,
3620 TREE_TYPE (x), x, t);
3621 else
3622 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3625 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3626 || TREE_ADDRESSABLE (new_var))
3627 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3628 idx, lane, ivar, lvar))
3630 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3632 tree iv = create_tmp_var (TREE_TYPE (new_var));
3633 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3634 gimplify_and_add (x, ilist);
3635 gimple_stmt_iterator gsi
3636 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3637 gassign *g
3638 = gimple_build_assign (unshare_expr (lvar), iv);
3639 gsi_insert_before_without_update (&gsi, g,
3640 GSI_SAME_STMT);
3641 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3642 enum tree_code code = PLUS_EXPR;
3643 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3644 code = POINTER_PLUS_EXPR;
3645 g = gimple_build_assign (iv, code, iv, t);
3646 gsi_insert_before_without_update (&gsi, g,
3647 GSI_SAME_STMT);
3648 break;
3650 x = lang_hooks.decls.omp_clause_copy_ctor
3651 (c, unshare_expr (ivar), x);
3652 gimplify_and_add (x, &llist[0]);
3653 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3654 if (x)
3656 gimple_seq tseq = NULL;
3658 dtor = x;
3659 gimplify_stmt (&dtor, &tseq);
3660 gimple_seq_add_seq (&llist[1], tseq);
3662 break;
3665 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3666 gimplify_and_add (x, ilist);
3667 goto do_dtor;
3669 case OMP_CLAUSE__LOOPTEMP_:
3670 gcc_assert (is_parallel_ctx (ctx));
3671 x = build_outer_var_ref (var, ctx);
3672 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3673 gimplify_and_add (x, ilist);
3674 break;
3676 case OMP_CLAUSE_COPYIN:
3677 by_ref = use_pointer_for_field (var, NULL);
3678 x = build_receiver_ref (var, by_ref, ctx);
3679 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3680 append_to_statement_list (x, &copyin_seq);
3681 copyin_by_ref |= by_ref;
3682 break;
3684 case OMP_CLAUSE_REDUCTION:
3685 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3687 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3688 gimple tseq;
3689 x = build_outer_var_ref (var, ctx);
3691 if (is_reference (var)
3692 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3693 TREE_TYPE (x)))
3694 x = build_fold_addr_expr_loc (clause_loc, x);
3695 SET_DECL_VALUE_EXPR (placeholder, x);
3696 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3697 tree new_vard = new_var;
3698 if (is_reference (var))
3700 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3701 new_vard = TREE_OPERAND (new_var, 0);
3702 gcc_assert (DECL_P (new_vard));
3704 if (is_simd
3705 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3706 idx, lane, ivar, lvar))
3708 if (new_vard == new_var)
3710 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3711 SET_DECL_VALUE_EXPR (new_var, ivar);
3713 else
3715 SET_DECL_VALUE_EXPR (new_vard,
3716 build_fold_addr_expr (ivar));
3717 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3719 x = lang_hooks.decls.omp_clause_default_ctor
3720 (c, unshare_expr (ivar),
3721 build_outer_var_ref (var, ctx));
3722 if (x)
3723 gimplify_and_add (x, &llist[0]);
3724 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3726 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3727 lower_omp (&tseq, ctx);
3728 gimple_seq_add_seq (&llist[0], tseq);
3730 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3731 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3732 lower_omp (&tseq, ctx);
3733 gimple_seq_add_seq (&llist[1], tseq);
3734 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3735 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3736 if (new_vard == new_var)
3737 SET_DECL_VALUE_EXPR (new_var, lvar);
3738 else
3739 SET_DECL_VALUE_EXPR (new_vard,
3740 build_fold_addr_expr (lvar));
3741 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3742 if (x)
3744 tseq = NULL;
3745 dtor = x;
3746 gimplify_stmt (&dtor, &tseq);
3747 gimple_seq_add_seq (&llist[1], tseq);
3749 break;
3751 /* If this is a reference to constant size reduction var
3752 with placeholder, we haven't emitted the initializer
3753 for it because it is undesirable if SIMD arrays are used.
3754 But if they aren't used, we need to emit the deferred
3755 initialization now. */
3756 else if (is_reference (var) && is_simd)
3757 handle_simd_reference (clause_loc, new_vard, ilist);
3758 x = lang_hooks.decls.omp_clause_default_ctor
3759 (c, unshare_expr (new_var),
3760 build_outer_var_ref (var, ctx));
3761 if (x)
3762 gimplify_and_add (x, ilist);
3763 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3765 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3766 lower_omp (&tseq, ctx);
3767 gimple_seq_add_seq (ilist, tseq);
3769 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3770 if (is_simd)
3772 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3773 lower_omp (&tseq, ctx);
3774 gimple_seq_add_seq (dlist, tseq);
3775 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3777 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3778 goto do_dtor;
3780 else
3782 x = omp_reduction_init (c, TREE_TYPE (new_var));
3783 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3784 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3786 /* reduction(-:var) sums up the partial results, so it
3787 acts identically to reduction(+:var). */
3788 if (code == MINUS_EXPR)
3789 code = PLUS_EXPR;
3791 tree new_vard = new_var;
3792 if (is_simd && is_reference (var))
3794 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3795 new_vard = TREE_OPERAND (new_var, 0);
3796 gcc_assert (DECL_P (new_vard));
3798 if (is_simd
3799 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3800 idx, lane, ivar, lvar))
3802 tree ref = build_outer_var_ref (var, ctx);
3804 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3806 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3807 ref = build_outer_var_ref (var, ctx);
3808 gimplify_assign (ref, x, &llist[1]);
3810 if (new_vard != new_var)
3812 SET_DECL_VALUE_EXPR (new_vard,
3813 build_fold_addr_expr (lvar));
3814 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3817 else
3819 if (is_reference (var) && is_simd)
3820 handle_simd_reference (clause_loc, new_vard, ilist);
3821 gimplify_assign (new_var, x, ilist);
3822 if (is_simd)
3824 tree ref = build_outer_var_ref (var, ctx);
3826 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3827 ref = build_outer_var_ref (var, ctx);
3828 gimplify_assign (ref, x, dlist);
3832 break;
3834 default:
3835 gcc_unreachable ();
3840 if (lane)
3842 tree uid = create_tmp_var (ptr_type_node, "simduid");
3843 /* Don't want uninit warnings on simduid, it is always uninitialized,
3844 but we use it not for the value, but for the DECL_UID only. */
3845 TREE_NO_WARNING (uid) = 1;
3846 gimple g
3847 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3848 gimple_call_set_lhs (g, lane);
3849 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3850 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3851 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3852 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3853 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3854 gimple_omp_for_set_clauses (ctx->stmt, c);
3855 g = gimple_build_assign (lane, INTEGER_CST,
3856 build_int_cst (unsigned_type_node, 0));
3857 gimple_seq_add_stmt (ilist, g);
3858 for (int i = 0; i < 2; i++)
3859 if (llist[i])
3861 tree vf = create_tmp_var (unsigned_type_node);
3862 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3863 gimple_call_set_lhs (g, vf);
3864 gimple_seq *seq = i == 0 ? ilist : dlist;
3865 gimple_seq_add_stmt (seq, g);
3866 tree t = build_int_cst (unsigned_type_node, 0);
3867 g = gimple_build_assign (idx, INTEGER_CST, t);
3868 gimple_seq_add_stmt (seq, g);
3869 tree body = create_artificial_label (UNKNOWN_LOCATION);
3870 tree header = create_artificial_label (UNKNOWN_LOCATION);
3871 tree end = create_artificial_label (UNKNOWN_LOCATION);
3872 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3873 gimple_seq_add_stmt (seq, gimple_build_label (body));
3874 gimple_seq_add_seq (seq, llist[i]);
3875 t = build_int_cst (unsigned_type_node, 1);
3876 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
3877 gimple_seq_add_stmt (seq, g);
3878 gimple_seq_add_stmt (seq, gimple_build_label (header));
3879 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3880 gimple_seq_add_stmt (seq, g);
3881 gimple_seq_add_stmt (seq, gimple_build_label (end));
3885 /* The copyin sequence is not to be executed by the main thread, since
3886 that would result in self-copies. Perhaps not visible to scalars,
3887 but it certainly is to C++ operator=. */
3888 if (copyin_seq)
3890 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3892 x = build2 (NE_EXPR, boolean_type_node, x,
3893 build_int_cst (TREE_TYPE (x), 0));
3894 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3895 gimplify_and_add (x, ilist);
3898 /* If any copyin variable is passed by reference, we must ensure the
3899 master thread doesn't modify it before it is copied over in all
3900 threads. Similarly for variables in both firstprivate and
3901 lastprivate clauses we need to ensure the lastprivate copying
3902 happens after firstprivate copying in all threads. And similarly
3903 for UDRs if initializer expression refers to omp_orig. */
3904 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3906 /* Don't add any barrier for #pragma omp simd or
3907 #pragma omp distribute. */
3908 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3909 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3910 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3913 /* If max_vf is non-zero, then we can use only a vectorization factor
3914 up to the max_vf we chose. So stick it into the safelen clause. */
3915 if (max_vf)
3917 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3918 OMP_CLAUSE_SAFELEN);
3919 if (c == NULL_TREE
3920 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
3921 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3922 max_vf) == 1))
3924 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3925 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3926 max_vf);
3927 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3928 gimple_omp_for_set_clauses (ctx->stmt, c);
3934 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3935 both parallel and workshare constructs. PREDICATE may be NULL if it's
3936 always true. */
3938 static void
3939 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3940 omp_context *ctx)
3942 tree x, c, label = NULL, orig_clauses = clauses;
3943 bool par_clauses = false;
3944 tree simduid = NULL, lastlane = NULL;
3946 /* Early exit if there are no lastprivate or linear clauses. */
3947 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3948 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3949 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3950 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3951 break;
3952 if (clauses == NULL)
3954 /* If this was a workshare clause, see if it had been combined
3955 with its parallel. In that case, look for the clauses on the
3956 parallel statement itself. */
3957 if (is_parallel_ctx (ctx))
3958 return;
3960 ctx = ctx->outer;
3961 if (ctx == NULL || !is_parallel_ctx (ctx))
3962 return;
3964 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3965 OMP_CLAUSE_LASTPRIVATE);
3966 if (clauses == NULL)
3967 return;
3968 par_clauses = true;
3971 if (predicate)
3973 gcond *stmt;
3974 tree label_true, arm1, arm2;
3976 label = create_artificial_label (UNKNOWN_LOCATION);
3977 label_true = create_artificial_label (UNKNOWN_LOCATION);
3978 arm1 = TREE_OPERAND (predicate, 0);
3979 arm2 = TREE_OPERAND (predicate, 1);
3980 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3981 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3982 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3983 label_true, label);
3984 gimple_seq_add_stmt (stmt_list, stmt);
3985 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3988 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3989 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3991 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3992 if (simduid)
3993 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3996 for (c = clauses; c ;)
3998 tree var, new_var;
3999 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4001 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4002 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4003 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4005 var = OMP_CLAUSE_DECL (c);
4006 new_var = lookup_decl (var, ctx);
4008 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4010 tree val = DECL_VALUE_EXPR (new_var);
4011 if (TREE_CODE (val) == ARRAY_REF
4012 && VAR_P (TREE_OPERAND (val, 0))
4013 && lookup_attribute ("omp simd array",
4014 DECL_ATTRIBUTES (TREE_OPERAND (val,
4015 0))))
4017 if (lastlane == NULL)
4019 lastlane = create_tmp_var (unsigned_type_node);
4020 gcall *g
4021 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4022 2, simduid,
4023 TREE_OPERAND (val, 1));
4024 gimple_call_set_lhs (g, lastlane);
4025 gimple_seq_add_stmt (stmt_list, g);
4027 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4028 TREE_OPERAND (val, 0), lastlane,
4029 NULL_TREE, NULL_TREE);
4033 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4034 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4036 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4037 gimple_seq_add_seq (stmt_list,
4038 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4039 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4041 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4042 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4044 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4045 gimple_seq_add_seq (stmt_list,
4046 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4047 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4050 x = build_outer_var_ref (var, ctx);
4051 if (is_reference (var))
4052 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4053 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4054 gimplify_and_add (x, stmt_list);
4056 c = OMP_CLAUSE_CHAIN (c);
4057 if (c == NULL && !par_clauses)
4059 /* If this was a workshare clause, see if it had been combined
4060 with its parallel. In that case, continue looking for the
4061 clauses also on the parallel statement itself. */
4062 if (is_parallel_ctx (ctx))
4063 break;
4065 ctx = ctx->outer;
4066 if (ctx == NULL || !is_parallel_ctx (ctx))
4067 break;
4069 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4070 OMP_CLAUSE_LASTPRIVATE);
4071 par_clauses = true;
4075 if (label)
4076 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4080 /* Generate code to implement the REDUCTION clauses. */
4082 static void
4083 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4085 gimple_seq sub_seq = NULL;
4086 gimple stmt;
4087 tree x, c;
4088 int count = 0;
4090 /* SIMD reductions are handled in lower_rec_input_clauses. */
4091 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4092 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4093 return;
4095 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4096 update in that case, otherwise use a lock. */
4097 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4098 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4100 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4102 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4103 count = -1;
4104 break;
4106 count++;
4109 if (count == 0)
4110 return;
4112 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4114 tree var, ref, new_var;
4115 enum tree_code code;
4116 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4118 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4119 continue;
4121 var = OMP_CLAUSE_DECL (c);
4122 new_var = lookup_decl (var, ctx);
4123 if (is_reference (var))
4124 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4125 ref = build_outer_var_ref (var, ctx);
4126 code = OMP_CLAUSE_REDUCTION_CODE (c);
4128 /* reduction(-:var) sums up the partial results, so it acts
4129 identically to reduction(+:var). */
4130 if (code == MINUS_EXPR)
4131 code = PLUS_EXPR;
4133 if (count == 1)
4135 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4137 addr = save_expr (addr);
4138 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4139 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4140 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4141 gimplify_and_add (x, stmt_seqp);
4142 return;
4145 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4147 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4149 if (is_reference (var)
4150 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4151 TREE_TYPE (ref)))
4152 ref = build_fold_addr_expr_loc (clause_loc, ref);
4153 SET_DECL_VALUE_EXPR (placeholder, ref);
4154 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4155 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4156 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4157 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4158 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4160 else
4162 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4163 ref = build_outer_var_ref (var, ctx);
4164 gimplify_assign (ref, x, &sub_seq);
4168 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4170 gimple_seq_add_stmt (stmt_seqp, stmt);
4172 gimple_seq_add_seq (stmt_seqp, sub_seq);
4174 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4176 gimple_seq_add_stmt (stmt_seqp, stmt);
4180 /* Generate code to implement the COPYPRIVATE clauses. */
4182 static void
4183 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4184 omp_context *ctx)
4186 tree c;
4188 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4190 tree var, new_var, ref, x;
4191 bool by_ref;
4192 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4194 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4195 continue;
4197 var = OMP_CLAUSE_DECL (c);
4198 by_ref = use_pointer_for_field (var, NULL);
4200 ref = build_sender_ref (var, ctx);
4201 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4202 if (by_ref)
4204 x = build_fold_addr_expr_loc (clause_loc, new_var);
4205 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4207 gimplify_assign (ref, x, slist);
4209 ref = build_receiver_ref (var, false, ctx);
4210 if (by_ref)
4212 ref = fold_convert_loc (clause_loc,
4213 build_pointer_type (TREE_TYPE (new_var)),
4214 ref);
4215 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4217 if (is_reference (var))
4219 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4220 ref = build_simple_mem_ref_loc (clause_loc, ref);
4221 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4223 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4224 gimplify_and_add (x, rlist);
4229 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4230 and REDUCTION from the sender (aka parent) side. */
4232 static void
4233 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4234 omp_context *ctx)
4236 tree c;
4238 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4240 tree val, ref, x, var;
4241 bool by_ref, do_in = false, do_out = false;
4242 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4244 switch (OMP_CLAUSE_CODE (c))
4246 case OMP_CLAUSE_PRIVATE:
4247 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4248 break;
4249 continue;
4250 case OMP_CLAUSE_FIRSTPRIVATE:
4251 case OMP_CLAUSE_COPYIN:
4252 case OMP_CLAUSE_LASTPRIVATE:
4253 case OMP_CLAUSE_REDUCTION:
4254 case OMP_CLAUSE__LOOPTEMP_:
4255 break;
4256 default:
4257 continue;
4260 val = OMP_CLAUSE_DECL (c);
4261 var = lookup_decl_in_outer_ctx (val, ctx);
4263 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4264 && is_global_var (var))
4265 continue;
4266 if (is_variable_sized (val))
4267 continue;
4268 by_ref = use_pointer_for_field (val, NULL);
4270 switch (OMP_CLAUSE_CODE (c))
4272 case OMP_CLAUSE_PRIVATE:
4273 case OMP_CLAUSE_FIRSTPRIVATE:
4274 case OMP_CLAUSE_COPYIN:
4275 case OMP_CLAUSE__LOOPTEMP_:
4276 do_in = true;
4277 break;
4279 case OMP_CLAUSE_LASTPRIVATE:
4280 if (by_ref || is_reference (val))
4282 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4283 continue;
4284 do_in = true;
4286 else
4288 do_out = true;
4289 if (lang_hooks.decls.omp_private_outer_ref (val))
4290 do_in = true;
4292 break;
4294 case OMP_CLAUSE_REDUCTION:
4295 do_in = true;
4296 do_out = !(by_ref || is_reference (val));
4297 break;
4299 default:
4300 gcc_unreachable ();
4303 if (do_in)
4305 ref = build_sender_ref (val, ctx);
4306 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4307 gimplify_assign (ref, x, ilist);
4308 if (is_task_ctx (ctx))
4309 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4312 if (do_out)
4314 ref = build_sender_ref (val, ctx);
4315 gimplify_assign (var, ref, olist);
4320 /* Generate code to implement SHARED from the sender (aka parent)
4321 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4322 list things that got automatically shared. */
4324 static void
4325 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4327 tree var, ovar, nvar, f, x, record_type;
4329 if (ctx->record_type == NULL)
4330 return;
4332 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4333 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4335 ovar = DECL_ABSTRACT_ORIGIN (f);
4336 nvar = maybe_lookup_decl (ovar, ctx);
4337 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4338 continue;
4340 /* If CTX is a nested parallel directive. Find the immediately
4341 enclosing parallel or workshare construct that contains a
4342 mapping for OVAR. */
4343 var = lookup_decl_in_outer_ctx (ovar, ctx);
4345 if (use_pointer_for_field (ovar, ctx))
4347 x = build_sender_ref (ovar, ctx);
4348 var = build_fold_addr_expr (var);
4349 gimplify_assign (x, var, ilist);
4351 else
4353 x = build_sender_ref (ovar, ctx);
4354 gimplify_assign (x, var, ilist);
4356 if (!TREE_READONLY (var)
4357 /* We don't need to receive a new reference to a result
4358 or parm decl. In fact we may not store to it as we will
4359 invalidate any pending RSO and generate wrong gimple
4360 during inlining. */
4361 && !((TREE_CODE (var) == RESULT_DECL
4362 || TREE_CODE (var) == PARM_DECL)
4363 && DECL_BY_REFERENCE (var)))
4365 x = build_sender_ref (ovar, ctx);
4366 gimplify_assign (var, x, olist);
4373 /* A convenience function to build an empty GIMPLE_COND with just the
4374 condition. */
4376 static gcond *
4377 gimple_build_cond_empty (tree cond)
4379 enum tree_code pred_code;
4380 tree lhs, rhs;
4382 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4383 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4387 /* Build the function calls to GOMP_parallel_start etc to actually
4388 generate the parallel operation. REGION is the parallel region
4389 being expanded. BB is the block where to insert the code. WS_ARGS
4390 will be set if this is a call to a combined parallel+workshare
4391 construct, it contains the list of additional arguments needed by
4392 the workshare construct. */
4394 static void
4395 expand_parallel_call (struct omp_region *region, basic_block bb,
4396 gomp_parallel *entry_stmt,
4397 vec<tree, va_gc> *ws_args)
4399 tree t, t1, t2, val, cond, c, clauses, flags;
4400 gimple_stmt_iterator gsi;
4401 gimple stmt;
4402 enum built_in_function start_ix;
4403 int start_ix2;
4404 location_t clause_loc;
4405 vec<tree, va_gc> *args;
4407 clauses = gimple_omp_parallel_clauses (entry_stmt);
4409 /* Determine what flavor of GOMP_parallel we will be
4410 emitting. */
4411 start_ix = BUILT_IN_GOMP_PARALLEL;
4412 if (is_combined_parallel (region))
4414 switch (region->inner->type)
4416 case GIMPLE_OMP_FOR:
4417 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4418 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4419 + (region->inner->sched_kind
4420 == OMP_CLAUSE_SCHEDULE_RUNTIME
4421 ? 3 : region->inner->sched_kind));
4422 start_ix = (enum built_in_function)start_ix2;
4423 break;
4424 case GIMPLE_OMP_SECTIONS:
4425 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4426 break;
4427 default:
4428 gcc_unreachable ();
4432 /* By default, the value of NUM_THREADS is zero (selected at run time)
4433 and there is no conditional. */
4434 cond = NULL_TREE;
4435 val = build_int_cst (unsigned_type_node, 0);
4436 flags = build_int_cst (unsigned_type_node, 0);
4438 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4439 if (c)
4440 cond = OMP_CLAUSE_IF_EXPR (c);
4442 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4443 if (c)
4445 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4446 clause_loc = OMP_CLAUSE_LOCATION (c);
4448 else
4449 clause_loc = gimple_location (entry_stmt);
4451 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4452 if (c)
4453 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4455 /* Ensure 'val' is of the correct type. */
4456 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4458 /* If we found the clause 'if (cond)', build either
4459 (cond != 0) or (cond ? val : 1u). */
4460 if (cond)
4462 cond = gimple_boolify (cond);
4464 if (integer_zerop (val))
4465 val = fold_build2_loc (clause_loc,
4466 EQ_EXPR, unsigned_type_node, cond,
4467 build_int_cst (TREE_TYPE (cond), 0));
4468 else
4470 basic_block cond_bb, then_bb, else_bb;
4471 edge e, e_then, e_else;
4472 tree tmp_then, tmp_else, tmp_join, tmp_var;
4474 tmp_var = create_tmp_var (TREE_TYPE (val));
4475 if (gimple_in_ssa_p (cfun))
4477 tmp_then = make_ssa_name (tmp_var);
4478 tmp_else = make_ssa_name (tmp_var);
4479 tmp_join = make_ssa_name (tmp_var);
4481 else
4483 tmp_then = tmp_var;
4484 tmp_else = tmp_var;
4485 tmp_join = tmp_var;
4488 e = split_block (bb, NULL);
4489 cond_bb = e->src;
4490 bb = e->dest;
4491 remove_edge (e);
4493 then_bb = create_empty_bb (cond_bb);
4494 else_bb = create_empty_bb (then_bb);
4495 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4496 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4498 stmt = gimple_build_cond_empty (cond);
4499 gsi = gsi_start_bb (cond_bb);
4500 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4502 gsi = gsi_start_bb (then_bb);
4503 stmt = gimple_build_assign (tmp_then, val);
4504 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4506 gsi = gsi_start_bb (else_bb);
4507 stmt = gimple_build_assign
4508 (tmp_else, build_int_cst (unsigned_type_node, 1));
4509 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4511 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4512 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4513 add_bb_to_loop (then_bb, cond_bb->loop_father);
4514 add_bb_to_loop (else_bb, cond_bb->loop_father);
4515 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4516 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4518 if (gimple_in_ssa_p (cfun))
4520 gphi *phi = create_phi_node (tmp_join, bb);
4521 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4522 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4525 val = tmp_join;
4528 gsi = gsi_start_bb (bb);
4529 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4530 false, GSI_CONTINUE_LINKING);
4533 gsi = gsi_last_bb (bb);
4534 t = gimple_omp_parallel_data_arg (entry_stmt);
4535 if (t == NULL)
4536 t1 = null_pointer_node;
4537 else
4538 t1 = build_fold_addr_expr (t);
4539 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4541 vec_alloc (args, 4 + vec_safe_length (ws_args));
4542 args->quick_push (t2);
4543 args->quick_push (t1);
4544 args->quick_push (val);
4545 if (ws_args)
4546 args->splice (*ws_args);
4547 args->quick_push (flags);
4549 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4550 builtin_decl_explicit (start_ix), args);
4552 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4553 false, GSI_CONTINUE_LINKING);
4556 /* Insert a function call whose name is FUNC_NAME with the information from
4557 ENTRY_STMT into the basic_block BB. */
4559 static void
4560 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
4561 vec <tree, va_gc> *ws_args)
4563 tree t, t1, t2;
4564 gimple_stmt_iterator gsi;
4565 vec <tree, va_gc> *args;
4567 gcc_assert (vec_safe_length (ws_args) == 2);
4568 tree func_name = (*ws_args)[0];
4569 tree grain = (*ws_args)[1];
4571 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
4572 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
4573 gcc_assert (count != NULL_TREE);
4574 count = OMP_CLAUSE_OPERAND (count, 0);
4576 gsi = gsi_last_bb (bb);
4577 t = gimple_omp_parallel_data_arg (entry_stmt);
4578 if (t == NULL)
4579 t1 = null_pointer_node;
4580 else
4581 t1 = build_fold_addr_expr (t);
4582 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4584 vec_alloc (args, 4);
4585 args->quick_push (t2);
4586 args->quick_push (t1);
4587 args->quick_push (count);
4588 args->quick_push (grain);
4589 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
4591 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
4592 GSI_CONTINUE_LINKING);
4595 /* Build the function call to GOMP_task to actually
4596 generate the task operation. BB is the block where to insert the code. */
4598 static void
4599 expand_task_call (basic_block bb, gomp_task *entry_stmt)
4601 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4602 gimple_stmt_iterator gsi;
4603 location_t loc = gimple_location (entry_stmt);
4605 clauses = gimple_omp_task_clauses (entry_stmt);
4607 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4608 if (c)
4609 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4610 else
4611 cond = boolean_true_node;
4613 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4614 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4615 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4616 flags = build_int_cst (unsigned_type_node,
4617 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4619 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4620 if (c)
4622 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4623 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4624 build_int_cst (unsigned_type_node, 2),
4625 build_int_cst (unsigned_type_node, 0));
4626 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4628 if (depend)
4629 depend = OMP_CLAUSE_DECL (depend);
4630 else
4631 depend = build_int_cst (ptr_type_node, 0);
4633 gsi = gsi_last_bb (bb);
4634 t = gimple_omp_task_data_arg (entry_stmt);
4635 if (t == NULL)
4636 t2 = null_pointer_node;
4637 else
4638 t2 = build_fold_addr_expr_loc (loc, t);
4639 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4640 t = gimple_omp_task_copy_fn (entry_stmt);
4641 if (t == NULL)
4642 t3 = null_pointer_node;
4643 else
4644 t3 = build_fold_addr_expr_loc (loc, t);
4646 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4647 8, t1, t2, t3,
4648 gimple_omp_task_arg_size (entry_stmt),
4649 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4650 depend);
4652 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4653 false, GSI_CONTINUE_LINKING);
4657 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4658 catch handler and return it. This prevents programs from violating the
4659 structured block semantics with throws. */
4661 static gimple_seq
4662 maybe_catch_exception (gimple_seq body)
4664 gimple g;
4665 tree decl;
4667 if (!flag_exceptions)
4668 return body;
4670 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4671 decl = lang_hooks.eh_protect_cleanup_actions ();
4672 else
4673 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4675 g = gimple_build_eh_must_not_throw (decl);
4676 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4677 GIMPLE_TRY_CATCH);
4679 return gimple_seq_alloc_with_stmt (g);
4682 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4684 static tree
4685 vec2chain (vec<tree, va_gc> *v)
4687 tree chain = NULL_TREE, t;
4688 unsigned ix;
4690 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4692 DECL_CHAIN (t) = chain;
4693 chain = t;
4696 return chain;
4700 /* Remove barriers in REGION->EXIT's block. Note that this is only
4701 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4702 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4703 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4704 removed. */
4706 static void
4707 remove_exit_barrier (struct omp_region *region)
4709 gimple_stmt_iterator gsi;
4710 basic_block exit_bb;
4711 edge_iterator ei;
4712 edge e;
4713 gimple stmt;
4714 int any_addressable_vars = -1;
4716 exit_bb = region->exit;
4718 /* If the parallel region doesn't return, we don't have REGION->EXIT
4719 block at all. */
4720 if (! exit_bb)
4721 return;
4723 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4724 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4725 statements that can appear in between are extremely limited -- no
4726 memory operations at all. Here, we allow nothing at all, so the
4727 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4728 gsi = gsi_last_bb (exit_bb);
4729 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4730 gsi_prev (&gsi);
4731 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4732 return;
4734 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4736 gsi = gsi_last_bb (e->src);
4737 if (gsi_end_p (gsi))
4738 continue;
4739 stmt = gsi_stmt (gsi);
4740 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4741 && !gimple_omp_return_nowait_p (stmt))
4743 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4744 in many cases. If there could be tasks queued, the barrier
4745 might be needed to let the tasks run before some local
4746 variable of the parallel that the task uses as shared
4747 runs out of scope. The task can be spawned either
4748 from within current function (this would be easy to check)
4749 or from some function it calls and gets passed an address
4750 of such a variable. */
4751 if (any_addressable_vars < 0)
4753 gomp_parallel *parallel_stmt
4754 = as_a <gomp_parallel *> (last_stmt (region->entry));
4755 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4756 tree local_decls, block, decl;
4757 unsigned ix;
4759 any_addressable_vars = 0;
4760 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4761 if (TREE_ADDRESSABLE (decl))
4763 any_addressable_vars = 1;
4764 break;
4766 for (block = gimple_block (stmt);
4767 !any_addressable_vars
4768 && block
4769 && TREE_CODE (block) == BLOCK;
4770 block = BLOCK_SUPERCONTEXT (block))
4772 for (local_decls = BLOCK_VARS (block);
4773 local_decls;
4774 local_decls = DECL_CHAIN (local_decls))
4775 if (TREE_ADDRESSABLE (local_decls))
4777 any_addressable_vars = 1;
4778 break;
4780 if (block == gimple_block (parallel_stmt))
4781 break;
4784 if (!any_addressable_vars)
4785 gimple_omp_return_set_nowait (stmt);
4790 static void
4791 remove_exit_barriers (struct omp_region *region)
4793 if (region->type == GIMPLE_OMP_PARALLEL)
4794 remove_exit_barrier (region);
4796 if (region->inner)
4798 region = region->inner;
4799 remove_exit_barriers (region);
4800 while (region->next)
4802 region = region->next;
4803 remove_exit_barriers (region);
4808 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4809 calls. These can't be declared as const functions, but
4810 within one parallel body they are constant, so they can be
4811 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4812 which are declared const. Similarly for task body, except
4813 that in untied task omp_get_thread_num () can change at any task
4814 scheduling point. */
4816 static void
4817 optimize_omp_library_calls (gimple entry_stmt)
4819 basic_block bb;
4820 gimple_stmt_iterator gsi;
4821 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4822 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4823 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4824 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4825 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4826 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4827 OMP_CLAUSE_UNTIED) != NULL);
4829 FOR_EACH_BB_FN (bb, cfun)
4830 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4832 gimple call = gsi_stmt (gsi);
4833 tree decl;
4835 if (is_gimple_call (call)
4836 && (decl = gimple_call_fndecl (call))
4837 && DECL_EXTERNAL (decl)
4838 && TREE_PUBLIC (decl)
4839 && DECL_INITIAL (decl) == NULL)
4841 tree built_in;
4843 if (DECL_NAME (decl) == thr_num_id)
4845 /* In #pragma omp task untied omp_get_thread_num () can change
4846 during the execution of the task region. */
4847 if (untied_task)
4848 continue;
4849 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4851 else if (DECL_NAME (decl) == num_thr_id)
4852 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4853 else
4854 continue;
4856 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4857 || gimple_call_num_args (call) != 0)
4858 continue;
4860 if (flag_exceptions && !TREE_NOTHROW (decl))
4861 continue;
4863 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4864 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4865 TREE_TYPE (TREE_TYPE (built_in))))
4866 continue;
4868 gimple_call_set_fndecl (call, built_in);
4873 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4874 regimplified. */
4876 static tree
4877 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4879 tree t = *tp;
4881 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4882 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4883 return t;
4885 if (TREE_CODE (t) == ADDR_EXPR)
4886 recompute_tree_invariant_for_addr_expr (t);
4888 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4889 return NULL_TREE;
4892 /* Prepend TO = FROM assignment before *GSI_P. */
4894 static void
4895 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4897 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4898 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4899 true, GSI_SAME_STMT);
4900 gimple stmt = gimple_build_assign (to, from);
4901 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4902 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4903 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4905 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4906 gimple_regimplify_operands (stmt, &gsi);
4910 /* Expand the OpenMP parallel or task directive starting at REGION. */
4912 static void
4913 expand_omp_taskreg (struct omp_region *region)
4915 basic_block entry_bb, exit_bb, new_bb;
4916 struct function *child_cfun;
4917 tree child_fn, block, t;
4918 gimple_stmt_iterator gsi;
4919 gimple entry_stmt, stmt;
4920 edge e;
4921 vec<tree, va_gc> *ws_args;
4923 entry_stmt = last_stmt (region->entry);
4924 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4925 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4927 entry_bb = region->entry;
4928 exit_bb = region->exit;
4930 bool is_cilk_for
4931 = (flag_cilkplus
4932 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
4933 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
4934 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
4936 if (is_cilk_for)
4937 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
4938 and the inner statement contains the name of the built-in function
4939 and grain. */
4940 ws_args = region->inner->ws_args;
4941 else if (is_combined_parallel (region))
4942 ws_args = region->ws_args;
4943 else
4944 ws_args = NULL;
4946 if (child_cfun->cfg)
4948 /* Due to inlining, it may happen that we have already outlined
4949 the region, in which case all we need to do is make the
4950 sub-graph unreachable and emit the parallel call. */
4951 edge entry_succ_e, exit_succ_e;
4953 entry_succ_e = single_succ_edge (entry_bb);
4955 gsi = gsi_last_bb (entry_bb);
4956 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4957 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4958 gsi_remove (&gsi, true);
4960 new_bb = entry_bb;
4961 if (exit_bb)
4963 exit_succ_e = single_succ_edge (exit_bb);
4964 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4966 remove_edge_and_dominated_blocks (entry_succ_e);
4968 else
4970 unsigned srcidx, dstidx, num;
4972 /* If the parallel region needs data sent from the parent
4973 function, then the very first statement (except possible
4974 tree profile counter updates) of the parallel body
4975 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4976 &.OMP_DATA_O is passed as an argument to the child function,
4977 we need to replace it with the argument as seen by the child
4978 function.
4980 In most cases, this will end up being the identity assignment
4981 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4982 a function call that has been inlined, the original PARM_DECL
4983 .OMP_DATA_I may have been converted into a different local
4984 variable. In which case, we need to keep the assignment. */
4985 if (gimple_omp_taskreg_data_arg (entry_stmt))
4987 basic_block entry_succ_bb = single_succ (entry_bb);
4988 tree arg, narg;
4989 gimple parcopy_stmt = NULL;
4991 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4993 gimple stmt;
4995 gcc_assert (!gsi_end_p (gsi));
4996 stmt = gsi_stmt (gsi);
4997 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4998 continue;
5000 if (gimple_num_ops (stmt) == 2)
5002 tree arg = gimple_assign_rhs1 (stmt);
5004 /* We're ignore the subcode because we're
5005 effectively doing a STRIP_NOPS. */
5007 if (TREE_CODE (arg) == ADDR_EXPR
5008 && TREE_OPERAND (arg, 0)
5009 == gimple_omp_taskreg_data_arg (entry_stmt))
5011 parcopy_stmt = stmt;
5012 break;
5017 gcc_assert (parcopy_stmt != NULL);
5018 arg = DECL_ARGUMENTS (child_fn);
5020 if (!gimple_in_ssa_p (cfun))
5022 if (gimple_assign_lhs (parcopy_stmt) == arg)
5023 gsi_remove (&gsi, true);
5024 else
5026 /* ?? Is setting the subcode really necessary ?? */
5027 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5028 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5031 else
5033 /* If we are in ssa form, we must load the value from the default
5034 definition of the argument. That should not be defined now,
5035 since the argument is not used uninitialized. */
5036 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5037 narg = make_ssa_name (arg, gimple_build_nop ());
5038 set_ssa_default_def (cfun, arg, narg);
5039 /* ?? Is setting the subcode really necessary ?? */
5040 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5041 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5042 update_stmt (parcopy_stmt);
5046 /* Declare local variables needed in CHILD_CFUN. */
5047 block = DECL_INITIAL (child_fn);
5048 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5049 /* The gimplifier could record temporaries in parallel/task block
5050 rather than in containing function's local_decls chain,
5051 which would mean cgraph missed finalizing them. Do it now. */
5052 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5053 if (TREE_CODE (t) == VAR_DECL
5054 && TREE_STATIC (t)
5055 && !DECL_EXTERNAL (t))
5056 varpool_node::finalize_decl (t);
5057 DECL_SAVED_TREE (child_fn) = NULL;
5058 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5059 gimple_set_body (child_fn, NULL);
5060 TREE_USED (block) = 1;
5062 /* Reset DECL_CONTEXT on function arguments. */
5063 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5064 DECL_CONTEXT (t) = child_fn;
5066 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5067 so that it can be moved to the child function. */
5068 gsi = gsi_last_bb (entry_bb);
5069 stmt = gsi_stmt (gsi);
5070 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5071 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5072 gsi_remove (&gsi, true);
5073 e = split_block (entry_bb, stmt);
5074 entry_bb = e->dest;
5075 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5077 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5078 if (exit_bb)
5080 gsi = gsi_last_bb (exit_bb);
5081 gcc_assert (!gsi_end_p (gsi)
5082 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5083 stmt = gimple_build_return (NULL);
5084 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5085 gsi_remove (&gsi, true);
5088 /* Move the parallel region into CHILD_CFUN. */
5090 if (gimple_in_ssa_p (cfun))
5092 init_tree_ssa (child_cfun);
5093 init_ssa_operands (child_cfun);
5094 child_cfun->gimple_df->in_ssa_p = true;
5095 block = NULL_TREE;
5097 else
5098 block = gimple_block (entry_stmt);
5100 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5101 if (exit_bb)
5102 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5103 /* When the OMP expansion process cannot guarantee an up-to-date
5104 loop tree arrange for the child function to fixup loops. */
5105 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5106 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5108 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5109 num = vec_safe_length (child_cfun->local_decls);
5110 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5112 t = (*child_cfun->local_decls)[srcidx];
5113 if (DECL_CONTEXT (t) == cfun->decl)
5114 continue;
5115 if (srcidx != dstidx)
5116 (*child_cfun->local_decls)[dstidx] = t;
5117 dstidx++;
5119 if (dstidx != num)
5120 vec_safe_truncate (child_cfun->local_decls, dstidx);
5122 /* Inform the callgraph about the new function. */
5123 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5124 cgraph_node::add_new_function (child_fn, true);
5126 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5127 fixed in a following pass. */
5128 push_cfun (child_cfun);
5129 if (optimize)
5130 optimize_omp_library_calls (entry_stmt);
5131 cgraph_edge::rebuild_edges ();
5133 /* Some EH regions might become dead, see PR34608. If
5134 pass_cleanup_cfg isn't the first pass to happen with the
5135 new child, these dead EH edges might cause problems.
5136 Clean them up now. */
5137 if (flag_exceptions)
5139 basic_block bb;
5140 bool changed = false;
5142 FOR_EACH_BB_FN (bb, cfun)
5143 changed |= gimple_purge_dead_eh_edges (bb);
5144 if (changed)
5145 cleanup_tree_cfg ();
5147 if (gimple_in_ssa_p (cfun))
5148 update_ssa (TODO_update_ssa);
5149 pop_cfun ();
5152 /* Emit a library call to launch the children threads. */
5153 if (is_cilk_for)
5154 expand_cilk_for_call (new_bb,
5155 as_a <gomp_parallel *> (entry_stmt), ws_args);
5156 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5157 expand_parallel_call (region, new_bb,
5158 as_a <gomp_parallel *> (entry_stmt), ws_args);
5159 else
5160 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5161 if (gimple_in_ssa_p (cfun))
5162 update_ssa (TODO_update_ssa_only_virtuals);
5166 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5167 of the combined collapse > 1 loop constructs, generate code like:
5168 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5169 if (cond3 is <)
5170 adj = STEP3 - 1;
5171 else
5172 adj = STEP3 + 1;
5173 count3 = (adj + N32 - N31) / STEP3;
5174 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5175 if (cond2 is <)
5176 adj = STEP2 - 1;
5177 else
5178 adj = STEP2 + 1;
5179 count2 = (adj + N22 - N21) / STEP2;
5180 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5181 if (cond1 is <)
5182 adj = STEP1 - 1;
5183 else
5184 adj = STEP1 + 1;
5185 count1 = (adj + N12 - N11) / STEP1;
5186 count = count1 * count2 * count3;
5187 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5188 count = 0;
5189 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5190 of the combined loop constructs, just initialize COUNTS array
5191 from the _looptemp_ clauses. */
5193 /* NOTE: It *could* be better to moosh all of the BBs together,
5194 creating one larger BB with all the computation and the unexpected
5195 jump at the end. I.e.
5197 bool zero3, zero2, zero1, zero;
5199 zero3 = N32 c3 N31;
5200 count3 = (N32 - N31) /[cl] STEP3;
5201 zero2 = N22 c2 N21;
5202 count2 = (N22 - N21) /[cl] STEP2;
5203 zero1 = N12 c1 N11;
5204 count1 = (N12 - N11) /[cl] STEP1;
5205 zero = zero3 || zero2 || zero1;
5206 count = count1 * count2 * count3;
5207 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5209 After all, we expect the zero=false, and thus we expect to have to
5210 evaluate all of the comparison expressions, so short-circuiting
5211 oughtn't be a win. Since the condition isn't protecting a
5212 denominator, we're not concerned about divide-by-zero, so we can
5213 fully evaluate count even if a numerator turned out to be wrong.
5215 It seems like putting this all together would create much better
5216 scheduling opportunities, and less pressure on the chip's branch
5217 predictor. */
5219 static void
5220 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5221 basic_block &entry_bb, tree *counts,
5222 basic_block &zero_iter_bb, int &first_zero_iter,
5223 basic_block &l2_dom_bb)
5225 tree t, type = TREE_TYPE (fd->loop.v);
5226 edge e, ne;
5227 int i;
5229 /* Collapsed loops need work for expansion into SSA form. */
5230 gcc_assert (!gimple_in_ssa_p (cfun));
5232 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5233 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5235 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5236 isn't supposed to be handled, as the inner loop doesn't
5237 use it. */
5238 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5239 OMP_CLAUSE__LOOPTEMP_);
5240 gcc_assert (innerc);
5241 for (i = 0; i < fd->collapse; i++)
5243 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5244 OMP_CLAUSE__LOOPTEMP_);
5245 gcc_assert (innerc);
5246 if (i)
5247 counts[i] = OMP_CLAUSE_DECL (innerc);
5248 else
5249 counts[0] = NULL_TREE;
5251 return;
5254 for (i = 0; i < fd->collapse; i++)
5256 tree itype = TREE_TYPE (fd->loops[i].v);
5258 if (SSA_VAR_P (fd->loop.n2)
5259 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5260 fold_convert (itype, fd->loops[i].n1),
5261 fold_convert (itype, fd->loops[i].n2)))
5262 == NULL_TREE || !integer_onep (t)))
5264 gcond *cond_stmt;
5265 tree n1, n2;
5266 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5267 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5268 true, GSI_SAME_STMT);
5269 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5270 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5271 true, GSI_SAME_STMT);
5272 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5273 NULL_TREE, NULL_TREE);
5274 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5275 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5276 expand_omp_regimplify_p, NULL, NULL)
5277 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5278 expand_omp_regimplify_p, NULL, NULL))
5280 *gsi = gsi_for_stmt (cond_stmt);
5281 gimple_regimplify_operands (cond_stmt, gsi);
5283 e = split_block (entry_bb, cond_stmt);
5284 if (zero_iter_bb == NULL)
5286 gassign *assign_stmt;
5287 first_zero_iter = i;
5288 zero_iter_bb = create_empty_bb (entry_bb);
5289 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5290 *gsi = gsi_after_labels (zero_iter_bb);
5291 assign_stmt = gimple_build_assign (fd->loop.n2,
5292 build_zero_cst (type));
5293 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5294 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5295 entry_bb);
5297 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5298 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5299 e->flags = EDGE_TRUE_VALUE;
5300 e->probability = REG_BR_PROB_BASE - ne->probability;
5301 if (l2_dom_bb == NULL)
5302 l2_dom_bb = entry_bb;
5303 entry_bb = e->dest;
5304 *gsi = gsi_last_bb (entry_bb);
5307 if (POINTER_TYPE_P (itype))
5308 itype = signed_type_for (itype);
5309 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5310 ? -1 : 1));
5311 t = fold_build2 (PLUS_EXPR, itype,
5312 fold_convert (itype, fd->loops[i].step), t);
5313 t = fold_build2 (PLUS_EXPR, itype, t,
5314 fold_convert (itype, fd->loops[i].n2));
5315 t = fold_build2 (MINUS_EXPR, itype, t,
5316 fold_convert (itype, fd->loops[i].n1));
5317 /* ?? We could probably use CEIL_DIV_EXPR instead of
5318 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5319 generate the same code in the end because generically we
5320 don't know that the values involved must be negative for
5321 GT?? */
5322 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5323 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5324 fold_build1 (NEGATE_EXPR, itype, t),
5325 fold_build1 (NEGATE_EXPR, itype,
5326 fold_convert (itype,
5327 fd->loops[i].step)));
5328 else
5329 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5330 fold_convert (itype, fd->loops[i].step));
5331 t = fold_convert (type, t);
5332 if (TREE_CODE (t) == INTEGER_CST)
5333 counts[i] = t;
5334 else
5336 counts[i] = create_tmp_reg (type, ".count");
5337 expand_omp_build_assign (gsi, counts[i], t);
5339 if (SSA_VAR_P (fd->loop.n2))
5341 if (i == 0)
5342 t = counts[0];
5343 else
5344 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5345 expand_omp_build_assign (gsi, fd->loop.n2, t);
5351 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5352 T = V;
5353 V3 = N31 + (T % count3) * STEP3;
5354 T = T / count3;
5355 V2 = N21 + (T % count2) * STEP2;
5356 T = T / count2;
5357 V1 = N11 + T * STEP1;
5358 if this loop doesn't have an inner loop construct combined with it.
5359 If it does have an inner loop construct combined with it and the
5360 iteration count isn't known constant, store values from counts array
5361 into its _looptemp_ temporaries instead. */
5363 static void
5364 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5365 tree *counts, gimple inner_stmt, tree startvar)
5367 int i;
5368 if (gimple_omp_for_combined_p (fd->for_stmt))
5370 /* If fd->loop.n2 is constant, then no propagation of the counts
5371 is needed, they are constant. */
5372 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5373 return;
5375 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5376 ? gimple_omp_parallel_clauses (inner_stmt)
5377 : gimple_omp_for_clauses (inner_stmt);
5378 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5379 isn't supposed to be handled, as the inner loop doesn't
5380 use it. */
5381 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5382 gcc_assert (innerc);
5383 for (i = 0; i < fd->collapse; i++)
5385 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5386 OMP_CLAUSE__LOOPTEMP_);
5387 gcc_assert (innerc);
5388 if (i)
5390 tree tem = OMP_CLAUSE_DECL (innerc);
5391 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5392 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5393 false, GSI_CONTINUE_LINKING);
5394 gassign *stmt = gimple_build_assign (tem, t);
5395 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5398 return;
5401 tree type = TREE_TYPE (fd->loop.v);
5402 tree tem = create_tmp_reg (type, ".tem");
5403 gassign *stmt = gimple_build_assign (tem, startvar);
5404 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5406 for (i = fd->collapse - 1; i >= 0; i--)
5408 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5409 itype = vtype;
5410 if (POINTER_TYPE_P (vtype))
5411 itype = signed_type_for (vtype);
5412 if (i != 0)
5413 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5414 else
5415 t = tem;
5416 t = fold_convert (itype, t);
5417 t = fold_build2 (MULT_EXPR, itype, t,
5418 fold_convert (itype, fd->loops[i].step));
5419 if (POINTER_TYPE_P (vtype))
5420 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5421 else
5422 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5423 t = force_gimple_operand_gsi (gsi, t,
5424 DECL_P (fd->loops[i].v)
5425 && TREE_ADDRESSABLE (fd->loops[i].v),
5426 NULL_TREE, false,
5427 GSI_CONTINUE_LINKING);
5428 stmt = gimple_build_assign (fd->loops[i].v, t);
5429 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5430 if (i != 0)
5432 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5433 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5434 false, GSI_CONTINUE_LINKING);
5435 stmt = gimple_build_assign (tem, t);
5436 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5442 /* Helper function for expand_omp_for_*. Generate code like:
5443 L10:
5444 V3 += STEP3;
5445 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5446 L11:
5447 V3 = N31;
5448 V2 += STEP2;
5449 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5450 L12:
5451 V2 = N21;
5452 V1 += STEP1;
5453 goto BODY_BB; */
5455 static basic_block
5456 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5457 basic_block body_bb)
5459 basic_block last_bb, bb, collapse_bb = NULL;
5460 int i;
5461 gimple_stmt_iterator gsi;
5462 edge e;
5463 tree t;
5464 gimple stmt;
5466 last_bb = cont_bb;
5467 for (i = fd->collapse - 1; i >= 0; i--)
5469 tree vtype = TREE_TYPE (fd->loops[i].v);
5471 bb = create_empty_bb (last_bb);
5472 add_bb_to_loop (bb, last_bb->loop_father);
5473 gsi = gsi_start_bb (bb);
5475 if (i < fd->collapse - 1)
5477 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5478 e->probability = REG_BR_PROB_BASE / 8;
5480 t = fd->loops[i + 1].n1;
5481 t = force_gimple_operand_gsi (&gsi, t,
5482 DECL_P (fd->loops[i + 1].v)
5483 && TREE_ADDRESSABLE (fd->loops[i
5484 + 1].v),
5485 NULL_TREE, false,
5486 GSI_CONTINUE_LINKING);
5487 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5488 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5490 else
5491 collapse_bb = bb;
5493 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5495 if (POINTER_TYPE_P (vtype))
5496 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5497 else
5498 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5499 t = force_gimple_operand_gsi (&gsi, t,
5500 DECL_P (fd->loops[i].v)
5501 && TREE_ADDRESSABLE (fd->loops[i].v),
5502 NULL_TREE, false, GSI_CONTINUE_LINKING);
5503 stmt = gimple_build_assign (fd->loops[i].v, t);
5504 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5506 if (i > 0)
5508 t = fd->loops[i].n2;
5509 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5510 false, GSI_CONTINUE_LINKING);
5511 tree v = fd->loops[i].v;
5512 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5513 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5514 false, GSI_CONTINUE_LINKING);
5515 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5516 stmt = gimple_build_cond_empty (t);
5517 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5518 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5519 e->probability = REG_BR_PROB_BASE * 7 / 8;
5521 else
5522 make_edge (bb, body_bb, EDGE_FALLTHRU);
5523 last_bb = bb;
5526 return collapse_bb;
5530 /* A subroutine of expand_omp_for. Generate code for a parallel
5531 loop with any schedule. Given parameters:
5533 for (V = N1; V cond N2; V += STEP) BODY;
5535 where COND is "<" or ">", we generate pseudocode
5537 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5538 if (more) goto L0; else goto L3;
5540 V = istart0;
5541 iend = iend0;
5543 BODY;
5544 V += STEP;
5545 if (V cond iend) goto L1; else goto L2;
5547 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5550 If this is a combined omp parallel loop, instead of the call to
5551 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5552 If this is gimple_omp_for_combined_p loop, then instead of assigning
5553 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5554 inner GIMPLE_OMP_FOR and V += STEP; and
5555 if (V cond iend) goto L1; else goto L2; are removed.
5557 For collapsed loops, given parameters:
5558 collapse(3)
5559 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5560 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5561 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5562 BODY;
5564 we generate pseudocode
5566 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5567 if (cond3 is <)
5568 adj = STEP3 - 1;
5569 else
5570 adj = STEP3 + 1;
5571 count3 = (adj + N32 - N31) / STEP3;
5572 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5573 if (cond2 is <)
5574 adj = STEP2 - 1;
5575 else
5576 adj = STEP2 + 1;
5577 count2 = (adj + N22 - N21) / STEP2;
5578 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5579 if (cond1 is <)
5580 adj = STEP1 - 1;
5581 else
5582 adj = STEP1 + 1;
5583 count1 = (adj + N12 - N11) / STEP1;
5584 count = count1 * count2 * count3;
5585 goto Z1;
5587 count = 0;
5589 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5590 if (more) goto L0; else goto L3;
5592 V = istart0;
5593 T = V;
5594 V3 = N31 + (T % count3) * STEP3;
5595 T = T / count3;
5596 V2 = N21 + (T % count2) * STEP2;
5597 T = T / count2;
5598 V1 = N11 + T * STEP1;
5599 iend = iend0;
5601 BODY;
5602 V += 1;
5603 if (V < iend) goto L10; else goto L2;
5604 L10:
5605 V3 += STEP3;
5606 if (V3 cond3 N32) goto L1; else goto L11;
5607 L11:
5608 V3 = N31;
5609 V2 += STEP2;
5610 if (V2 cond2 N22) goto L1; else goto L12;
5611 L12:
5612 V2 = N21;
5613 V1 += STEP1;
5614 goto L1;
5616 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5621 static void
5622 expand_omp_for_generic (struct omp_region *region,
5623 struct omp_for_data *fd,
5624 enum built_in_function start_fn,
5625 enum built_in_function next_fn,
5626 gimple inner_stmt)
5628 tree type, istart0, iend0, iend;
5629 tree t, vmain, vback, bias = NULL_TREE;
5630 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5631 basic_block l2_bb = NULL, l3_bb = NULL;
5632 gimple_stmt_iterator gsi;
5633 gassign *assign_stmt;
5634 bool in_combined_parallel = is_combined_parallel (region);
5635 bool broken_loop = region->cont == NULL;
5636 edge e, ne;
5637 tree *counts = NULL;
5638 int i;
5640 gcc_assert (!broken_loop || !in_combined_parallel);
5641 gcc_assert (fd->iter_type == long_integer_type_node
5642 || !in_combined_parallel);
5644 type = TREE_TYPE (fd->loop.v);
5645 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5646 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5647 TREE_ADDRESSABLE (istart0) = 1;
5648 TREE_ADDRESSABLE (iend0) = 1;
5650 /* See if we need to bias by LLONG_MIN. */
5651 if (fd->iter_type == long_long_unsigned_type_node
5652 && TREE_CODE (type) == INTEGER_TYPE
5653 && !TYPE_UNSIGNED (type))
5655 tree n1, n2;
5657 if (fd->loop.cond_code == LT_EXPR)
5659 n1 = fd->loop.n1;
5660 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5662 else
5664 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5665 n2 = fd->loop.n1;
5667 if (TREE_CODE (n1) != INTEGER_CST
5668 || TREE_CODE (n2) != INTEGER_CST
5669 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5670 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5673 entry_bb = region->entry;
5674 cont_bb = region->cont;
5675 collapse_bb = NULL;
5676 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5677 gcc_assert (broken_loop
5678 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5679 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5680 l1_bb = single_succ (l0_bb);
5681 if (!broken_loop)
5683 l2_bb = create_empty_bb (cont_bb);
5684 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5685 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5687 else
5688 l2_bb = NULL;
5689 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5690 exit_bb = region->exit;
5692 gsi = gsi_last_bb (entry_bb);
5694 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5695 if (fd->collapse > 1)
5697 int first_zero_iter = -1;
5698 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5700 counts = XALLOCAVEC (tree, fd->collapse);
5701 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5702 zero_iter_bb, first_zero_iter,
5703 l2_dom_bb);
5705 if (zero_iter_bb)
5707 /* Some counts[i] vars might be uninitialized if
5708 some loop has zero iterations. But the body shouldn't
5709 be executed in that case, so just avoid uninit warnings. */
5710 for (i = first_zero_iter; i < fd->collapse; i++)
5711 if (SSA_VAR_P (counts[i]))
5712 TREE_NO_WARNING (counts[i]) = 1;
5713 gsi_prev (&gsi);
5714 e = split_block (entry_bb, gsi_stmt (gsi));
5715 entry_bb = e->dest;
5716 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5717 gsi = gsi_last_bb (entry_bb);
5718 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5719 get_immediate_dominator (CDI_DOMINATORS,
5720 zero_iter_bb));
5723 if (in_combined_parallel)
5725 /* In a combined parallel loop, emit a call to
5726 GOMP_loop_foo_next. */
5727 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5728 build_fold_addr_expr (istart0),
5729 build_fold_addr_expr (iend0));
5731 else
5733 tree t0, t1, t2, t3, t4;
5734 /* If this is not a combined parallel loop, emit a call to
5735 GOMP_loop_foo_start in ENTRY_BB. */
5736 t4 = build_fold_addr_expr (iend0);
5737 t3 = build_fold_addr_expr (istart0);
5738 t2 = fold_convert (fd->iter_type, fd->loop.step);
5739 t1 = fd->loop.n2;
5740 t0 = fd->loop.n1;
5741 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5743 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5744 OMP_CLAUSE__LOOPTEMP_);
5745 gcc_assert (innerc);
5746 t0 = OMP_CLAUSE_DECL (innerc);
5747 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5748 OMP_CLAUSE__LOOPTEMP_);
5749 gcc_assert (innerc);
5750 t1 = OMP_CLAUSE_DECL (innerc);
5752 if (POINTER_TYPE_P (TREE_TYPE (t0))
5753 && TYPE_PRECISION (TREE_TYPE (t0))
5754 != TYPE_PRECISION (fd->iter_type))
5756 /* Avoid casting pointers to integer of a different size. */
5757 tree itype = signed_type_for (type);
5758 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5759 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5761 else
5763 t1 = fold_convert (fd->iter_type, t1);
5764 t0 = fold_convert (fd->iter_type, t0);
5766 if (bias)
5768 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5769 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5771 if (fd->iter_type == long_integer_type_node)
5773 if (fd->chunk_size)
5775 t = fold_convert (fd->iter_type, fd->chunk_size);
5776 t = build_call_expr (builtin_decl_explicit (start_fn),
5777 6, t0, t1, t2, t, t3, t4);
5779 else
5780 t = build_call_expr (builtin_decl_explicit (start_fn),
5781 5, t0, t1, t2, t3, t4);
5783 else
5785 tree t5;
5786 tree c_bool_type;
5787 tree bfn_decl;
5789 /* The GOMP_loop_ull_*start functions have additional boolean
5790 argument, true for < loops and false for > loops.
5791 In Fortran, the C bool type can be different from
5792 boolean_type_node. */
5793 bfn_decl = builtin_decl_explicit (start_fn);
5794 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5795 t5 = build_int_cst (c_bool_type,
5796 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5797 if (fd->chunk_size)
5799 tree bfn_decl = builtin_decl_explicit (start_fn);
5800 t = fold_convert (fd->iter_type, fd->chunk_size);
5801 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5803 else
5804 t = build_call_expr (builtin_decl_explicit (start_fn),
5805 6, t5, t0, t1, t2, t3, t4);
5808 if (TREE_TYPE (t) != boolean_type_node)
5809 t = fold_build2 (NE_EXPR, boolean_type_node,
5810 t, build_int_cst (TREE_TYPE (t), 0));
5811 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5812 true, GSI_SAME_STMT);
5813 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5815 /* Remove the GIMPLE_OMP_FOR statement. */
5816 gsi_remove (&gsi, true);
5818 /* Iteration setup for sequential loop goes in L0_BB. */
5819 tree startvar = fd->loop.v;
5820 tree endvar = NULL_TREE;
5822 if (gimple_omp_for_combined_p (fd->for_stmt))
5824 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5825 && gimple_omp_for_kind (inner_stmt)
5826 == GF_OMP_FOR_KIND_SIMD);
5827 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5828 OMP_CLAUSE__LOOPTEMP_);
5829 gcc_assert (innerc);
5830 startvar = OMP_CLAUSE_DECL (innerc);
5831 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5832 OMP_CLAUSE__LOOPTEMP_);
5833 gcc_assert (innerc);
5834 endvar = OMP_CLAUSE_DECL (innerc);
5837 gsi = gsi_start_bb (l0_bb);
5838 t = istart0;
5839 if (bias)
5840 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5841 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5842 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5843 t = fold_convert (TREE_TYPE (startvar), t);
5844 t = force_gimple_operand_gsi (&gsi, t,
5845 DECL_P (startvar)
5846 && TREE_ADDRESSABLE (startvar),
5847 NULL_TREE, false, GSI_CONTINUE_LINKING);
5848 assign_stmt = gimple_build_assign (startvar, t);
5849 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5851 t = iend0;
5852 if (bias)
5853 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5854 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5855 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5856 t = fold_convert (TREE_TYPE (startvar), t);
5857 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5858 false, GSI_CONTINUE_LINKING);
5859 if (endvar)
5861 assign_stmt = gimple_build_assign (endvar, iend);
5862 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5863 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
5864 assign_stmt = gimple_build_assign (fd->loop.v, iend);
5865 else
5866 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
5867 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
5869 if (fd->collapse > 1)
5870 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5872 if (!broken_loop)
5874 /* Code to control the increment and predicate for the sequential
5875 loop goes in the CONT_BB. */
5876 gsi = gsi_last_bb (cont_bb);
5877 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
5878 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
5879 vmain = gimple_omp_continue_control_use (cont_stmt);
5880 vback = gimple_omp_continue_control_def (cont_stmt);
5882 if (!gimple_omp_for_combined_p (fd->for_stmt))
5884 if (POINTER_TYPE_P (type))
5885 t = fold_build_pointer_plus (vmain, fd->loop.step);
5886 else
5887 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5888 t = force_gimple_operand_gsi (&gsi, t,
5889 DECL_P (vback)
5890 && TREE_ADDRESSABLE (vback),
5891 NULL_TREE, true, GSI_SAME_STMT);
5892 assign_stmt = gimple_build_assign (vback, t);
5893 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
5895 t = build2 (fd->loop.cond_code, boolean_type_node,
5896 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5897 iend);
5898 gcond *cond_stmt = gimple_build_cond_empty (t);
5899 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
5902 /* Remove GIMPLE_OMP_CONTINUE. */
5903 gsi_remove (&gsi, true);
5905 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5906 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5908 /* Emit code to get the next parallel iteration in L2_BB. */
5909 gsi = gsi_start_bb (l2_bb);
5911 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5912 build_fold_addr_expr (istart0),
5913 build_fold_addr_expr (iend0));
5914 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5915 false, GSI_CONTINUE_LINKING);
5916 if (TREE_TYPE (t) != boolean_type_node)
5917 t = fold_build2 (NE_EXPR, boolean_type_node,
5918 t, build_int_cst (TREE_TYPE (t), 0));
5919 gcond *cond_stmt = gimple_build_cond_empty (t);
5920 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
5923 /* Add the loop cleanup function. */
5924 gsi = gsi_last_bb (exit_bb);
5925 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5926 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5927 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5928 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5929 else
5930 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5931 gcall *call_stmt = gimple_build_call (t, 0);
5932 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5933 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5934 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
5935 gsi_remove (&gsi, true);
5937 /* Connect the new blocks. */
5938 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5939 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5941 if (!broken_loop)
5943 gimple_seq phis;
5945 e = find_edge (cont_bb, l3_bb);
5946 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5948 phis = phi_nodes (l3_bb);
5949 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5951 gimple phi = gsi_stmt (gsi);
5952 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5953 PHI_ARG_DEF_FROM_EDGE (phi, e));
5955 remove_edge (e);
5957 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5958 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5959 e = find_edge (cont_bb, l1_bb);
5960 if (gimple_omp_for_combined_p (fd->for_stmt))
5962 remove_edge (e);
5963 e = NULL;
5965 else if (fd->collapse > 1)
5967 remove_edge (e);
5968 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5970 else
5971 e->flags = EDGE_TRUE_VALUE;
5972 if (e)
5974 e->probability = REG_BR_PROB_BASE * 7 / 8;
5975 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5977 else
5979 e = find_edge (cont_bb, l2_bb);
5980 e->flags = EDGE_FALLTHRU;
5982 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5984 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5985 recompute_dominator (CDI_DOMINATORS, l2_bb));
5986 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5987 recompute_dominator (CDI_DOMINATORS, l3_bb));
5988 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5989 recompute_dominator (CDI_DOMINATORS, l0_bb));
5990 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5991 recompute_dominator (CDI_DOMINATORS, l1_bb));
5993 struct loop *outer_loop = alloc_loop ();
5994 outer_loop->header = l0_bb;
5995 outer_loop->latch = l2_bb;
5996 add_loop (outer_loop, l0_bb->loop_father);
5998 if (!gimple_omp_for_combined_p (fd->for_stmt))
6000 struct loop *loop = alloc_loop ();
6001 loop->header = l1_bb;
6002 /* The loop may have multiple latches. */
6003 add_loop (loop, outer_loop);
6009 /* A subroutine of expand_omp_for. Generate code for a parallel
6010 loop with static schedule and no specified chunk size. Given
6011 parameters:
6013 for (V = N1; V cond N2; V += STEP) BODY;
6015 where COND is "<" or ">", we generate pseudocode
6017 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6018 if (cond is <)
6019 adj = STEP - 1;
6020 else
6021 adj = STEP + 1;
6022 if ((__typeof (V)) -1 > 0 && cond is >)
6023 n = -(adj + N2 - N1) / -STEP;
6024 else
6025 n = (adj + N2 - N1) / STEP;
6026 q = n / nthreads;
6027 tt = n % nthreads;
6028 if (threadid < tt) goto L3; else goto L4;
6030 tt = 0;
6031 q = q + 1;
6033 s0 = q * threadid + tt;
6034 e0 = s0 + q;
6035 V = s0 * STEP + N1;
6036 if (s0 >= e0) goto L2; else goto L0;
6038 e = e0 * STEP + N1;
6040 BODY;
6041 V += STEP;
6042 if (V cond e) goto L1;
6046 static void
6047 expand_omp_for_static_nochunk (struct omp_region *region,
6048 struct omp_for_data *fd,
6049 gimple inner_stmt)
6051 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6052 tree type, itype, vmain, vback;
6053 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6054 basic_block body_bb, cont_bb, collapse_bb = NULL;
6055 basic_block fin_bb;
6056 gimple_stmt_iterator gsi;
6057 edge ep;
6058 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6059 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6060 bool broken_loop = region->cont == NULL;
6061 tree *counts = NULL;
6062 tree n1, n2, step;
6064 itype = type = TREE_TYPE (fd->loop.v);
6065 if (POINTER_TYPE_P (type))
6066 itype = signed_type_for (type);
6068 entry_bb = region->entry;
6069 cont_bb = region->cont;
6070 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6071 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6072 gcc_assert (broken_loop
6073 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6074 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6075 body_bb = single_succ (seq_start_bb);
6076 if (!broken_loop)
6078 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6079 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6081 exit_bb = region->exit;
6083 /* Iteration space partitioning goes in ENTRY_BB. */
6084 gsi = gsi_last_bb (entry_bb);
6085 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6087 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6089 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6090 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6093 if (fd->collapse > 1)
6095 int first_zero_iter = -1;
6096 basic_block l2_dom_bb = NULL;
6098 counts = XALLOCAVEC (tree, fd->collapse);
6099 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6100 fin_bb, first_zero_iter,
6101 l2_dom_bb);
6102 t = NULL_TREE;
6104 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6105 t = integer_one_node;
6106 else
6107 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6108 fold_convert (type, fd->loop.n1),
6109 fold_convert (type, fd->loop.n2));
6110 if (fd->collapse == 1
6111 && TYPE_UNSIGNED (type)
6112 && (t == NULL_TREE || !integer_onep (t)))
6114 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6115 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6116 true, GSI_SAME_STMT);
6117 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6118 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6119 true, GSI_SAME_STMT);
6120 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6121 NULL_TREE, NULL_TREE);
6122 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6123 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6124 expand_omp_regimplify_p, NULL, NULL)
6125 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6126 expand_omp_regimplify_p, NULL, NULL))
6128 gsi = gsi_for_stmt (cond_stmt);
6129 gimple_regimplify_operands (cond_stmt, &gsi);
6131 ep = split_block (entry_bb, cond_stmt);
6132 ep->flags = EDGE_TRUE_VALUE;
6133 entry_bb = ep->dest;
6134 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6135 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6136 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6137 if (gimple_in_ssa_p (cfun))
6139 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6140 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6141 !gsi_end_p (gpi); gsi_next (&gpi))
6143 gphi *phi = gpi.phi ();
6144 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6145 ep, UNKNOWN_LOCATION);
6148 gsi = gsi_last_bb (entry_bb);
6151 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6152 t = fold_convert (itype, t);
6153 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6154 true, GSI_SAME_STMT);
6156 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6157 t = fold_convert (itype, t);
6158 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6159 true, GSI_SAME_STMT);
6161 n1 = fd->loop.n1;
6162 n2 = fd->loop.n2;
6163 step = fd->loop.step;
6164 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6166 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6167 OMP_CLAUSE__LOOPTEMP_);
6168 gcc_assert (innerc);
6169 n1 = OMP_CLAUSE_DECL (innerc);
6170 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6171 OMP_CLAUSE__LOOPTEMP_);
6172 gcc_assert (innerc);
6173 n2 = OMP_CLAUSE_DECL (innerc);
6175 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6176 true, NULL_TREE, true, GSI_SAME_STMT);
6177 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6178 true, NULL_TREE, true, GSI_SAME_STMT);
6179 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6180 true, NULL_TREE, true, GSI_SAME_STMT);
6182 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6183 t = fold_build2 (PLUS_EXPR, itype, step, t);
6184 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6185 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6186 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6187 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6188 fold_build1 (NEGATE_EXPR, itype, t),
6189 fold_build1 (NEGATE_EXPR, itype, step));
6190 else
6191 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6192 t = fold_convert (itype, t);
6193 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6195 q = create_tmp_reg (itype, "q");
6196 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6197 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6198 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6200 tt = create_tmp_reg (itype, "tt");
6201 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6202 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6203 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6205 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6206 gcond *cond_stmt = gimple_build_cond_empty (t);
6207 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6209 second_bb = split_block (entry_bb, cond_stmt)->dest;
6210 gsi = gsi_last_bb (second_bb);
6211 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6213 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6214 GSI_SAME_STMT);
6215 gassign *assign_stmt
6216 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6217 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6219 third_bb = split_block (second_bb, assign_stmt)->dest;
6220 gsi = gsi_last_bb (third_bb);
6221 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6223 t = build2 (MULT_EXPR, itype, q, threadid);
6224 t = build2 (PLUS_EXPR, itype, t, tt);
6225 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6227 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6228 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6230 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6231 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6233 /* Remove the GIMPLE_OMP_FOR statement. */
6234 gsi_remove (&gsi, true);
6236 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6237 gsi = gsi_start_bb (seq_start_bb);
6239 tree startvar = fd->loop.v;
6240 tree endvar = NULL_TREE;
6242 if (gimple_omp_for_combined_p (fd->for_stmt))
6244 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6245 ? gimple_omp_parallel_clauses (inner_stmt)
6246 : gimple_omp_for_clauses (inner_stmt);
6247 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6248 gcc_assert (innerc);
6249 startvar = OMP_CLAUSE_DECL (innerc);
6250 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6251 OMP_CLAUSE__LOOPTEMP_);
6252 gcc_assert (innerc);
6253 endvar = OMP_CLAUSE_DECL (innerc);
6255 t = fold_convert (itype, s0);
6256 t = fold_build2 (MULT_EXPR, itype, t, step);
6257 if (POINTER_TYPE_P (type))
6258 t = fold_build_pointer_plus (n1, t);
6259 else
6260 t = fold_build2 (PLUS_EXPR, type, t, n1);
6261 t = fold_convert (TREE_TYPE (startvar), t);
6262 t = force_gimple_operand_gsi (&gsi, t,
6263 DECL_P (startvar)
6264 && TREE_ADDRESSABLE (startvar),
6265 NULL_TREE, false, GSI_CONTINUE_LINKING);
6266 assign_stmt = gimple_build_assign (startvar, t);
6267 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6269 t = fold_convert (itype, e0);
6270 t = fold_build2 (MULT_EXPR, itype, t, step);
6271 if (POINTER_TYPE_P (type))
6272 t = fold_build_pointer_plus (n1, t);
6273 else
6274 t = fold_build2 (PLUS_EXPR, type, t, n1);
6275 t = fold_convert (TREE_TYPE (startvar), t);
6276 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6277 false, GSI_CONTINUE_LINKING);
6278 if (endvar)
6280 assign_stmt = gimple_build_assign (endvar, e);
6281 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6282 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6283 assign_stmt = gimple_build_assign (fd->loop.v, e);
6284 else
6285 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6286 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6288 if (fd->collapse > 1)
6289 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6291 if (!broken_loop)
6293 /* The code controlling the sequential loop replaces the
6294 GIMPLE_OMP_CONTINUE. */
6295 gsi = gsi_last_bb (cont_bb);
6296 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6297 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6298 vmain = gimple_omp_continue_control_use (cont_stmt);
6299 vback = gimple_omp_continue_control_def (cont_stmt);
6301 if (!gimple_omp_for_combined_p (fd->for_stmt))
6303 if (POINTER_TYPE_P (type))
6304 t = fold_build_pointer_plus (vmain, step);
6305 else
6306 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6307 t = force_gimple_operand_gsi (&gsi, t,
6308 DECL_P (vback)
6309 && TREE_ADDRESSABLE (vback),
6310 NULL_TREE, true, GSI_SAME_STMT);
6311 assign_stmt = gimple_build_assign (vback, t);
6312 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6314 t = build2 (fd->loop.cond_code, boolean_type_node,
6315 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6316 ? t : vback, e);
6317 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6320 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6321 gsi_remove (&gsi, true);
6323 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6324 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6327 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6328 gsi = gsi_last_bb (exit_bb);
6329 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6331 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6332 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6334 gsi_remove (&gsi, true);
6336 /* Connect all the blocks. */
6337 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6338 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6339 ep = find_edge (entry_bb, second_bb);
6340 ep->flags = EDGE_TRUE_VALUE;
6341 ep->probability = REG_BR_PROB_BASE / 4;
6342 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6343 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6345 if (!broken_loop)
6347 ep = find_edge (cont_bb, body_bb);
6348 if (gimple_omp_for_combined_p (fd->for_stmt))
6350 remove_edge (ep);
6351 ep = NULL;
6353 else if (fd->collapse > 1)
6355 remove_edge (ep);
6356 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6358 else
6359 ep->flags = EDGE_TRUE_VALUE;
6360 find_edge (cont_bb, fin_bb)->flags
6361 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6364 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6365 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6366 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6368 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6369 recompute_dominator (CDI_DOMINATORS, body_bb));
6370 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6371 recompute_dominator (CDI_DOMINATORS, fin_bb));
6373 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6375 struct loop *loop = alloc_loop ();
6376 loop->header = body_bb;
6377 if (collapse_bb == NULL)
6378 loop->latch = cont_bb;
6379 add_loop (loop, body_bb->loop_father);
6384 /* A subroutine of expand_omp_for. Generate code for a parallel
6385 loop with static schedule and a specified chunk size. Given
6386 parameters:
6388 for (V = N1; V cond N2; V += STEP) BODY;
6390 where COND is "<" or ">", we generate pseudocode
6392 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6393 if (cond is <)
6394 adj = STEP - 1;
6395 else
6396 adj = STEP + 1;
6397 if ((__typeof (V)) -1 > 0 && cond is >)
6398 n = -(adj + N2 - N1) / -STEP;
6399 else
6400 n = (adj + N2 - N1) / STEP;
6401 trip = 0;
6402 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6403 here so that V is defined
6404 if the loop is not entered
6406 s0 = (trip * nthreads + threadid) * CHUNK;
6407 e0 = min(s0 + CHUNK, n);
6408 if (s0 < n) goto L1; else goto L4;
6410 V = s0 * STEP + N1;
6411 e = e0 * STEP + N1;
6413 BODY;
6414 V += STEP;
6415 if (V cond e) goto L2; else goto L3;
6417 trip += 1;
6418 goto L0;
6422 static void
6423 expand_omp_for_static_chunk (struct omp_region *region,
6424 struct omp_for_data *fd, gimple inner_stmt)
6426 tree n, s0, e0, e, t;
6427 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6428 tree type, itype, vmain, vback, vextra;
6429 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6430 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6431 gimple_stmt_iterator gsi;
6432 edge se;
6433 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6434 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6435 bool broken_loop = region->cont == NULL;
6436 tree *counts = NULL;
6437 tree n1, n2, step;
6439 itype = type = TREE_TYPE (fd->loop.v);
6440 if (POINTER_TYPE_P (type))
6441 itype = signed_type_for (type);
6443 entry_bb = region->entry;
6444 se = split_block (entry_bb, last_stmt (entry_bb));
6445 entry_bb = se->src;
6446 iter_part_bb = se->dest;
6447 cont_bb = region->cont;
6448 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6449 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6450 gcc_assert (broken_loop
6451 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6452 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6453 body_bb = single_succ (seq_start_bb);
6454 if (!broken_loop)
6456 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6457 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6458 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6460 exit_bb = region->exit;
6462 /* Trip and adjustment setup goes in ENTRY_BB. */
6463 gsi = gsi_last_bb (entry_bb);
6464 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6466 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6468 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6469 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6472 if (fd->collapse > 1)
6474 int first_zero_iter = -1;
6475 basic_block l2_dom_bb = NULL;
6477 counts = XALLOCAVEC (tree, fd->collapse);
6478 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6479 fin_bb, first_zero_iter,
6480 l2_dom_bb);
6481 t = NULL_TREE;
6483 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6484 t = integer_one_node;
6485 else
6486 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6487 fold_convert (type, fd->loop.n1),
6488 fold_convert (type, fd->loop.n2));
6489 if (fd->collapse == 1
6490 && TYPE_UNSIGNED (type)
6491 && (t == NULL_TREE || !integer_onep (t)))
6493 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6494 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6495 true, GSI_SAME_STMT);
6496 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6497 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6498 true, GSI_SAME_STMT);
6499 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6500 NULL_TREE, NULL_TREE);
6501 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6502 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6503 expand_omp_regimplify_p, NULL, NULL)
6504 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6505 expand_omp_regimplify_p, NULL, NULL))
6507 gsi = gsi_for_stmt (cond_stmt);
6508 gimple_regimplify_operands (cond_stmt, &gsi);
6510 se = split_block (entry_bb, cond_stmt);
6511 se->flags = EDGE_TRUE_VALUE;
6512 entry_bb = se->dest;
6513 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6514 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6515 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6516 if (gimple_in_ssa_p (cfun))
6518 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6519 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6520 !gsi_end_p (gpi); gsi_next (&gpi))
6522 gphi *phi = gpi.phi ();
6523 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6524 se, UNKNOWN_LOCATION);
6527 gsi = gsi_last_bb (entry_bb);
6530 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6531 t = fold_convert (itype, t);
6532 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6533 true, GSI_SAME_STMT);
6535 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6536 t = fold_convert (itype, t);
6537 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6538 true, GSI_SAME_STMT);
6540 n1 = fd->loop.n1;
6541 n2 = fd->loop.n2;
6542 step = fd->loop.step;
6543 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6545 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6546 OMP_CLAUSE__LOOPTEMP_);
6547 gcc_assert (innerc);
6548 n1 = OMP_CLAUSE_DECL (innerc);
6549 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6550 OMP_CLAUSE__LOOPTEMP_);
6551 gcc_assert (innerc);
6552 n2 = OMP_CLAUSE_DECL (innerc);
6554 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6555 true, NULL_TREE, true, GSI_SAME_STMT);
6556 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6557 true, NULL_TREE, true, GSI_SAME_STMT);
6558 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6559 true, NULL_TREE, true, GSI_SAME_STMT);
6560 fd->chunk_size
6561 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
6562 true, NULL_TREE, true, GSI_SAME_STMT);
6564 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6565 t = fold_build2 (PLUS_EXPR, itype, step, t);
6566 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6567 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6568 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6569 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6570 fold_build1 (NEGATE_EXPR, itype, t),
6571 fold_build1 (NEGATE_EXPR, itype, step));
6572 else
6573 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6574 t = fold_convert (itype, t);
6575 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6576 true, GSI_SAME_STMT);
6578 trip_var = create_tmp_reg (itype, ".trip");
6579 if (gimple_in_ssa_p (cfun))
6581 trip_init = make_ssa_name (trip_var);
6582 trip_main = make_ssa_name (trip_var);
6583 trip_back = make_ssa_name (trip_var);
6585 else
6587 trip_init = trip_var;
6588 trip_main = trip_var;
6589 trip_back = trip_var;
6592 gassign *assign_stmt
6593 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6594 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6596 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6597 t = fold_build2 (MULT_EXPR, itype, t, step);
6598 if (POINTER_TYPE_P (type))
6599 t = fold_build_pointer_plus (n1, t);
6600 else
6601 t = fold_build2 (PLUS_EXPR, type, t, n1);
6602 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6603 true, GSI_SAME_STMT);
6605 /* Remove the GIMPLE_OMP_FOR. */
6606 gsi_remove (&gsi, true);
6608 /* Iteration space partitioning goes in ITER_PART_BB. */
6609 gsi = gsi_last_bb (iter_part_bb);
6611 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6612 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6613 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6614 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6615 false, GSI_CONTINUE_LINKING);
6617 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6618 t = fold_build2 (MIN_EXPR, itype, t, n);
6619 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6620 false, GSI_CONTINUE_LINKING);
6622 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6623 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6625 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6626 gsi = gsi_start_bb (seq_start_bb);
6628 tree startvar = fd->loop.v;
6629 tree endvar = NULL_TREE;
6631 if (gimple_omp_for_combined_p (fd->for_stmt))
6633 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6634 ? gimple_omp_parallel_clauses (inner_stmt)
6635 : gimple_omp_for_clauses (inner_stmt);
6636 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6637 gcc_assert (innerc);
6638 startvar = OMP_CLAUSE_DECL (innerc);
6639 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6640 OMP_CLAUSE__LOOPTEMP_);
6641 gcc_assert (innerc);
6642 endvar = OMP_CLAUSE_DECL (innerc);
6645 t = fold_convert (itype, s0);
6646 t = fold_build2 (MULT_EXPR, itype, t, step);
6647 if (POINTER_TYPE_P (type))
6648 t = fold_build_pointer_plus (n1, t);
6649 else
6650 t = fold_build2 (PLUS_EXPR, type, t, n1);
6651 t = fold_convert (TREE_TYPE (startvar), t);
6652 t = force_gimple_operand_gsi (&gsi, t,
6653 DECL_P (startvar)
6654 && TREE_ADDRESSABLE (startvar),
6655 NULL_TREE, false, GSI_CONTINUE_LINKING);
6656 assign_stmt = gimple_build_assign (startvar, t);
6657 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6659 t = fold_convert (itype, e0);
6660 t = fold_build2 (MULT_EXPR, itype, t, step);
6661 if (POINTER_TYPE_P (type))
6662 t = fold_build_pointer_plus (n1, t);
6663 else
6664 t = fold_build2 (PLUS_EXPR, type, t, n1);
6665 t = fold_convert (TREE_TYPE (startvar), t);
6666 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6667 false, GSI_CONTINUE_LINKING);
6668 if (endvar)
6670 assign_stmt = gimple_build_assign (endvar, e);
6671 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6672 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6673 assign_stmt = gimple_build_assign (fd->loop.v, e);
6674 else
6675 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6676 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6678 if (fd->collapse > 1)
6679 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6681 if (!broken_loop)
6683 /* The code controlling the sequential loop goes in CONT_BB,
6684 replacing the GIMPLE_OMP_CONTINUE. */
6685 gsi = gsi_last_bb (cont_bb);
6686 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6687 vmain = gimple_omp_continue_control_use (cont_stmt);
6688 vback = gimple_omp_continue_control_def (cont_stmt);
6690 if (!gimple_omp_for_combined_p (fd->for_stmt))
6692 if (POINTER_TYPE_P (type))
6693 t = fold_build_pointer_plus (vmain, step);
6694 else
6695 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6696 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
6697 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6698 true, GSI_SAME_STMT);
6699 assign_stmt = gimple_build_assign (vback, t);
6700 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6702 t = build2 (fd->loop.cond_code, boolean_type_node,
6703 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6704 ? t : vback, e);
6705 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6708 /* Remove GIMPLE_OMP_CONTINUE. */
6709 gsi_remove (&gsi, true);
6711 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6712 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6714 /* Trip update code goes into TRIP_UPDATE_BB. */
6715 gsi = gsi_start_bb (trip_update_bb);
6717 t = build_int_cst (itype, 1);
6718 t = build2 (PLUS_EXPR, itype, trip_main, t);
6719 assign_stmt = gimple_build_assign (trip_back, t);
6720 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6723 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6724 gsi = gsi_last_bb (exit_bb);
6725 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6727 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6728 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6730 gsi_remove (&gsi, true);
6732 /* Connect the new blocks. */
6733 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6734 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6736 if (!broken_loop)
6738 se = find_edge (cont_bb, body_bb);
6739 if (gimple_omp_for_combined_p (fd->for_stmt))
6741 remove_edge (se);
6742 se = NULL;
6744 else if (fd->collapse > 1)
6746 remove_edge (se);
6747 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6749 else
6750 se->flags = EDGE_TRUE_VALUE;
6751 find_edge (cont_bb, trip_update_bb)->flags
6752 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6754 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6757 if (gimple_in_ssa_p (cfun))
6759 gphi_iterator psi;
6760 gphi *phi;
6761 edge re, ene;
6762 edge_var_map *vm;
6763 size_t i;
6765 gcc_assert (fd->collapse == 1 && !broken_loop);
6767 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6768 remove arguments of the phi nodes in fin_bb. We need to create
6769 appropriate phi nodes in iter_part_bb instead. */
6770 se = single_pred_edge (fin_bb);
6771 re = single_succ_edge (trip_update_bb);
6772 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
6773 ene = single_succ_edge (entry_bb);
6775 psi = gsi_start_phis (fin_bb);
6776 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6777 gsi_next (&psi), ++i)
6779 gphi *nphi;
6780 source_location locus;
6782 phi = psi.phi ();
6783 t = gimple_phi_result (phi);
6784 gcc_assert (t == redirect_edge_var_map_result (vm));
6785 nphi = create_phi_node (t, iter_part_bb);
6787 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6788 locus = gimple_phi_arg_location_from_edge (phi, se);
6790 /* A special case -- fd->loop.v is not yet computed in
6791 iter_part_bb, we need to use vextra instead. */
6792 if (t == fd->loop.v)
6793 t = vextra;
6794 add_phi_arg (nphi, t, ene, locus);
6795 locus = redirect_edge_var_map_location (vm);
6796 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6798 gcc_assert (gsi_end_p (psi) && i == head->length ());
6799 redirect_edge_var_map_clear (re);
6800 while (1)
6802 psi = gsi_start_phis (fin_bb);
6803 if (gsi_end_p (psi))
6804 break;
6805 remove_phi_node (&psi, false);
6808 /* Make phi node for trip. */
6809 phi = create_phi_node (trip_main, iter_part_bb);
6810 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6811 UNKNOWN_LOCATION);
6812 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6813 UNKNOWN_LOCATION);
6816 if (!broken_loop)
6817 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6818 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6819 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6820 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6821 recompute_dominator (CDI_DOMINATORS, fin_bb));
6822 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6823 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6824 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6825 recompute_dominator (CDI_DOMINATORS, body_bb));
6827 if (!broken_loop)
6829 struct loop *trip_loop = alloc_loop ();
6830 trip_loop->header = iter_part_bb;
6831 trip_loop->latch = trip_update_bb;
6832 add_loop (trip_loop, iter_part_bb->loop_father);
6834 if (!gimple_omp_for_combined_p (fd->for_stmt))
6836 struct loop *loop = alloc_loop ();
6837 loop->header = body_bb;
6838 if (collapse_bb == NULL)
6839 loop->latch = cont_bb;
6840 add_loop (loop, trip_loop);
6845 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
6846 Given parameters:
6847 for (V = N1; V cond N2; V += STEP) BODY;
6849 where COND is "<" or ">" or "!=", we generate pseudocode
6851 for (ind_var = low; ind_var < high; ind_var++)
6853 V = n1 + (ind_var * STEP)
6855 <BODY>
6858 In the above pseudocode, low and high are function parameters of the
6859 child function. In the function below, we are inserting a temp.
6860 variable that will be making a call to two OMP functions that will not be
6861 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
6862 with _Cilk_for). These functions are replaced with low and high
6863 by the function that handles taskreg. */
6866 static void
6867 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
6869 bool broken_loop = region->cont == NULL;
6870 basic_block entry_bb = region->entry;
6871 basic_block cont_bb = region->cont;
6873 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6874 gcc_assert (broken_loop
6875 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6876 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6877 basic_block l1_bb, l2_bb;
6879 if (!broken_loop)
6881 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6882 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6883 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6884 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6886 else
6888 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6889 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6890 l2_bb = single_succ (l1_bb);
6892 basic_block exit_bb = region->exit;
6893 basic_block l2_dom_bb = NULL;
6895 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
6897 /* Below statements until the "tree high_val = ..." are pseudo statements
6898 used to pass information to be used by expand_omp_taskreg.
6899 low_val and high_val will be replaced by the __low and __high
6900 parameter from the child function.
6902 The call_exprs part is a place-holder, it is mainly used
6903 to distinctly identify to the top-level part that this is
6904 where we should put low and high (reasoning given in header
6905 comment). */
6907 tree child_fndecl
6908 = gimple_omp_parallel_child_fn (
6909 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
6910 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
6911 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
6913 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
6914 high_val = t;
6915 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
6916 low_val = t;
6918 gcc_assert (low_val && high_val);
6920 tree type = TREE_TYPE (low_val);
6921 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
6922 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6924 /* Not needed in SSA form right now. */
6925 gcc_assert (!gimple_in_ssa_p (cfun));
6926 if (l2_dom_bb == NULL)
6927 l2_dom_bb = l1_bb;
6929 tree n1 = low_val;
6930 tree n2 = high_val;
6932 gimple stmt = gimple_build_assign (ind_var, n1);
6934 /* Replace the GIMPLE_OMP_FOR statement. */
6935 gsi_replace (&gsi, stmt, true);
6937 if (!broken_loop)
6939 /* Code to control the increment goes in the CONT_BB. */
6940 gsi = gsi_last_bb (cont_bb);
6941 stmt = gsi_stmt (gsi);
6942 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6943 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
6944 build_one_cst (type));
6946 /* Replace GIMPLE_OMP_CONTINUE. */
6947 gsi_replace (&gsi, stmt, true);
6950 /* Emit the condition in L1_BB. */
6951 gsi = gsi_after_labels (l1_bb);
6952 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
6953 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
6954 fd->loop.step);
6955 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
6956 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6957 fd->loop.n1, fold_convert (sizetype, t));
6958 else
6959 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6960 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
6961 t = fold_convert (TREE_TYPE (fd->loop.v), t);
6962 expand_omp_build_assign (&gsi, fd->loop.v, t);
6964 /* The condition is always '<' since the runtime will fill in the low
6965 and high values. */
6966 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
6967 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6969 /* Remove GIMPLE_OMP_RETURN. */
6970 gsi = gsi_last_bb (exit_bb);
6971 gsi_remove (&gsi, true);
6973 /* Connect the new blocks. */
6974 remove_edge (FALLTHRU_EDGE (entry_bb));
6976 edge e, ne;
6977 if (!broken_loop)
6979 remove_edge (BRANCH_EDGE (entry_bb));
6980 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6982 e = BRANCH_EDGE (l1_bb);
6983 ne = FALLTHRU_EDGE (l1_bb);
6984 e->flags = EDGE_TRUE_VALUE;
6986 else
6988 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6990 ne = single_succ_edge (l1_bb);
6991 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6994 ne->flags = EDGE_FALSE_VALUE;
6995 e->probability = REG_BR_PROB_BASE * 7 / 8;
6996 ne->probability = REG_BR_PROB_BASE / 8;
6998 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6999 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7000 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7002 if (!broken_loop)
7004 struct loop *loop = alloc_loop ();
7005 loop->header = l1_bb;
7006 loop->latch = cont_bb;
7007 add_loop (loop, l1_bb->loop_father);
7008 loop->safelen = INT_MAX;
7011 /* Pick the correct library function based on the precision of the
7012 induction variable type. */
7013 tree lib_fun = NULL_TREE;
7014 if (TYPE_PRECISION (type) == 32)
7015 lib_fun = cilk_for_32_fndecl;
7016 else if (TYPE_PRECISION (type) == 64)
7017 lib_fun = cilk_for_64_fndecl;
7018 else
7019 gcc_unreachable ();
7021 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7023 /* WS_ARGS contains the library function flavor to call:
7024 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7025 user-defined grain value. If the user does not define one, then zero
7026 is passed in by the parser. */
7027 vec_alloc (region->ws_args, 2);
7028 region->ws_args->quick_push (lib_fun);
7029 region->ws_args->quick_push (fd->chunk_size);
7032 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7033 loop. Given parameters:
7035 for (V = N1; V cond N2; V += STEP) BODY;
7037 where COND is "<" or ">", we generate pseudocode
7039 V = N1;
7040 goto L1;
7042 BODY;
7043 V += STEP;
7045 if (V cond N2) goto L0; else goto L2;
7048 For collapsed loops, given parameters:
7049 collapse(3)
7050 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7051 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7052 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7053 BODY;
7055 we generate pseudocode
7057 if (cond3 is <)
7058 adj = STEP3 - 1;
7059 else
7060 adj = STEP3 + 1;
7061 count3 = (adj + N32 - N31) / STEP3;
7062 if (cond2 is <)
7063 adj = STEP2 - 1;
7064 else
7065 adj = STEP2 + 1;
7066 count2 = (adj + N22 - N21) / STEP2;
7067 if (cond1 is <)
7068 adj = STEP1 - 1;
7069 else
7070 adj = STEP1 + 1;
7071 count1 = (adj + N12 - N11) / STEP1;
7072 count = count1 * count2 * count3;
7073 V = 0;
7074 V1 = N11;
7075 V2 = N21;
7076 V3 = N31;
7077 goto L1;
7079 BODY;
7080 V += 1;
7081 V3 += STEP3;
7082 V2 += (V3 cond3 N32) ? 0 : STEP2;
7083 V3 = (V3 cond3 N32) ? V3 : N31;
7084 V1 += (V2 cond2 N22) ? 0 : STEP1;
7085 V2 = (V2 cond2 N22) ? V2 : N21;
7087 if (V < count) goto L0; else goto L2;
7092 static void
7093 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7095 tree type, t;
7096 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7097 gimple_stmt_iterator gsi;
7098 gimple stmt;
7099 gcond *cond_stmt;
7100 bool broken_loop = region->cont == NULL;
7101 edge e, ne;
7102 tree *counts = NULL;
7103 int i;
7104 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7105 OMP_CLAUSE_SAFELEN);
7106 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7107 OMP_CLAUSE__SIMDUID_);
7108 tree n1, n2;
7110 type = TREE_TYPE (fd->loop.v);
7111 entry_bb = region->entry;
7112 cont_bb = region->cont;
7113 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7114 gcc_assert (broken_loop
7115 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7116 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7117 if (!broken_loop)
7119 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7120 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7121 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7122 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7124 else
7126 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7127 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7128 l2_bb = single_succ (l1_bb);
7130 exit_bb = region->exit;
7131 l2_dom_bb = NULL;
7133 gsi = gsi_last_bb (entry_bb);
7135 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7136 /* Not needed in SSA form right now. */
7137 gcc_assert (!gimple_in_ssa_p (cfun));
7138 if (fd->collapse > 1)
7140 int first_zero_iter = -1;
7141 basic_block zero_iter_bb = l2_bb;
7143 counts = XALLOCAVEC (tree, fd->collapse);
7144 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7145 zero_iter_bb, first_zero_iter,
7146 l2_dom_bb);
7148 if (l2_dom_bb == NULL)
7149 l2_dom_bb = l1_bb;
7151 n1 = fd->loop.n1;
7152 n2 = fd->loop.n2;
7153 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7155 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7156 OMP_CLAUSE__LOOPTEMP_);
7157 gcc_assert (innerc);
7158 n1 = OMP_CLAUSE_DECL (innerc);
7159 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7160 OMP_CLAUSE__LOOPTEMP_);
7161 gcc_assert (innerc);
7162 n2 = OMP_CLAUSE_DECL (innerc);
7163 expand_omp_build_assign (&gsi, fd->loop.v,
7164 fold_convert (type, n1));
7165 if (fd->collapse > 1)
7167 gsi_prev (&gsi);
7168 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7169 gsi_next (&gsi);
7172 else
7174 expand_omp_build_assign (&gsi, fd->loop.v,
7175 fold_convert (type, fd->loop.n1));
7176 if (fd->collapse > 1)
7177 for (i = 0; i < fd->collapse; i++)
7179 tree itype = TREE_TYPE (fd->loops[i].v);
7180 if (POINTER_TYPE_P (itype))
7181 itype = signed_type_for (itype);
7182 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7183 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7187 /* Remove the GIMPLE_OMP_FOR statement. */
7188 gsi_remove (&gsi, true);
7190 if (!broken_loop)
7192 /* Code to control the increment goes in the CONT_BB. */
7193 gsi = gsi_last_bb (cont_bb);
7194 stmt = gsi_stmt (gsi);
7195 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7197 if (POINTER_TYPE_P (type))
7198 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7199 else
7200 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7201 expand_omp_build_assign (&gsi, fd->loop.v, t);
7203 if (fd->collapse > 1)
7205 i = fd->collapse - 1;
7206 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7208 t = fold_convert (sizetype, fd->loops[i].step);
7209 t = fold_build_pointer_plus (fd->loops[i].v, t);
7211 else
7213 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7214 fd->loops[i].step);
7215 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7216 fd->loops[i].v, t);
7218 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7220 for (i = fd->collapse - 1; i > 0; i--)
7222 tree itype = TREE_TYPE (fd->loops[i].v);
7223 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7224 if (POINTER_TYPE_P (itype2))
7225 itype2 = signed_type_for (itype2);
7226 t = build3 (COND_EXPR, itype2,
7227 build2 (fd->loops[i].cond_code, boolean_type_node,
7228 fd->loops[i].v,
7229 fold_convert (itype, fd->loops[i].n2)),
7230 build_int_cst (itype2, 0),
7231 fold_convert (itype2, fd->loops[i - 1].step));
7232 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7233 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7234 else
7235 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7236 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7238 t = build3 (COND_EXPR, itype,
7239 build2 (fd->loops[i].cond_code, boolean_type_node,
7240 fd->loops[i].v,
7241 fold_convert (itype, fd->loops[i].n2)),
7242 fd->loops[i].v,
7243 fold_convert (itype, fd->loops[i].n1));
7244 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7248 /* Remove GIMPLE_OMP_CONTINUE. */
7249 gsi_remove (&gsi, true);
7252 /* Emit the condition in L1_BB. */
7253 gsi = gsi_start_bb (l1_bb);
7255 t = fold_convert (type, n2);
7256 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7257 false, GSI_CONTINUE_LINKING);
7258 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7259 cond_stmt = gimple_build_cond_empty (t);
7260 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7261 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7262 NULL, NULL)
7263 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7264 NULL, NULL))
7266 gsi = gsi_for_stmt (cond_stmt);
7267 gimple_regimplify_operands (cond_stmt, &gsi);
7270 /* Remove GIMPLE_OMP_RETURN. */
7271 gsi = gsi_last_bb (exit_bb);
7272 gsi_remove (&gsi, true);
7274 /* Connect the new blocks. */
7275 remove_edge (FALLTHRU_EDGE (entry_bb));
7277 if (!broken_loop)
7279 remove_edge (BRANCH_EDGE (entry_bb));
7280 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7282 e = BRANCH_EDGE (l1_bb);
7283 ne = FALLTHRU_EDGE (l1_bb);
7284 e->flags = EDGE_TRUE_VALUE;
7286 else
7288 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7290 ne = single_succ_edge (l1_bb);
7291 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7294 ne->flags = EDGE_FALSE_VALUE;
7295 e->probability = REG_BR_PROB_BASE * 7 / 8;
7296 ne->probability = REG_BR_PROB_BASE / 8;
7298 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7299 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7300 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7302 if (!broken_loop)
7304 struct loop *loop = alloc_loop ();
7305 loop->header = l1_bb;
7306 loop->latch = cont_bb;
7307 add_loop (loop, l1_bb->loop_father);
7308 if (safelen == NULL_TREE)
7309 loop->safelen = INT_MAX;
7310 else
7312 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7313 if (TREE_CODE (safelen) != INTEGER_CST)
7314 loop->safelen = 0;
7315 else if (!tree_fits_uhwi_p (safelen)
7316 || tree_to_uhwi (safelen) > INT_MAX)
7317 loop->safelen = INT_MAX;
7318 else
7319 loop->safelen = tree_to_uhwi (safelen);
7320 if (loop->safelen == 1)
7321 loop->safelen = 0;
7323 if (simduid)
7325 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7326 cfun->has_simduid_loops = true;
7328 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7329 the loop. */
7330 if ((flag_tree_loop_vectorize
7331 || (!global_options_set.x_flag_tree_loop_vectorize
7332 && !global_options_set.x_flag_tree_vectorize))
7333 && flag_tree_loop_optimize
7334 && loop->safelen > 1)
7336 loop->force_vectorize = true;
7337 cfun->has_force_vectorize_loops = true;
7343 /* Expand the OpenMP loop defined by REGION. */
7345 static void
7346 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7348 struct omp_for_data fd;
7349 struct omp_for_data_loop *loops;
7351 loops
7352 = (struct omp_for_data_loop *)
7353 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7354 * sizeof (struct omp_for_data_loop));
7355 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7356 &fd, loops);
7357 region->sched_kind = fd.sched_kind;
7359 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7360 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7361 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7362 if (region->cont)
7364 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7365 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7366 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7368 else
7369 /* If there isn't a continue then this is a degerate case where
7370 the introduction of abnormal edges during lowering will prevent
7371 original loops from being detected. Fix that up. */
7372 loops_state_set (LOOPS_NEED_FIXUP);
7374 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7375 expand_omp_simd (region, &fd);
7376 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7377 expand_cilk_for (region, &fd);
7378 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7379 && !fd.have_ordered)
7381 if (fd.chunk_size == NULL)
7382 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7383 else
7384 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7386 else
7388 int fn_index, start_ix, next_ix;
7390 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7391 == GF_OMP_FOR_KIND_FOR);
7392 if (fd.chunk_size == NULL
7393 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7394 fd.chunk_size = integer_zero_node;
7395 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7396 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7397 ? 3 : fd.sched_kind;
7398 fn_index += fd.have_ordered * 4;
7399 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7400 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7401 if (fd.iter_type == long_long_unsigned_type_node)
7403 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7404 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7405 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7406 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7408 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7409 (enum built_in_function) next_ix, inner_stmt);
7412 if (gimple_in_ssa_p (cfun))
7413 update_ssa (TODO_update_ssa_only_virtuals);
7417 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7419 v = GOMP_sections_start (n);
7421 switch (v)
7423 case 0:
7424 goto L2;
7425 case 1:
7426 section 1;
7427 goto L1;
7428 case 2:
7430 case n:
7432 default:
7433 abort ();
7436 v = GOMP_sections_next ();
7437 goto L0;
7439 reduction;
7441 If this is a combined parallel sections, replace the call to
7442 GOMP_sections_start with call to GOMP_sections_next. */
7444 static void
7445 expand_omp_sections (struct omp_region *region)
7447 tree t, u, vin = NULL, vmain, vnext, l2;
7448 unsigned len;
7449 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7450 gimple_stmt_iterator si, switch_si;
7451 gomp_sections *sections_stmt;
7452 gimple stmt;
7453 gomp_continue *cont;
7454 edge_iterator ei;
7455 edge e;
7456 struct omp_region *inner;
7457 unsigned i, casei;
7458 bool exit_reachable = region->cont != NULL;
7460 gcc_assert (region->exit != NULL);
7461 entry_bb = region->entry;
7462 l0_bb = single_succ (entry_bb);
7463 l1_bb = region->cont;
7464 l2_bb = region->exit;
7465 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7466 l2 = gimple_block_label (l2_bb);
7467 else
7469 /* This can happen if there are reductions. */
7470 len = EDGE_COUNT (l0_bb->succs);
7471 gcc_assert (len > 0);
7472 e = EDGE_SUCC (l0_bb, len - 1);
7473 si = gsi_last_bb (e->dest);
7474 l2 = NULL_TREE;
7475 if (gsi_end_p (si)
7476 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7477 l2 = gimple_block_label (e->dest);
7478 else
7479 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7481 si = gsi_last_bb (e->dest);
7482 if (gsi_end_p (si)
7483 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7485 l2 = gimple_block_label (e->dest);
7486 break;
7490 if (exit_reachable)
7491 default_bb = create_empty_bb (l1_bb->prev_bb);
7492 else
7493 default_bb = create_empty_bb (l0_bb);
7495 /* We will build a switch() with enough cases for all the
7496 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7497 and a default case to abort if something goes wrong. */
7498 len = EDGE_COUNT (l0_bb->succs);
7500 /* Use vec::quick_push on label_vec throughout, since we know the size
7501 in advance. */
7502 auto_vec<tree> label_vec (len);
7504 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7505 GIMPLE_OMP_SECTIONS statement. */
7506 si = gsi_last_bb (entry_bb);
7507 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
7508 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7509 vin = gimple_omp_sections_control (sections_stmt);
7510 if (!is_combined_parallel (region))
7512 /* If we are not inside a combined parallel+sections region,
7513 call GOMP_sections_start. */
7514 t = build_int_cst (unsigned_type_node, len - 1);
7515 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7516 stmt = gimple_build_call (u, 1, t);
7518 else
7520 /* Otherwise, call GOMP_sections_next. */
7521 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7522 stmt = gimple_build_call (u, 0);
7524 gimple_call_set_lhs (stmt, vin);
7525 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7526 gsi_remove (&si, true);
7528 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7529 L0_BB. */
7530 switch_si = gsi_last_bb (l0_bb);
7531 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7532 if (exit_reachable)
7534 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
7535 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7536 vmain = gimple_omp_continue_control_use (cont);
7537 vnext = gimple_omp_continue_control_def (cont);
7539 else
7541 vmain = vin;
7542 vnext = NULL_TREE;
7545 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7546 label_vec.quick_push (t);
7547 i = 1;
7549 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7550 for (inner = region->inner, casei = 1;
7551 inner;
7552 inner = inner->next, i++, casei++)
7554 basic_block s_entry_bb, s_exit_bb;
7556 /* Skip optional reduction region. */
7557 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7559 --i;
7560 --casei;
7561 continue;
7564 s_entry_bb = inner->entry;
7565 s_exit_bb = inner->exit;
7567 t = gimple_block_label (s_entry_bb);
7568 u = build_int_cst (unsigned_type_node, casei);
7569 u = build_case_label (u, NULL, t);
7570 label_vec.quick_push (u);
7572 si = gsi_last_bb (s_entry_bb);
7573 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7574 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7575 gsi_remove (&si, true);
7576 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7578 if (s_exit_bb == NULL)
7579 continue;
7581 si = gsi_last_bb (s_exit_bb);
7582 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7583 gsi_remove (&si, true);
7585 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7588 /* Error handling code goes in DEFAULT_BB. */
7589 t = gimple_block_label (default_bb);
7590 u = build_case_label (NULL, NULL, t);
7591 make_edge (l0_bb, default_bb, 0);
7592 add_bb_to_loop (default_bb, current_loops->tree_root);
7594 stmt = gimple_build_switch (vmain, u, label_vec);
7595 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7596 gsi_remove (&switch_si, true);
7598 si = gsi_start_bb (default_bb);
7599 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7600 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7602 if (exit_reachable)
7604 tree bfn_decl;
7606 /* Code to get the next section goes in L1_BB. */
7607 si = gsi_last_bb (l1_bb);
7608 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7610 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7611 stmt = gimple_build_call (bfn_decl, 0);
7612 gimple_call_set_lhs (stmt, vnext);
7613 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7614 gsi_remove (&si, true);
7616 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7619 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7620 si = gsi_last_bb (l2_bb);
7621 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7622 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7623 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7624 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7625 else
7626 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7627 stmt = gimple_build_call (t, 0);
7628 if (gimple_omp_return_lhs (gsi_stmt (si)))
7629 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7630 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7631 gsi_remove (&si, true);
7633 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7637 /* Expand code for an OpenMP single directive. We've already expanded
7638 much of the code, here we simply place the GOMP_barrier call. */
7640 static void
7641 expand_omp_single (struct omp_region *region)
7643 basic_block entry_bb, exit_bb;
7644 gimple_stmt_iterator si;
7646 entry_bb = region->entry;
7647 exit_bb = region->exit;
7649 si = gsi_last_bb (entry_bb);
7650 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7651 gsi_remove (&si, true);
7652 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7654 si = gsi_last_bb (exit_bb);
7655 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7657 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7658 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7660 gsi_remove (&si, true);
7661 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7665 /* Generic expansion for OpenMP synchronization directives: master,
7666 ordered and critical. All we need to do here is remove the entry
7667 and exit markers for REGION. */
7669 static void
7670 expand_omp_synch (struct omp_region *region)
7672 basic_block entry_bb, exit_bb;
7673 gimple_stmt_iterator si;
7675 entry_bb = region->entry;
7676 exit_bb = region->exit;
7678 si = gsi_last_bb (entry_bb);
7679 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7680 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7681 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7682 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7683 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7684 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7685 gsi_remove (&si, true);
7686 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7688 if (exit_bb)
7690 si = gsi_last_bb (exit_bb);
7691 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7692 gsi_remove (&si, true);
7693 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7697 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7698 operation as a normal volatile load. */
7700 static bool
7701 expand_omp_atomic_load (basic_block load_bb, tree addr,
7702 tree loaded_val, int index)
7704 enum built_in_function tmpbase;
7705 gimple_stmt_iterator gsi;
7706 basic_block store_bb;
7707 location_t loc;
7708 gimple stmt;
7709 tree decl, call, type, itype;
7711 gsi = gsi_last_bb (load_bb);
7712 stmt = gsi_stmt (gsi);
7713 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7714 loc = gimple_location (stmt);
7716 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7717 is smaller than word size, then expand_atomic_load assumes that the load
7718 is atomic. We could avoid the builtin entirely in this case. */
7720 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7721 decl = builtin_decl_explicit (tmpbase);
7722 if (decl == NULL_TREE)
7723 return false;
7725 type = TREE_TYPE (loaded_val);
7726 itype = TREE_TYPE (TREE_TYPE (decl));
7728 call = build_call_expr_loc (loc, decl, 2, addr,
7729 build_int_cst (NULL,
7730 gimple_omp_atomic_seq_cst_p (stmt)
7731 ? MEMMODEL_SEQ_CST
7732 : MEMMODEL_RELAXED));
7733 if (!useless_type_conversion_p (type, itype))
7734 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7735 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7737 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7738 gsi_remove (&gsi, true);
7740 store_bb = single_succ (load_bb);
7741 gsi = gsi_last_bb (store_bb);
7742 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7743 gsi_remove (&gsi, true);
7745 if (gimple_in_ssa_p (cfun))
7746 update_ssa (TODO_update_ssa_no_phi);
7748 return true;
7751 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7752 operation as a normal volatile store. */
7754 static bool
7755 expand_omp_atomic_store (basic_block load_bb, tree addr,
7756 tree loaded_val, tree stored_val, int index)
7758 enum built_in_function tmpbase;
7759 gimple_stmt_iterator gsi;
7760 basic_block store_bb = single_succ (load_bb);
7761 location_t loc;
7762 gimple stmt;
7763 tree decl, call, type, itype;
7764 machine_mode imode;
7765 bool exchange;
7767 gsi = gsi_last_bb (load_bb);
7768 stmt = gsi_stmt (gsi);
7769 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7771 /* If the load value is needed, then this isn't a store but an exchange. */
7772 exchange = gimple_omp_atomic_need_value_p (stmt);
7774 gsi = gsi_last_bb (store_bb);
7775 stmt = gsi_stmt (gsi);
7776 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7777 loc = gimple_location (stmt);
7779 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7780 is smaller than word size, then expand_atomic_store assumes that the store
7781 is atomic. We could avoid the builtin entirely in this case. */
7783 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7784 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7785 decl = builtin_decl_explicit (tmpbase);
7786 if (decl == NULL_TREE)
7787 return false;
7789 type = TREE_TYPE (stored_val);
7791 /* Dig out the type of the function's second argument. */
7792 itype = TREE_TYPE (decl);
7793 itype = TYPE_ARG_TYPES (itype);
7794 itype = TREE_CHAIN (itype);
7795 itype = TREE_VALUE (itype);
7796 imode = TYPE_MODE (itype);
7798 if (exchange && !can_atomic_exchange_p (imode, true))
7799 return false;
7801 if (!useless_type_conversion_p (itype, type))
7802 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7803 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7804 build_int_cst (NULL,
7805 gimple_omp_atomic_seq_cst_p (stmt)
7806 ? MEMMODEL_SEQ_CST
7807 : MEMMODEL_RELAXED));
7808 if (exchange)
7810 if (!useless_type_conversion_p (type, itype))
7811 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7812 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7815 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7816 gsi_remove (&gsi, true);
7818 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7819 gsi = gsi_last_bb (load_bb);
7820 gsi_remove (&gsi, true);
7822 if (gimple_in_ssa_p (cfun))
7823 update_ssa (TODO_update_ssa_no_phi);
7825 return true;
7828 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7829 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7830 size of the data type, and thus usable to find the index of the builtin
7831 decl. Returns false if the expression is not of the proper form. */
7833 static bool
7834 expand_omp_atomic_fetch_op (basic_block load_bb,
7835 tree addr, tree loaded_val,
7836 tree stored_val, int index)
7838 enum built_in_function oldbase, newbase, tmpbase;
7839 tree decl, itype, call;
7840 tree lhs, rhs;
7841 basic_block store_bb = single_succ (load_bb);
7842 gimple_stmt_iterator gsi;
7843 gimple stmt;
7844 location_t loc;
7845 enum tree_code code;
7846 bool need_old, need_new;
7847 machine_mode imode;
7848 bool seq_cst;
7850 /* We expect to find the following sequences:
7852 load_bb:
7853 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7855 store_bb:
7856 val = tmp OP something; (or: something OP tmp)
7857 GIMPLE_OMP_STORE (val)
7859 ???FIXME: Allow a more flexible sequence.
7860 Perhaps use data flow to pick the statements.
7864 gsi = gsi_after_labels (store_bb);
7865 stmt = gsi_stmt (gsi);
7866 loc = gimple_location (stmt);
7867 if (!is_gimple_assign (stmt))
7868 return false;
7869 gsi_next (&gsi);
7870 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7871 return false;
7872 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7873 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7874 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7875 gcc_checking_assert (!need_old || !need_new);
7877 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7878 return false;
7880 /* Check for one of the supported fetch-op operations. */
7881 code = gimple_assign_rhs_code (stmt);
7882 switch (code)
7884 case PLUS_EXPR:
7885 case POINTER_PLUS_EXPR:
7886 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7887 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7888 break;
7889 case MINUS_EXPR:
7890 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7891 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7892 break;
7893 case BIT_AND_EXPR:
7894 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7895 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7896 break;
7897 case BIT_IOR_EXPR:
7898 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7899 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7900 break;
7901 case BIT_XOR_EXPR:
7902 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7903 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7904 break;
7905 default:
7906 return false;
7909 /* Make sure the expression is of the proper form. */
7910 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7911 rhs = gimple_assign_rhs2 (stmt);
7912 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7913 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7914 rhs = gimple_assign_rhs1 (stmt);
7915 else
7916 return false;
7918 tmpbase = ((enum built_in_function)
7919 ((need_new ? newbase : oldbase) + index + 1));
7920 decl = builtin_decl_explicit (tmpbase);
7921 if (decl == NULL_TREE)
7922 return false;
7923 itype = TREE_TYPE (TREE_TYPE (decl));
7924 imode = TYPE_MODE (itype);
7926 /* We could test all of the various optabs involved, but the fact of the
7927 matter is that (with the exception of i486 vs i586 and xadd) all targets
7928 that support any atomic operaton optab also implements compare-and-swap.
7929 Let optabs.c take care of expanding any compare-and-swap loop. */
7930 if (!can_compare_and_swap_p (imode, true))
7931 return false;
7933 gsi = gsi_last_bb (load_bb);
7934 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7936 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7937 It only requires that the operation happen atomically. Thus we can
7938 use the RELAXED memory model. */
7939 call = build_call_expr_loc (loc, decl, 3, addr,
7940 fold_convert_loc (loc, itype, rhs),
7941 build_int_cst (NULL,
7942 seq_cst ? MEMMODEL_SEQ_CST
7943 : MEMMODEL_RELAXED));
7945 if (need_old || need_new)
7947 lhs = need_old ? loaded_val : stored_val;
7948 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7949 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7951 else
7952 call = fold_convert_loc (loc, void_type_node, call);
7953 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7954 gsi_remove (&gsi, true);
7956 gsi = gsi_last_bb (store_bb);
7957 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7958 gsi_remove (&gsi, true);
7959 gsi = gsi_last_bb (store_bb);
7960 gsi_remove (&gsi, true);
7962 if (gimple_in_ssa_p (cfun))
7963 update_ssa (TODO_update_ssa_no_phi);
7965 return true;
7968 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7970 oldval = *addr;
7971 repeat:
7972 newval = rhs; // with oldval replacing *addr in rhs
7973 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7974 if (oldval != newval)
7975 goto repeat;
7977 INDEX is log2 of the size of the data type, and thus usable to find the
7978 index of the builtin decl. */
7980 static bool
7981 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7982 tree addr, tree loaded_val, tree stored_val,
7983 int index)
7985 tree loadedi, storedi, initial, new_storedi, old_vali;
7986 tree type, itype, cmpxchg, iaddr;
7987 gimple_stmt_iterator si;
7988 basic_block loop_header = single_succ (load_bb);
7989 gimple phi, stmt;
7990 edge e;
7991 enum built_in_function fncode;
7993 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7994 order to use the RELAXED memory model effectively. */
7995 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7996 + index + 1);
7997 cmpxchg = builtin_decl_explicit (fncode);
7998 if (cmpxchg == NULL_TREE)
7999 return false;
8000 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8001 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8003 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8004 return false;
8006 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8007 si = gsi_last_bb (load_bb);
8008 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8010 /* For floating-point values, we'll need to view-convert them to integers
8011 so that we can perform the atomic compare and swap. Simplify the
8012 following code by always setting up the "i"ntegral variables. */
8013 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8015 tree iaddr_val;
8017 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8018 true));
8019 iaddr_val
8020 = force_gimple_operand_gsi (&si,
8021 fold_convert (TREE_TYPE (iaddr), addr),
8022 false, NULL_TREE, true, GSI_SAME_STMT);
8023 stmt = gimple_build_assign (iaddr, iaddr_val);
8024 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8025 loadedi = create_tmp_var (itype);
8026 if (gimple_in_ssa_p (cfun))
8027 loadedi = make_ssa_name (loadedi);
8029 else
8031 iaddr = addr;
8032 loadedi = loaded_val;
8035 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8036 tree loaddecl = builtin_decl_explicit (fncode);
8037 if (loaddecl)
8038 initial
8039 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8040 build_call_expr (loaddecl, 2, iaddr,
8041 build_int_cst (NULL_TREE,
8042 MEMMODEL_RELAXED)));
8043 else
8044 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8045 build_int_cst (TREE_TYPE (iaddr), 0));
8047 initial
8048 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8049 GSI_SAME_STMT);
8051 /* Move the value to the LOADEDI temporary. */
8052 if (gimple_in_ssa_p (cfun))
8054 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8055 phi = create_phi_node (loadedi, loop_header);
8056 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8057 initial);
8059 else
8060 gsi_insert_before (&si,
8061 gimple_build_assign (loadedi, initial),
8062 GSI_SAME_STMT);
8063 if (loadedi != loaded_val)
8065 gimple_stmt_iterator gsi2;
8066 tree x;
8068 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8069 gsi2 = gsi_start_bb (loop_header);
8070 if (gimple_in_ssa_p (cfun))
8072 gassign *stmt;
8073 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8074 true, GSI_SAME_STMT);
8075 stmt = gimple_build_assign (loaded_val, x);
8076 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8078 else
8080 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8081 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8082 true, GSI_SAME_STMT);
8085 gsi_remove (&si, true);
8087 si = gsi_last_bb (store_bb);
8088 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8090 if (iaddr == addr)
8091 storedi = stored_val;
8092 else
8093 storedi =
8094 force_gimple_operand_gsi (&si,
8095 build1 (VIEW_CONVERT_EXPR, itype,
8096 stored_val), true, NULL_TREE, true,
8097 GSI_SAME_STMT);
8099 /* Build the compare&swap statement. */
8100 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8101 new_storedi = force_gimple_operand_gsi (&si,
8102 fold_convert (TREE_TYPE (loadedi),
8103 new_storedi),
8104 true, NULL_TREE,
8105 true, GSI_SAME_STMT);
8107 if (gimple_in_ssa_p (cfun))
8108 old_vali = loadedi;
8109 else
8111 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8112 stmt = gimple_build_assign (old_vali, loadedi);
8113 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8115 stmt = gimple_build_assign (loadedi, new_storedi);
8116 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8119 /* Note that we always perform the comparison as an integer, even for
8120 floating point. This allows the atomic operation to properly
8121 succeed even with NaNs and -0.0. */
8122 stmt = gimple_build_cond_empty
8123 (build2 (NE_EXPR, boolean_type_node,
8124 new_storedi, old_vali));
8125 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8127 /* Update cfg. */
8128 e = single_succ_edge (store_bb);
8129 e->flags &= ~EDGE_FALLTHRU;
8130 e->flags |= EDGE_FALSE_VALUE;
8132 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8134 /* Copy the new value to loadedi (we already did that before the condition
8135 if we are not in SSA). */
8136 if (gimple_in_ssa_p (cfun))
8138 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8139 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8142 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8143 gsi_remove (&si, true);
8145 struct loop *loop = alloc_loop ();
8146 loop->header = loop_header;
8147 loop->latch = store_bb;
8148 add_loop (loop, loop_header->loop_father);
8150 if (gimple_in_ssa_p (cfun))
8151 update_ssa (TODO_update_ssa_no_phi);
8153 return true;
8156 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8158 GOMP_atomic_start ();
8159 *addr = rhs;
8160 GOMP_atomic_end ();
8162 The result is not globally atomic, but works so long as all parallel
8163 references are within #pragma omp atomic directives. According to
8164 responses received from omp@openmp.org, appears to be within spec.
8165 Which makes sense, since that's how several other compilers handle
8166 this situation as well.
8167 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8168 expanding. STORED_VAL is the operand of the matching
8169 GIMPLE_OMP_ATOMIC_STORE.
8171 We replace
8172 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8173 loaded_val = *addr;
8175 and replace
8176 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8177 *addr = stored_val;
8180 static bool
8181 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8182 tree addr, tree loaded_val, tree stored_val)
8184 gimple_stmt_iterator si;
8185 gassign *stmt;
8186 tree t;
8188 si = gsi_last_bb (load_bb);
8189 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8191 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8192 t = build_call_expr (t, 0);
8193 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8195 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8196 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8197 gsi_remove (&si, true);
8199 si = gsi_last_bb (store_bb);
8200 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8202 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8203 stored_val);
8204 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8206 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8207 t = build_call_expr (t, 0);
8208 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8209 gsi_remove (&si, true);
8211 if (gimple_in_ssa_p (cfun))
8212 update_ssa (TODO_update_ssa_no_phi);
8213 return true;
8216 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8217 using expand_omp_atomic_fetch_op. If it failed, we try to
8218 call expand_omp_atomic_pipeline, and if it fails too, the
8219 ultimate fallback is wrapping the operation in a mutex
8220 (expand_omp_atomic_mutex). REGION is the atomic region built
8221 by build_omp_regions_1(). */
8223 static void
8224 expand_omp_atomic (struct omp_region *region)
8226 basic_block load_bb = region->entry, store_bb = region->exit;
8227 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8228 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8229 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8230 tree addr = gimple_omp_atomic_load_rhs (load);
8231 tree stored_val = gimple_omp_atomic_store_val (store);
8232 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8233 HOST_WIDE_INT index;
8235 /* Make sure the type is one of the supported sizes. */
8236 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8237 index = exact_log2 (index);
8238 if (index >= 0 && index <= 4)
8240 unsigned int align = TYPE_ALIGN_UNIT (type);
8242 /* __sync builtins require strict data alignment. */
8243 if (exact_log2 (align) >= index)
8245 /* Atomic load. */
8246 if (loaded_val == stored_val
8247 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8248 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8249 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8250 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8251 return;
8253 /* Atomic store. */
8254 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8255 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8256 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8257 && store_bb == single_succ (load_bb)
8258 && first_stmt (store_bb) == store
8259 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8260 stored_val, index))
8261 return;
8263 /* When possible, use specialized atomic update functions. */
8264 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8265 && store_bb == single_succ (load_bb)
8266 && expand_omp_atomic_fetch_op (load_bb, addr,
8267 loaded_val, stored_val, index))
8268 return;
8270 /* If we don't have specialized __sync builtins, try and implement
8271 as a compare and swap loop. */
8272 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8273 loaded_val, stored_val, index))
8274 return;
8278 /* The ultimate fallback is wrapping the operation in a mutex. */
8279 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8283 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
8285 static void
8286 expand_omp_target (struct omp_region *region)
8288 basic_block entry_bb, exit_bb, new_bb;
8289 struct function *child_cfun = NULL;
8290 tree child_fn = NULL_TREE, block, t;
8291 gimple_stmt_iterator gsi;
8292 gomp_target *entry_stmt;
8293 gimple stmt;
8294 edge e;
8296 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8297 new_bb = region->entry;
8298 int kind = gimple_omp_target_kind (entry_stmt);
8299 if (kind == GF_OMP_TARGET_KIND_REGION)
8301 child_fn = gimple_omp_target_child_fn (entry_stmt);
8302 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8305 entry_bb = region->entry;
8306 exit_bb = region->exit;
8308 if (kind == GF_OMP_TARGET_KIND_REGION)
8310 unsigned srcidx, dstidx, num;
8312 /* If the target region needs data sent from the parent
8313 function, then the very first statement (except possible
8314 tree profile counter updates) of the parallel body
8315 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8316 &.OMP_DATA_O is passed as an argument to the child function,
8317 we need to replace it with the argument as seen by the child
8318 function.
8320 In most cases, this will end up being the identity assignment
8321 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8322 a function call that has been inlined, the original PARM_DECL
8323 .OMP_DATA_I may have been converted into a different local
8324 variable. In which case, we need to keep the assignment. */
8325 if (gimple_omp_target_data_arg (entry_stmt))
8327 basic_block entry_succ_bb = single_succ (entry_bb);
8328 gimple_stmt_iterator gsi;
8329 tree arg;
8330 gimple tgtcopy_stmt = NULL;
8331 tree sender
8332 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
8334 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8336 gcc_assert (!gsi_end_p (gsi));
8337 stmt = gsi_stmt (gsi);
8338 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8339 continue;
8341 if (gimple_num_ops (stmt) == 2)
8343 tree arg = gimple_assign_rhs1 (stmt);
8345 /* We're ignoring the subcode because we're
8346 effectively doing a STRIP_NOPS. */
8348 if (TREE_CODE (arg) == ADDR_EXPR
8349 && TREE_OPERAND (arg, 0) == sender)
8351 tgtcopy_stmt = stmt;
8352 break;
8357 gcc_assert (tgtcopy_stmt != NULL);
8358 arg = DECL_ARGUMENTS (child_fn);
8360 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8361 gsi_remove (&gsi, true);
8364 /* Declare local variables needed in CHILD_CFUN. */
8365 block = DECL_INITIAL (child_fn);
8366 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8367 /* The gimplifier could record temporaries in target block
8368 rather than in containing function's local_decls chain,
8369 which would mean cgraph missed finalizing them. Do it now. */
8370 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8371 if (TREE_CODE (t) == VAR_DECL
8372 && TREE_STATIC (t)
8373 && !DECL_EXTERNAL (t))
8374 varpool_node::finalize_decl (t);
8375 DECL_SAVED_TREE (child_fn) = NULL;
8376 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8377 gimple_set_body (child_fn, NULL);
8378 TREE_USED (block) = 1;
8380 /* Reset DECL_CONTEXT on function arguments. */
8381 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8382 DECL_CONTEXT (t) = child_fn;
8384 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8385 so that it can be moved to the child function. */
8386 gsi = gsi_last_bb (entry_bb);
8387 stmt = gsi_stmt (gsi);
8388 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
8389 && gimple_omp_target_kind (stmt)
8390 == GF_OMP_TARGET_KIND_REGION);
8391 gsi_remove (&gsi, true);
8392 e = split_block (entry_bb, stmt);
8393 entry_bb = e->dest;
8394 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8396 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8397 if (exit_bb)
8399 gsi = gsi_last_bb (exit_bb);
8400 gcc_assert (!gsi_end_p (gsi)
8401 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8402 stmt = gimple_build_return (NULL);
8403 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8404 gsi_remove (&gsi, true);
8407 /* Move the target region into CHILD_CFUN. */
8409 block = gimple_block (entry_stmt);
8411 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8412 if (exit_bb)
8413 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8414 /* When the OMP expansion process cannot guarantee an up-to-date
8415 loop tree arrange for the child function to fixup loops. */
8416 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8417 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8419 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8420 num = vec_safe_length (child_cfun->local_decls);
8421 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8423 t = (*child_cfun->local_decls)[srcidx];
8424 if (DECL_CONTEXT (t) == cfun->decl)
8425 continue;
8426 if (srcidx != dstidx)
8427 (*child_cfun->local_decls)[dstidx] = t;
8428 dstidx++;
8430 if (dstidx != num)
8431 vec_safe_truncate (child_cfun->local_decls, dstidx);
8433 /* Inform the callgraph about the new function. */
8434 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8435 cgraph_node::add_new_function (child_fn, true);
8437 #ifdef ENABLE_OFFLOADING
8438 /* Add the new function to the offload table. */
8439 vec_safe_push (offload_funcs, child_fn);
8440 #endif
8442 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8443 fixed in a following pass. */
8444 push_cfun (child_cfun);
8445 cgraph_edge::rebuild_edges ();
8447 #ifdef ENABLE_OFFLOADING
8448 /* Prevent IPA from removing child_fn as unreachable, since there are no
8449 refs from the parent function to child_fn in offload LTO mode. */
8450 struct cgraph_node *node = cgraph_node::get (child_fn);
8451 node->mark_force_output ();
8452 #endif
8454 /* Some EH regions might become dead, see PR34608. If
8455 pass_cleanup_cfg isn't the first pass to happen with the
8456 new child, these dead EH edges might cause problems.
8457 Clean them up now. */
8458 if (flag_exceptions)
8460 basic_block bb;
8461 bool changed = false;
8463 FOR_EACH_BB_FN (bb, cfun)
8464 changed |= gimple_purge_dead_eh_edges (bb);
8465 if (changed)
8466 cleanup_tree_cfg ();
8468 pop_cfun ();
8471 /* Emit a library call to launch the target region, or do data
8472 transfers. */
8473 tree t1, t2, t3, t4, device, cond, c, clauses;
8474 enum built_in_function start_ix;
8475 location_t clause_loc;
8477 clauses = gimple_omp_target_clauses (entry_stmt);
8479 if (kind == GF_OMP_TARGET_KIND_REGION)
8480 start_ix = BUILT_IN_GOMP_TARGET;
8481 else if (kind == GF_OMP_TARGET_KIND_DATA)
8482 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8483 else
8484 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8486 /* By default, the value of DEVICE is -1 (let runtime library choose)
8487 and there is no conditional. */
8488 cond = NULL_TREE;
8489 device = build_int_cst (integer_type_node, -1);
8491 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8492 if (c)
8493 cond = OMP_CLAUSE_IF_EXPR (c);
8495 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8496 if (c)
8498 device = OMP_CLAUSE_DEVICE_ID (c);
8499 clause_loc = OMP_CLAUSE_LOCATION (c);
8501 else
8502 clause_loc = gimple_location (entry_stmt);
8504 /* Ensure 'device' is of the correct type. */
8505 device = fold_convert_loc (clause_loc, integer_type_node, device);
8507 /* If we found the clause 'if (cond)', build
8508 (cond ? device : -2). */
8509 if (cond)
8511 cond = gimple_boolify (cond);
8513 basic_block cond_bb, then_bb, else_bb;
8514 edge e;
8515 tree tmp_var;
8517 tmp_var = create_tmp_var (TREE_TYPE (device));
8518 if (kind != GF_OMP_TARGET_KIND_REGION)
8520 gsi = gsi_last_bb (new_bb);
8521 gsi_prev (&gsi);
8522 e = split_block (new_bb, gsi_stmt (gsi));
8524 else
8525 e = split_block (new_bb, NULL);
8526 cond_bb = e->src;
8527 new_bb = e->dest;
8528 remove_edge (e);
8530 then_bb = create_empty_bb (cond_bb);
8531 else_bb = create_empty_bb (then_bb);
8532 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8533 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8535 stmt = gimple_build_cond_empty (cond);
8536 gsi = gsi_last_bb (cond_bb);
8537 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8539 gsi = gsi_start_bb (then_bb);
8540 stmt = gimple_build_assign (tmp_var, device);
8541 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8543 gsi = gsi_start_bb (else_bb);
8544 stmt = gimple_build_assign (tmp_var,
8545 build_int_cst (integer_type_node, -2));
8546 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8548 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8549 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8550 add_bb_to_loop (then_bb, cond_bb->loop_father);
8551 add_bb_to_loop (else_bb, cond_bb->loop_father);
8552 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8553 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8555 device = tmp_var;
8558 gsi = gsi_last_bb (new_bb);
8559 t = gimple_omp_target_data_arg (entry_stmt);
8560 if (t == NULL)
8562 t1 = size_zero_node;
8563 t2 = build_zero_cst (ptr_type_node);
8564 t3 = t2;
8565 t4 = t2;
8567 else
8569 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8570 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8571 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8572 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8573 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8576 gimple g;
8577 /* FIXME: This will be address of
8578 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8579 symbol, as soon as the linker plugin is able to create it for us. */
8580 tree openmp_target = build_zero_cst (ptr_type_node);
8581 if (kind == GF_OMP_TARGET_KIND_REGION)
8583 tree fnaddr = build_fold_addr_expr (child_fn);
8584 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8585 device, fnaddr, openmp_target, t1, t2, t3, t4);
8587 else
8588 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8589 device, openmp_target, t1, t2, t3, t4);
8590 gimple_set_location (g, gimple_location (entry_stmt));
8591 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8592 if (kind != GF_OMP_TARGET_KIND_REGION)
8594 g = gsi_stmt (gsi);
8595 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8596 gsi_remove (&gsi, true);
8598 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8600 gsi = gsi_last_bb (region->exit);
8601 g = gsi_stmt (gsi);
8602 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8603 gsi_remove (&gsi, true);
8608 /* Expand the parallel region tree rooted at REGION. Expansion
8609 proceeds in depth-first order. Innermost regions are expanded
8610 first. This way, parallel regions that require a new function to
8611 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8612 internal dependencies in their body. */
8614 static void
8615 expand_omp (struct omp_region *region)
8617 while (region)
8619 location_t saved_location;
8620 gimple inner_stmt = NULL;
8622 /* First, determine whether this is a combined parallel+workshare
8623 region. */
8624 if (region->type == GIMPLE_OMP_PARALLEL)
8625 determine_parallel_type (region);
8627 if (region->type == GIMPLE_OMP_FOR
8628 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8629 inner_stmt = last_stmt (region->inner->entry);
8631 if (region->inner)
8632 expand_omp (region->inner);
8634 saved_location = input_location;
8635 if (gimple_has_location (last_stmt (region->entry)))
8636 input_location = gimple_location (last_stmt (region->entry));
8638 switch (region->type)
8640 case GIMPLE_OMP_PARALLEL:
8641 case GIMPLE_OMP_TASK:
8642 expand_omp_taskreg (region);
8643 break;
8645 case GIMPLE_OMP_FOR:
8646 expand_omp_for (region, inner_stmt);
8647 break;
8649 case GIMPLE_OMP_SECTIONS:
8650 expand_omp_sections (region);
8651 break;
8653 case GIMPLE_OMP_SECTION:
8654 /* Individual omp sections are handled together with their
8655 parent GIMPLE_OMP_SECTIONS region. */
8656 break;
8658 case GIMPLE_OMP_SINGLE:
8659 expand_omp_single (region);
8660 break;
8662 case GIMPLE_OMP_MASTER:
8663 case GIMPLE_OMP_TASKGROUP:
8664 case GIMPLE_OMP_ORDERED:
8665 case GIMPLE_OMP_CRITICAL:
8666 case GIMPLE_OMP_TEAMS:
8667 expand_omp_synch (region);
8668 break;
8670 case GIMPLE_OMP_ATOMIC_LOAD:
8671 expand_omp_atomic (region);
8672 break;
8674 case GIMPLE_OMP_TARGET:
8675 expand_omp_target (region);
8676 break;
8678 default:
8679 gcc_unreachable ();
8682 input_location = saved_location;
8683 region = region->next;
8688 /* Helper for build_omp_regions. Scan the dominator tree starting at
8689 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8690 true, the function ends once a single tree is built (otherwise, whole
8691 forest of OMP constructs may be built). */
8693 static void
8694 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8695 bool single_tree)
8697 gimple_stmt_iterator gsi;
8698 gimple stmt;
8699 basic_block son;
8701 gsi = gsi_last_bb (bb);
8702 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8704 struct omp_region *region;
8705 enum gimple_code code;
8707 stmt = gsi_stmt (gsi);
8708 code = gimple_code (stmt);
8709 if (code == GIMPLE_OMP_RETURN)
8711 /* STMT is the return point out of region PARENT. Mark it
8712 as the exit point and make PARENT the immediately
8713 enclosing region. */
8714 gcc_assert (parent);
8715 region = parent;
8716 region->exit = bb;
8717 parent = parent->outer;
8719 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8721 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8722 GIMPLE_OMP_RETURN, but matches with
8723 GIMPLE_OMP_ATOMIC_LOAD. */
8724 gcc_assert (parent);
8725 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8726 region = parent;
8727 region->exit = bb;
8728 parent = parent->outer;
8731 else if (code == GIMPLE_OMP_CONTINUE)
8733 gcc_assert (parent);
8734 parent->cont = bb;
8736 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8738 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8739 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8742 else if (code == GIMPLE_OMP_TARGET
8743 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8744 new_omp_region (bb, code, parent);
8745 else
8747 /* Otherwise, this directive becomes the parent for a new
8748 region. */
8749 region = new_omp_region (bb, code, parent);
8750 parent = region;
8754 if (single_tree && !parent)
8755 return;
8757 for (son = first_dom_son (CDI_DOMINATORS, bb);
8758 son;
8759 son = next_dom_son (CDI_DOMINATORS, son))
8760 build_omp_regions_1 (son, parent, single_tree);
8763 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8764 root_omp_region. */
8766 static void
8767 build_omp_regions_root (basic_block root)
8769 gcc_assert (root_omp_region == NULL);
8770 build_omp_regions_1 (root, NULL, true);
8771 gcc_assert (root_omp_region != NULL);
8774 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8776 void
8777 omp_expand_local (basic_block head)
8779 build_omp_regions_root (head);
8780 if (dump_file && (dump_flags & TDF_DETAILS))
8782 fprintf (dump_file, "\nOMP region tree\n\n");
8783 dump_omp_region (dump_file, root_omp_region, 0);
8784 fprintf (dump_file, "\n");
8787 remove_exit_barriers (root_omp_region);
8788 expand_omp (root_omp_region);
8790 free_omp_regions ();
8793 /* Scan the CFG and build a tree of OMP regions. Return the root of
8794 the OMP region tree. */
8796 static void
8797 build_omp_regions (void)
8799 gcc_assert (root_omp_region == NULL);
8800 calculate_dominance_info (CDI_DOMINATORS);
8801 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8804 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8806 static unsigned int
8807 execute_expand_omp (void)
8809 build_omp_regions ();
8811 if (!root_omp_region)
8812 return 0;
8814 if (dump_file)
8816 fprintf (dump_file, "\nOMP region tree\n\n");
8817 dump_omp_region (dump_file, root_omp_region, 0);
8818 fprintf (dump_file, "\n");
8821 remove_exit_barriers (root_omp_region);
8823 expand_omp (root_omp_region);
8825 cleanup_tree_cfg ();
8827 free_omp_regions ();
8829 return 0;
8832 /* OMP expansion -- the default pass, run before creation of SSA form. */
8834 namespace {
8836 const pass_data pass_data_expand_omp =
8838 GIMPLE_PASS, /* type */
8839 "ompexp", /* name */
8840 OPTGROUP_NONE, /* optinfo_flags */
8841 TV_NONE, /* tv_id */
8842 PROP_gimple_any, /* properties_required */
8843 PROP_gimple_eomp, /* properties_provided */
8844 0, /* properties_destroyed */
8845 0, /* todo_flags_start */
8846 0, /* todo_flags_finish */
8849 class pass_expand_omp : public gimple_opt_pass
8851 public:
8852 pass_expand_omp (gcc::context *ctxt)
8853 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8856 /* opt_pass methods: */
8857 virtual unsigned int execute (function *)
8859 bool gate = ((flag_openmp != 0 || flag_openmp_simd != 0
8860 || flag_cilkplus != 0) && !seen_error ());
8862 /* This pass always runs, to provide PROP_gimple_eomp.
8863 But there is nothing to do unless -fopenmp is given. */
8864 if (!gate)
8865 return 0;
8867 return execute_expand_omp ();
8870 }; // class pass_expand_omp
8872 } // anon namespace
8874 gimple_opt_pass *
8875 make_pass_expand_omp (gcc::context *ctxt)
8877 return new pass_expand_omp (ctxt);
8880 namespace {
8882 const pass_data pass_data_expand_omp_ssa =
8884 GIMPLE_PASS, /* type */
8885 "ompexpssa", /* name */
8886 OPTGROUP_NONE, /* optinfo_flags */
8887 TV_NONE, /* tv_id */
8888 PROP_cfg | PROP_ssa, /* properties_required */
8889 PROP_gimple_eomp, /* properties_provided */
8890 0, /* properties_destroyed */
8891 0, /* todo_flags_start */
8892 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
8895 class pass_expand_omp_ssa : public gimple_opt_pass
8897 public:
8898 pass_expand_omp_ssa (gcc::context *ctxt)
8899 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
8902 /* opt_pass methods: */
8903 virtual bool gate (function *fun)
8905 return !(fun->curr_properties & PROP_gimple_eomp);
8907 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8909 }; // class pass_expand_omp_ssa
8911 } // anon namespace
8913 gimple_opt_pass *
8914 make_pass_expand_omp_ssa (gcc::context *ctxt)
8916 return new pass_expand_omp_ssa (ctxt);
8919 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8921 /* If ctx is a worksharing context inside of a cancellable parallel
8922 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8923 and conditional branch to parallel's cancel_label to handle
8924 cancellation in the implicit barrier. */
8926 static void
8927 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8929 gimple omp_return = gimple_seq_last_stmt (*body);
8930 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8931 if (gimple_omp_return_nowait_p (omp_return))
8932 return;
8933 if (ctx->outer
8934 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8935 && ctx->outer->cancellable)
8937 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8938 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8939 tree lhs = create_tmp_var (c_bool_type);
8940 gimple_omp_return_set_lhs (omp_return, lhs);
8941 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8942 gimple g = gimple_build_cond (NE_EXPR, lhs,
8943 fold_convert (c_bool_type,
8944 boolean_false_node),
8945 ctx->outer->cancel_label, fallthru_label);
8946 gimple_seq_add_stmt (body, g);
8947 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8951 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8952 CTX is the enclosing OMP context for the current statement. */
8954 static void
8955 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8957 tree block, control;
8958 gimple_stmt_iterator tgsi;
8959 gomp_sections *stmt;
8960 gimple t;
8961 gbind *new_stmt, *bind;
8962 gimple_seq ilist, dlist, olist, new_body;
8964 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
8966 push_gimplify_context ();
8968 dlist = NULL;
8969 ilist = NULL;
8970 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8971 &ilist, &dlist, ctx, NULL);
8973 new_body = gimple_omp_body (stmt);
8974 gimple_omp_set_body (stmt, NULL);
8975 tgsi = gsi_start (new_body);
8976 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8978 omp_context *sctx;
8979 gimple sec_start;
8981 sec_start = gsi_stmt (tgsi);
8982 sctx = maybe_lookup_ctx (sec_start);
8983 gcc_assert (sctx);
8985 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8986 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8987 GSI_CONTINUE_LINKING);
8988 gimple_omp_set_body (sec_start, NULL);
8990 if (gsi_one_before_end_p (tgsi))
8992 gimple_seq l = NULL;
8993 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8994 &l, ctx);
8995 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8996 gimple_omp_section_set_last (sec_start);
8999 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
9000 GSI_CONTINUE_LINKING);
9003 block = make_node (BLOCK);
9004 bind = gimple_build_bind (NULL, new_body, block);
9006 olist = NULL;
9007 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
9009 block = make_node (BLOCK);
9010 new_stmt = gimple_build_bind (NULL, NULL, block);
9011 gsi_replace (gsi_p, new_stmt, true);
9013 pop_gimplify_context (new_stmt);
9014 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9015 BLOCK_VARS (block) = gimple_bind_vars (bind);
9016 if (BLOCK_VARS (block))
9017 TREE_USED (block) = 1;
9019 new_body = NULL;
9020 gimple_seq_add_seq (&new_body, ilist);
9021 gimple_seq_add_stmt (&new_body, stmt);
9022 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
9023 gimple_seq_add_stmt (&new_body, bind);
9025 control = create_tmp_var (unsigned_type_node, ".section");
9026 t = gimple_build_omp_continue (control, control);
9027 gimple_omp_sections_set_control (stmt, control);
9028 gimple_seq_add_stmt (&new_body, t);
9030 gimple_seq_add_seq (&new_body, olist);
9031 if (ctx->cancellable)
9032 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9033 gimple_seq_add_seq (&new_body, dlist);
9035 new_body = maybe_catch_exception (new_body);
9037 t = gimple_build_omp_return
9038 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
9039 OMP_CLAUSE_NOWAIT));
9040 gimple_seq_add_stmt (&new_body, t);
9041 maybe_add_implicit_barrier_cancel (ctx, &new_body);
9043 gimple_bind_set_body (new_stmt, new_body);
9047 /* A subroutine of lower_omp_single. Expand the simple form of
9048 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
9050 if (GOMP_single_start ())
9051 BODY;
9052 [ GOMP_barrier (); ] -> unless 'nowait' is present.
9054 FIXME. It may be better to delay expanding the logic of this until
9055 pass_expand_omp. The expanded logic may make the job more difficult
9056 to a synchronization analysis pass. */
9058 static void
9059 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
9061 location_t loc = gimple_location (single_stmt);
9062 tree tlabel = create_artificial_label (loc);
9063 tree flabel = create_artificial_label (loc);
9064 gimple call, cond;
9065 tree lhs, decl;
9067 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
9068 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
9069 call = gimple_build_call (decl, 0);
9070 gimple_call_set_lhs (call, lhs);
9071 gimple_seq_add_stmt (pre_p, call);
9073 cond = gimple_build_cond (EQ_EXPR, lhs,
9074 fold_convert_loc (loc, TREE_TYPE (lhs),
9075 boolean_true_node),
9076 tlabel, flabel);
9077 gimple_seq_add_stmt (pre_p, cond);
9078 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
9079 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9080 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
9084 /* A subroutine of lower_omp_single. Expand the simple form of
9085 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
9087 #pragma omp single copyprivate (a, b, c)
9089 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
9092 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
9094 BODY;
9095 copyout.a = a;
9096 copyout.b = b;
9097 copyout.c = c;
9098 GOMP_single_copy_end (&copyout);
9100 else
9102 a = copyout_p->a;
9103 b = copyout_p->b;
9104 c = copyout_p->c;
9106 GOMP_barrier ();
9109 FIXME. It may be better to delay expanding the logic of this until
9110 pass_expand_omp. The expanded logic may make the job more difficult
9111 to a synchronization analysis pass. */
9113 static void
9114 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
9115 omp_context *ctx)
9117 tree ptr_type, t, l0, l1, l2, bfn_decl;
9118 gimple_seq copyin_seq;
9119 location_t loc = gimple_location (single_stmt);
9121 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
9123 ptr_type = build_pointer_type (ctx->record_type);
9124 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
9126 l0 = create_artificial_label (loc);
9127 l1 = create_artificial_label (loc);
9128 l2 = create_artificial_label (loc);
9130 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
9131 t = build_call_expr_loc (loc, bfn_decl, 0);
9132 t = fold_convert_loc (loc, ptr_type, t);
9133 gimplify_assign (ctx->receiver_decl, t, pre_p);
9135 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
9136 build_int_cst (ptr_type, 0));
9137 t = build3 (COND_EXPR, void_type_node, t,
9138 build_and_jump (&l0), build_and_jump (&l1));
9139 gimplify_and_add (t, pre_p);
9141 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
9143 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9145 copyin_seq = NULL;
9146 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
9147 &copyin_seq, ctx);
9149 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9150 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
9151 t = build_call_expr_loc (loc, bfn_decl, 1, t);
9152 gimplify_and_add (t, pre_p);
9154 t = build_and_jump (&l2);
9155 gimplify_and_add (t, pre_p);
9157 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
9159 gimple_seq_add_seq (pre_p, copyin_seq);
9161 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
9165 /* Expand code for an OpenMP single directive. */
9167 static void
9168 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9170 tree block;
9171 gimple t;
9172 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
9173 gbind *bind;
9174 gimple_seq bind_body, bind_body_tail = NULL, dlist;
9176 push_gimplify_context ();
9178 block = make_node (BLOCK);
9179 bind = gimple_build_bind (NULL, NULL, block);
9180 gsi_replace (gsi_p, bind, true);
9181 bind_body = NULL;
9182 dlist = NULL;
9183 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
9184 &bind_body, &dlist, ctx, NULL);
9185 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
9187 gimple_seq_add_stmt (&bind_body, single_stmt);
9189 if (ctx->record_type)
9190 lower_omp_single_copy (single_stmt, &bind_body, ctx);
9191 else
9192 lower_omp_single_simple (single_stmt, &bind_body);
9194 gimple_omp_set_body (single_stmt, NULL);
9196 gimple_seq_add_seq (&bind_body, dlist);
9198 bind_body = maybe_catch_exception (bind_body);
9200 t = gimple_build_omp_return
9201 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
9202 OMP_CLAUSE_NOWAIT));
9203 gimple_seq_add_stmt (&bind_body_tail, t);
9204 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
9205 if (ctx->record_type)
9207 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9208 tree clobber = build_constructor (ctx->record_type, NULL);
9209 TREE_THIS_VOLATILE (clobber) = 1;
9210 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9211 clobber), GSI_SAME_STMT);
9213 gimple_seq_add_seq (&bind_body, bind_body_tail);
9214 gimple_bind_set_body (bind, bind_body);
9216 pop_gimplify_context (bind);
9218 gimple_bind_append_vars (bind, ctx->block_vars);
9219 BLOCK_VARS (block) = ctx->block_vars;
9220 if (BLOCK_VARS (block))
9221 TREE_USED (block) = 1;
9225 /* Expand code for an OpenMP master directive. */
9227 static void
9228 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9230 tree block, lab = NULL, x, bfn_decl;
9231 gimple stmt = gsi_stmt (*gsi_p);
9232 gbind *bind;
9233 location_t loc = gimple_location (stmt);
9234 gimple_seq tseq;
9236 push_gimplify_context ();
9238 block = make_node (BLOCK);
9239 bind = gimple_build_bind (NULL, NULL, block);
9240 gsi_replace (gsi_p, bind, true);
9241 gimple_bind_add_stmt (bind, stmt);
9243 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9244 x = build_call_expr_loc (loc, bfn_decl, 0);
9245 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
9246 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9247 tseq = NULL;
9248 gimplify_and_add (x, &tseq);
9249 gimple_bind_add_seq (bind, tseq);
9251 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9252 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9253 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9254 gimple_omp_set_body (stmt, NULL);
9256 gimple_bind_add_stmt (bind, gimple_build_label (lab));
9258 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9260 pop_gimplify_context (bind);
9262 gimple_bind_append_vars (bind, ctx->block_vars);
9263 BLOCK_VARS (block) = ctx->block_vars;
9267 /* Expand code for an OpenMP taskgroup directive. */
9269 static void
9270 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9272 gimple stmt = gsi_stmt (*gsi_p);
9273 gcall *x;
9274 gbind *bind;
9275 tree block = make_node (BLOCK);
9277 bind = gimple_build_bind (NULL, NULL, block);
9278 gsi_replace (gsi_p, bind, true);
9279 gimple_bind_add_stmt (bind, stmt);
9281 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9283 gimple_bind_add_stmt (bind, x);
9285 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9286 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9287 gimple_omp_set_body (stmt, NULL);
9289 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9291 gimple_bind_append_vars (bind, ctx->block_vars);
9292 BLOCK_VARS (block) = ctx->block_vars;
9296 /* Expand code for an OpenMP ordered directive. */
9298 static void
9299 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9301 tree block;
9302 gimple stmt = gsi_stmt (*gsi_p);
9303 gcall *x;
9304 gbind *bind;
9306 push_gimplify_context ();
9308 block = make_node (BLOCK);
9309 bind = gimple_build_bind (NULL, NULL, block);
9310 gsi_replace (gsi_p, bind, true);
9311 gimple_bind_add_stmt (bind, stmt);
9313 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
9315 gimple_bind_add_stmt (bind, x);
9317 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9318 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9319 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9320 gimple_omp_set_body (stmt, NULL);
9322 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
9323 gimple_bind_add_stmt (bind, x);
9325 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9327 pop_gimplify_context (bind);
9329 gimple_bind_append_vars (bind, ctx->block_vars);
9330 BLOCK_VARS (block) = gimple_bind_vars (bind);
9334 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9335 substitution of a couple of function calls. But in the NAMED case,
9336 requires that languages coordinate a symbol name. It is therefore
9337 best put here in common code. */
9339 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
9341 static void
9342 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9344 tree block;
9345 tree name, lock, unlock;
9346 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
9347 gbind *bind;
9348 location_t loc = gimple_location (stmt);
9349 gimple_seq tbody;
9351 name = gimple_omp_critical_name (stmt);
9352 if (name)
9354 tree decl;
9356 if (!critical_name_mutexes)
9357 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
9359 tree *n = critical_name_mutexes->get (name);
9360 if (n == NULL)
9362 char *new_str;
9364 decl = create_tmp_var_raw (ptr_type_node);
9366 new_str = ACONCAT ((".gomp_critical_user_",
9367 IDENTIFIER_POINTER (name), NULL));
9368 DECL_NAME (decl) = get_identifier (new_str);
9369 TREE_PUBLIC (decl) = 1;
9370 TREE_STATIC (decl) = 1;
9371 DECL_COMMON (decl) = 1;
9372 DECL_ARTIFICIAL (decl) = 1;
9373 DECL_IGNORED_P (decl) = 1;
9375 varpool_node::finalize_decl (decl);
9377 critical_name_mutexes->put (name, decl);
9379 else
9380 decl = *n;
9382 /* If '#pragma omp critical' is inside target region or
9383 inside function marked as offloadable, the symbol must be
9384 marked as offloadable too. */
9385 omp_context *octx;
9386 if (cgraph_node::get (current_function_decl)->offloadable)
9387 varpool_node::get_create (decl)->offloadable = 1;
9388 else
9389 for (octx = ctx->outer; octx; octx = octx->outer)
9390 if (is_targetreg_ctx (octx))
9392 varpool_node::get_create (decl)->offloadable = 1;
9393 break;
9396 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
9397 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
9399 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
9400 unlock = build_call_expr_loc (loc, unlock, 1,
9401 build_fold_addr_expr_loc (loc, decl));
9403 else
9405 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
9406 lock = build_call_expr_loc (loc, lock, 0);
9408 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
9409 unlock = build_call_expr_loc (loc, unlock, 0);
9412 push_gimplify_context ();
9414 block = make_node (BLOCK);
9415 bind = gimple_build_bind (NULL, NULL, block);
9416 gsi_replace (gsi_p, bind, true);
9417 gimple_bind_add_stmt (bind, stmt);
9419 tbody = gimple_bind_body (bind);
9420 gimplify_and_add (lock, &tbody);
9421 gimple_bind_set_body (bind, tbody);
9423 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9424 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9425 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9426 gimple_omp_set_body (stmt, NULL);
9428 tbody = gimple_bind_body (bind);
9429 gimplify_and_add (unlock, &tbody);
9430 gimple_bind_set_body (bind, tbody);
9432 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9434 pop_gimplify_context (bind);
9435 gimple_bind_append_vars (bind, ctx->block_vars);
9436 BLOCK_VARS (block) = gimple_bind_vars (bind);
9440 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9441 for a lastprivate clause. Given a loop control predicate of (V
9442 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9443 is appended to *DLIST, iterator initialization is appended to
9444 *BODY_P. */
9446 static void
9447 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
9448 gimple_seq *dlist, struct omp_context *ctx)
9450 tree clauses, cond, vinit;
9451 enum tree_code cond_code;
9452 gimple_seq stmts;
9454 cond_code = fd->loop.cond_code;
9455 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
9457 /* When possible, use a strict equality expression. This can let VRP
9458 type optimizations deduce the value and remove a copy. */
9459 if (tree_fits_shwi_p (fd->loop.step))
9461 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
9462 if (step == 1 || step == -1)
9463 cond_code = EQ_EXPR;
9466 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
9468 clauses = gimple_omp_for_clauses (fd->for_stmt);
9469 stmts = NULL;
9470 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
9471 if (!gimple_seq_empty_p (stmts))
9473 gimple_seq_add_seq (&stmts, *dlist);
9474 *dlist = stmts;
9476 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9477 vinit = fd->loop.n1;
9478 if (cond_code == EQ_EXPR
9479 && tree_fits_shwi_p (fd->loop.n2)
9480 && ! integer_zerop (fd->loop.n2))
9481 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
9482 else
9483 vinit = unshare_expr (vinit);
9485 /* Initialize the iterator variable, so that threads that don't execute
9486 any iterations don't execute the lastprivate clauses by accident. */
9487 gimplify_assign (fd->loop.v, vinit, body_p);
9492 /* Lower code for an OpenMP loop directive. */
9494 static void
9495 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9497 tree *rhs_p, block;
9498 struct omp_for_data fd, *fdp = NULL;
9499 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
9500 gbind *new_stmt;
9501 gimple_seq omp_for_body, body, dlist;
9502 size_t i;
9504 push_gimplify_context ();
9506 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
9508 block = make_node (BLOCK);
9509 new_stmt = gimple_build_bind (NULL, NULL, block);
9510 /* Replace at gsi right away, so that 'stmt' is no member
9511 of a sequence anymore as we're going to add to to a different
9512 one below. */
9513 gsi_replace (gsi_p, new_stmt, true);
9515 /* Move declaration of temporaries in the loop body before we make
9516 it go away. */
9517 omp_for_body = gimple_omp_body (stmt);
9518 if (!gimple_seq_empty_p (omp_for_body)
9519 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9521 gbind *inner_bind
9522 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
9523 tree vars = gimple_bind_vars (inner_bind);
9524 gimple_bind_append_vars (new_stmt, vars);
9525 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9526 keep them on the inner_bind and it's block. */
9527 gimple_bind_set_vars (inner_bind, NULL_TREE);
9528 if (gimple_bind_block (inner_bind))
9529 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9532 if (gimple_omp_for_combined_into_p (stmt))
9534 extract_omp_for_data (stmt, &fd, NULL);
9535 fdp = &fd;
9537 /* We need two temporaries with fd.loop.v type (istart/iend)
9538 and then (fd.collapse - 1) temporaries with the same
9539 type for count2 ... countN-1 vars if not constant. */
9540 size_t count = 2;
9541 tree type = fd.iter_type;
9542 if (fd.collapse > 1
9543 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9544 count += fd.collapse - 1;
9545 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9546 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9547 tree clauses = *pc;
9548 if (parallel_for)
9549 outerc
9550 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9551 OMP_CLAUSE__LOOPTEMP_);
9552 for (i = 0; i < count; i++)
9554 tree temp;
9555 if (parallel_for)
9557 gcc_assert (outerc);
9558 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9559 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9560 OMP_CLAUSE__LOOPTEMP_);
9562 else
9564 temp = create_tmp_var (type);
9565 insert_decl_map (&ctx->outer->cb, temp, temp);
9567 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9568 OMP_CLAUSE_DECL (*pc) = temp;
9569 pc = &OMP_CLAUSE_CHAIN (*pc);
9571 *pc = clauses;
9574 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9575 dlist = NULL;
9576 body = NULL;
9577 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9578 fdp);
9579 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9581 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9583 /* Lower the header expressions. At this point, we can assume that
9584 the header is of the form:
9586 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9588 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9589 using the .omp_data_s mapping, if needed. */
9590 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9592 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9593 if (!is_gimple_min_invariant (*rhs_p))
9594 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9596 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9597 if (!is_gimple_min_invariant (*rhs_p))
9598 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9600 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9601 if (!is_gimple_min_invariant (*rhs_p))
9602 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9605 /* Once lowered, extract the bounds and clauses. */
9606 extract_omp_for_data (stmt, &fd, NULL);
9608 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9610 gimple_seq_add_stmt (&body, stmt);
9611 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9613 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9614 fd.loop.v));
9616 /* After the loop, add exit clauses. */
9617 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9619 if (ctx->cancellable)
9620 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9622 gimple_seq_add_seq (&body, dlist);
9624 body = maybe_catch_exception (body);
9626 /* Region exit marker goes at the end of the loop body. */
9627 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9628 maybe_add_implicit_barrier_cancel (ctx, &body);
9629 pop_gimplify_context (new_stmt);
9631 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9632 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9633 if (BLOCK_VARS (block))
9634 TREE_USED (block) = 1;
9636 gimple_bind_set_body (new_stmt, body);
9637 gimple_omp_set_body (stmt, NULL);
9638 gimple_omp_for_set_pre_body (stmt, NULL);
9641 /* Callback for walk_stmts. Check if the current statement only contains
9642 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9644 static tree
9645 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9646 bool *handled_ops_p,
9647 struct walk_stmt_info *wi)
9649 int *info = (int *) wi->info;
9650 gimple stmt = gsi_stmt (*gsi_p);
9652 *handled_ops_p = true;
9653 switch (gimple_code (stmt))
9655 WALK_SUBSTMTS;
9657 case GIMPLE_OMP_FOR:
9658 case GIMPLE_OMP_SECTIONS:
9659 *info = *info == 0 ? 1 : -1;
9660 break;
9661 default:
9662 *info = -1;
9663 break;
9665 return NULL;
9668 struct omp_taskcopy_context
9670 /* This field must be at the beginning, as we do "inheritance": Some
9671 callback functions for tree-inline.c (e.g., omp_copy_decl)
9672 receive a copy_body_data pointer that is up-casted to an
9673 omp_context pointer. */
9674 copy_body_data cb;
9675 omp_context *ctx;
9678 static tree
9679 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9681 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9683 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9684 return create_tmp_var (TREE_TYPE (var));
9686 return var;
9689 static tree
9690 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9692 tree name, new_fields = NULL, type, f;
9694 type = lang_hooks.types.make_type (RECORD_TYPE);
9695 name = DECL_NAME (TYPE_NAME (orig_type));
9696 name = build_decl (gimple_location (tcctx->ctx->stmt),
9697 TYPE_DECL, name, type);
9698 TYPE_NAME (type) = name;
9700 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9702 tree new_f = copy_node (f);
9703 DECL_CONTEXT (new_f) = type;
9704 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9705 TREE_CHAIN (new_f) = new_fields;
9706 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9707 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9708 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9709 &tcctx->cb, NULL);
9710 new_fields = new_f;
9711 tcctx->cb.decl_map->put (f, new_f);
9713 TYPE_FIELDS (type) = nreverse (new_fields);
9714 layout_type (type);
9715 return type;
9718 /* Create task copyfn. */
9720 static void
9721 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
9723 struct function *child_cfun;
9724 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9725 tree record_type, srecord_type, bind, list;
9726 bool record_needs_remap = false, srecord_needs_remap = false;
9727 splay_tree_node n;
9728 struct omp_taskcopy_context tcctx;
9729 location_t loc = gimple_location (task_stmt);
9731 child_fn = gimple_omp_task_copy_fn (task_stmt);
9732 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9733 gcc_assert (child_cfun->cfg == NULL);
9734 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9736 /* Reset DECL_CONTEXT on function arguments. */
9737 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9738 DECL_CONTEXT (t) = child_fn;
9740 /* Populate the function. */
9741 push_gimplify_context ();
9742 push_cfun (child_cfun);
9744 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9745 TREE_SIDE_EFFECTS (bind) = 1;
9746 list = NULL;
9747 DECL_SAVED_TREE (child_fn) = bind;
9748 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9750 /* Remap src and dst argument types if needed. */
9751 record_type = ctx->record_type;
9752 srecord_type = ctx->srecord_type;
9753 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9754 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9756 record_needs_remap = true;
9757 break;
9759 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9760 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9762 srecord_needs_remap = true;
9763 break;
9766 if (record_needs_remap || srecord_needs_remap)
9768 memset (&tcctx, '\0', sizeof (tcctx));
9769 tcctx.cb.src_fn = ctx->cb.src_fn;
9770 tcctx.cb.dst_fn = child_fn;
9771 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
9772 gcc_checking_assert (tcctx.cb.src_node);
9773 tcctx.cb.dst_node = tcctx.cb.src_node;
9774 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9775 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9776 tcctx.cb.eh_lp_nr = 0;
9777 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9778 tcctx.cb.decl_map = new hash_map<tree, tree>;
9779 tcctx.ctx = ctx;
9781 if (record_needs_remap)
9782 record_type = task_copyfn_remap_type (&tcctx, record_type);
9783 if (srecord_needs_remap)
9784 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9786 else
9787 tcctx.cb.decl_map = NULL;
9789 arg = DECL_ARGUMENTS (child_fn);
9790 TREE_TYPE (arg) = build_pointer_type (record_type);
9791 sarg = DECL_CHAIN (arg);
9792 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9794 /* First pass: initialize temporaries used in record_type and srecord_type
9795 sizes and field offsets. */
9796 if (tcctx.cb.decl_map)
9797 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9798 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9800 tree *p;
9802 decl = OMP_CLAUSE_DECL (c);
9803 p = tcctx.cb.decl_map->get (decl);
9804 if (p == NULL)
9805 continue;
9806 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9807 sf = (tree) n->value;
9808 sf = *tcctx.cb.decl_map->get (sf);
9809 src = build_simple_mem_ref_loc (loc, sarg);
9810 src = omp_build_component_ref (src, sf);
9811 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9812 append_to_statement_list (t, &list);
9815 /* Second pass: copy shared var pointers and copy construct non-VLA
9816 firstprivate vars. */
9817 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9818 switch (OMP_CLAUSE_CODE (c))
9820 case OMP_CLAUSE_SHARED:
9821 decl = OMP_CLAUSE_DECL (c);
9822 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9823 if (n == NULL)
9824 break;
9825 f = (tree) n->value;
9826 if (tcctx.cb.decl_map)
9827 f = *tcctx.cb.decl_map->get (f);
9828 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9829 sf = (tree) n->value;
9830 if (tcctx.cb.decl_map)
9831 sf = *tcctx.cb.decl_map->get (sf);
9832 src = build_simple_mem_ref_loc (loc, sarg);
9833 src = omp_build_component_ref (src, sf);
9834 dst = build_simple_mem_ref_loc (loc, arg);
9835 dst = omp_build_component_ref (dst, f);
9836 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9837 append_to_statement_list (t, &list);
9838 break;
9839 case OMP_CLAUSE_FIRSTPRIVATE:
9840 decl = OMP_CLAUSE_DECL (c);
9841 if (is_variable_sized (decl))
9842 break;
9843 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9844 if (n == NULL)
9845 break;
9846 f = (tree) n->value;
9847 if (tcctx.cb.decl_map)
9848 f = *tcctx.cb.decl_map->get (f);
9849 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9850 if (n != NULL)
9852 sf = (tree) n->value;
9853 if (tcctx.cb.decl_map)
9854 sf = *tcctx.cb.decl_map->get (sf);
9855 src = build_simple_mem_ref_loc (loc, sarg);
9856 src = omp_build_component_ref (src, sf);
9857 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9858 src = build_simple_mem_ref_loc (loc, src);
9860 else
9861 src = decl;
9862 dst = build_simple_mem_ref_loc (loc, arg);
9863 dst = omp_build_component_ref (dst, f);
9864 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9865 append_to_statement_list (t, &list);
9866 break;
9867 case OMP_CLAUSE_PRIVATE:
9868 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9869 break;
9870 decl = OMP_CLAUSE_DECL (c);
9871 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9872 f = (tree) n->value;
9873 if (tcctx.cb.decl_map)
9874 f = *tcctx.cb.decl_map->get (f);
9875 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9876 if (n != NULL)
9878 sf = (tree) n->value;
9879 if (tcctx.cb.decl_map)
9880 sf = *tcctx.cb.decl_map->get (sf);
9881 src = build_simple_mem_ref_loc (loc, sarg);
9882 src = omp_build_component_ref (src, sf);
9883 if (use_pointer_for_field (decl, NULL))
9884 src = build_simple_mem_ref_loc (loc, src);
9886 else
9887 src = decl;
9888 dst = build_simple_mem_ref_loc (loc, arg);
9889 dst = omp_build_component_ref (dst, f);
9890 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9891 append_to_statement_list (t, &list);
9892 break;
9893 default:
9894 break;
9897 /* Last pass: handle VLA firstprivates. */
9898 if (tcctx.cb.decl_map)
9899 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9900 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9902 tree ind, ptr, df;
9904 decl = OMP_CLAUSE_DECL (c);
9905 if (!is_variable_sized (decl))
9906 continue;
9907 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9908 if (n == NULL)
9909 continue;
9910 f = (tree) n->value;
9911 f = *tcctx.cb.decl_map->get (f);
9912 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9913 ind = DECL_VALUE_EXPR (decl);
9914 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9915 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9916 n = splay_tree_lookup (ctx->sfield_map,
9917 (splay_tree_key) TREE_OPERAND (ind, 0));
9918 sf = (tree) n->value;
9919 sf = *tcctx.cb.decl_map->get (sf);
9920 src = build_simple_mem_ref_loc (loc, sarg);
9921 src = omp_build_component_ref (src, sf);
9922 src = build_simple_mem_ref_loc (loc, src);
9923 dst = build_simple_mem_ref_loc (loc, arg);
9924 dst = omp_build_component_ref (dst, f);
9925 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9926 append_to_statement_list (t, &list);
9927 n = splay_tree_lookup (ctx->field_map,
9928 (splay_tree_key) TREE_OPERAND (ind, 0));
9929 df = (tree) n->value;
9930 df = *tcctx.cb.decl_map->get (df);
9931 ptr = build_simple_mem_ref_loc (loc, arg);
9932 ptr = omp_build_component_ref (ptr, df);
9933 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9934 build_fold_addr_expr_loc (loc, dst));
9935 append_to_statement_list (t, &list);
9938 t = build1 (RETURN_EXPR, void_type_node, NULL);
9939 append_to_statement_list (t, &list);
9941 if (tcctx.cb.decl_map)
9942 delete tcctx.cb.decl_map;
9943 pop_gimplify_context (NULL);
9944 BIND_EXPR_BODY (bind) = list;
9945 pop_cfun ();
9948 static void
9949 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9951 tree c, clauses;
9952 gimple g;
9953 size_t n_in = 0, n_out = 0, idx = 2, i;
9955 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9956 OMP_CLAUSE_DEPEND);
9957 gcc_assert (clauses);
9958 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9959 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9960 switch (OMP_CLAUSE_DEPEND_KIND (c))
9962 case OMP_CLAUSE_DEPEND_IN:
9963 n_in++;
9964 break;
9965 case OMP_CLAUSE_DEPEND_OUT:
9966 case OMP_CLAUSE_DEPEND_INOUT:
9967 n_out++;
9968 break;
9969 default:
9970 gcc_unreachable ();
9972 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9973 tree array = create_tmp_var (type);
9974 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9975 NULL_TREE);
9976 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9977 gimple_seq_add_stmt (iseq, g);
9978 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9979 NULL_TREE);
9980 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9981 gimple_seq_add_stmt (iseq, g);
9982 for (i = 0; i < 2; i++)
9984 if ((i ? n_in : n_out) == 0)
9985 continue;
9986 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9987 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9988 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9990 tree t = OMP_CLAUSE_DECL (c);
9991 t = fold_convert (ptr_type_node, t);
9992 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9993 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9994 NULL_TREE, NULL_TREE);
9995 g = gimple_build_assign (r, t);
9996 gimple_seq_add_stmt (iseq, g);
9999 tree *p = gimple_omp_task_clauses_ptr (stmt);
10000 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
10001 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
10002 OMP_CLAUSE_CHAIN (c) = *p;
10003 *p = c;
10004 tree clobber = build_constructor (type, NULL);
10005 TREE_THIS_VOLATILE (clobber) = 1;
10006 g = gimple_build_assign (array, clobber);
10007 gimple_seq_add_stmt (oseq, g);
10010 /* Lower the OpenMP parallel or task directive in the current statement
10011 in GSI_P. CTX holds context information for the directive. */
10013 static void
10014 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10016 tree clauses;
10017 tree child_fn, t;
10018 gimple stmt = gsi_stmt (*gsi_p);
10019 gbind *par_bind, *bind, *dep_bind = NULL;
10020 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
10021 location_t loc = gimple_location (stmt);
10023 clauses = gimple_omp_taskreg_clauses (stmt);
10024 par_bind
10025 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
10026 par_body = gimple_bind_body (par_bind);
10027 child_fn = ctx->cb.dst_fn;
10028 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
10029 && !gimple_omp_parallel_combined_p (stmt))
10031 struct walk_stmt_info wi;
10032 int ws_num = 0;
10034 memset (&wi, 0, sizeof (wi));
10035 wi.info = &ws_num;
10036 wi.val_only = true;
10037 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
10038 if (ws_num == 1)
10039 gimple_omp_parallel_set_combined_p (stmt, true);
10041 gimple_seq dep_ilist = NULL;
10042 gimple_seq dep_olist = NULL;
10043 if (gimple_code (stmt) == GIMPLE_OMP_TASK
10044 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
10046 push_gimplify_context ();
10047 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
10048 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
10051 if (ctx->srecord_type)
10052 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
10054 push_gimplify_context ();
10056 par_olist = NULL;
10057 par_ilist = NULL;
10058 par_rlist = NULL;
10059 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
10060 lower_omp (&par_body, ctx);
10061 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
10062 lower_reduction_clauses (clauses, &par_rlist, ctx);
10064 /* Declare all the variables created by mapping and the variables
10065 declared in the scope of the parallel body. */
10066 record_vars_into (ctx->block_vars, child_fn);
10067 record_vars_into (gimple_bind_vars (par_bind), child_fn);
10069 if (ctx->record_type)
10071 ctx->sender_decl
10072 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
10073 : ctx->record_type, ".omp_data_o");
10074 DECL_NAMELESS (ctx->sender_decl) = 1;
10075 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10076 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
10079 olist = NULL;
10080 ilist = NULL;
10081 lower_send_clauses (clauses, &ilist, &olist, ctx);
10082 lower_send_shared_vars (&ilist, &olist, ctx);
10084 if (ctx->record_type)
10086 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
10087 TREE_THIS_VOLATILE (clobber) = 1;
10088 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10089 clobber));
10092 /* Once all the expansions are done, sequence all the different
10093 fragments inside gimple_omp_body. */
10095 new_body = NULL;
10097 if (ctx->record_type)
10099 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10100 /* fixup_child_record_type might have changed receiver_decl's type. */
10101 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10102 gimple_seq_add_stmt (&new_body,
10103 gimple_build_assign (ctx->receiver_decl, t));
10106 gimple_seq_add_seq (&new_body, par_ilist);
10107 gimple_seq_add_seq (&new_body, par_body);
10108 gimple_seq_add_seq (&new_body, par_rlist);
10109 if (ctx->cancellable)
10110 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10111 gimple_seq_add_seq (&new_body, par_olist);
10112 new_body = maybe_catch_exception (new_body);
10113 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10114 gimple_omp_set_body (stmt, new_body);
10116 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
10117 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
10118 gimple_bind_add_seq (bind, ilist);
10119 gimple_bind_add_stmt (bind, stmt);
10120 gimple_bind_add_seq (bind, olist);
10122 pop_gimplify_context (NULL);
10124 if (dep_bind)
10126 gimple_bind_add_seq (dep_bind, dep_ilist);
10127 gimple_bind_add_stmt (dep_bind, bind);
10128 gimple_bind_add_seq (dep_bind, dep_olist);
10129 pop_gimplify_context (dep_bind);
10133 /* Lower the OpenMP target directive in the current statement
10134 in GSI_P. CTX holds context information for the directive. */
10136 static void
10137 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10139 tree clauses;
10140 tree child_fn, t, c;
10141 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
10142 gbind *tgt_bind = NULL, *bind;
10143 gimple_seq tgt_body = NULL, olist, ilist, new_body;
10144 location_t loc = gimple_location (stmt);
10145 int kind = gimple_omp_target_kind (stmt);
10146 unsigned int map_cnt = 0;
10148 clauses = gimple_omp_target_clauses (stmt);
10149 if (kind == GF_OMP_TARGET_KIND_REGION)
10151 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
10152 tgt_body = gimple_bind_body (tgt_bind);
10154 else if (kind == GF_OMP_TARGET_KIND_DATA)
10155 tgt_body = gimple_omp_body (stmt);
10156 child_fn = ctx->cb.dst_fn;
10158 push_gimplify_context ();
10160 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10161 switch (OMP_CLAUSE_CODE (c))
10163 tree var, x;
10165 default:
10166 break;
10167 case OMP_CLAUSE_MAP:
10168 case OMP_CLAUSE_TO:
10169 case OMP_CLAUSE_FROM:
10170 var = OMP_CLAUSE_DECL (c);
10171 if (!DECL_P (var))
10173 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10174 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10175 map_cnt++;
10176 continue;
10179 if (DECL_SIZE (var)
10180 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
10182 tree var2 = DECL_VALUE_EXPR (var);
10183 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
10184 var2 = TREE_OPERAND (var2, 0);
10185 gcc_assert (DECL_P (var2));
10186 var = var2;
10189 if (!maybe_lookup_field (var, ctx))
10190 continue;
10192 if (kind == GF_OMP_TARGET_KIND_REGION)
10194 x = build_receiver_ref (var, true, ctx);
10195 tree new_var = lookup_decl (var, ctx);
10196 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10197 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10198 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10199 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
10200 x = build_simple_mem_ref (x);
10201 SET_DECL_VALUE_EXPR (new_var, x);
10202 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
10204 map_cnt++;
10207 if (kind == GF_OMP_TARGET_KIND_REGION)
10209 target_nesting_level++;
10210 lower_omp (&tgt_body, ctx);
10211 target_nesting_level--;
10213 else if (kind == GF_OMP_TARGET_KIND_DATA)
10214 lower_omp (&tgt_body, ctx);
10216 if (kind == GF_OMP_TARGET_KIND_REGION)
10218 /* Declare all the variables created by mapping and the variables
10219 declared in the scope of the target body. */
10220 record_vars_into (ctx->block_vars, child_fn);
10221 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
10224 olist = NULL;
10225 ilist = NULL;
10226 if (ctx->record_type)
10228 ctx->sender_decl
10229 = create_tmp_var (ctx->record_type, ".omp_data_arr");
10230 DECL_NAMELESS (ctx->sender_decl) = 1;
10231 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10232 t = make_tree_vec (3);
10233 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
10234 TREE_VEC_ELT (t, 1)
10235 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
10236 ".omp_data_sizes");
10237 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
10238 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
10239 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
10240 TREE_VEC_ELT (t, 2)
10241 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
10242 map_cnt),
10243 ".omp_data_kinds");
10244 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
10245 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
10246 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
10247 gimple_omp_target_set_data_arg (stmt, t);
10249 vec<constructor_elt, va_gc> *vsize;
10250 vec<constructor_elt, va_gc> *vkind;
10251 vec_alloc (vsize, map_cnt);
10252 vec_alloc (vkind, map_cnt);
10253 unsigned int map_idx = 0;
10255 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10256 switch (OMP_CLAUSE_CODE (c))
10258 tree ovar, nc;
10260 default:
10261 break;
10262 case OMP_CLAUSE_MAP:
10263 case OMP_CLAUSE_TO:
10264 case OMP_CLAUSE_FROM:
10265 nc = c;
10266 ovar = OMP_CLAUSE_DECL (c);
10267 if (!DECL_P (ovar))
10269 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10270 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10272 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
10273 == get_base_address (ovar));
10274 nc = OMP_CLAUSE_CHAIN (c);
10275 ovar = OMP_CLAUSE_DECL (nc);
10277 else
10279 tree x = build_sender_ref (ovar, ctx);
10280 tree v
10281 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
10282 gimplify_assign (x, v, &ilist);
10283 nc = NULL_TREE;
10286 else
10288 if (DECL_SIZE (ovar)
10289 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
10291 tree ovar2 = DECL_VALUE_EXPR (ovar);
10292 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
10293 ovar2 = TREE_OPERAND (ovar2, 0);
10294 gcc_assert (DECL_P (ovar2));
10295 ovar = ovar2;
10297 if (!maybe_lookup_field (ovar, ctx))
10298 continue;
10301 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
10302 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
10303 talign = DECL_ALIGN_UNIT (ovar);
10304 if (nc)
10306 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
10307 tree x = build_sender_ref (ovar, ctx);
10308 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10309 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10310 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10311 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
10313 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10314 tree avar
10315 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
10316 mark_addressable (avar);
10317 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
10318 talign = DECL_ALIGN_UNIT (avar);
10319 avar = build_fold_addr_expr (avar);
10320 gimplify_assign (x, avar, &ilist);
10322 else if (is_gimple_reg (var))
10324 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10325 tree avar = create_tmp_var (TREE_TYPE (var));
10326 mark_addressable (avar);
10327 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
10328 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
10329 gimplify_assign (avar, var, &ilist);
10330 avar = build_fold_addr_expr (avar);
10331 gimplify_assign (x, avar, &ilist);
10332 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
10333 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
10334 && !TYPE_READONLY (TREE_TYPE (var)))
10336 x = build_sender_ref (ovar, ctx);
10337 x = build_simple_mem_ref (x);
10338 gimplify_assign (var, x, &olist);
10341 else
10343 var = build_fold_addr_expr (var);
10344 gimplify_assign (x, var, &ilist);
10347 tree s = OMP_CLAUSE_SIZE (c);
10348 if (s == NULL_TREE)
10349 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
10350 s = fold_convert (size_type_node, s);
10351 tree purpose = size_int (map_idx++);
10352 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
10353 if (TREE_CODE (s) != INTEGER_CST)
10354 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
10356 unsigned char tkind = 0;
10357 switch (OMP_CLAUSE_CODE (c))
10359 case OMP_CLAUSE_MAP:
10360 tkind = OMP_CLAUSE_MAP_KIND (c);
10361 break;
10362 case OMP_CLAUSE_TO:
10363 tkind = OMP_CLAUSE_MAP_TO;
10364 break;
10365 case OMP_CLAUSE_FROM:
10366 tkind = OMP_CLAUSE_MAP_FROM;
10367 break;
10368 default:
10369 gcc_unreachable ();
10371 talign = ceil_log2 (talign);
10372 tkind |= talign << 3;
10373 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
10374 build_int_cst (unsigned_char_type_node,
10375 tkind));
10376 if (nc && nc != c)
10377 c = nc;
10380 gcc_assert (map_idx == map_cnt);
10382 DECL_INITIAL (TREE_VEC_ELT (t, 1))
10383 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
10384 DECL_INITIAL (TREE_VEC_ELT (t, 2))
10385 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
10386 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
10388 gimple_seq initlist = NULL;
10389 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
10390 TREE_VEC_ELT (t, 1)),
10391 &initlist, true, NULL_TREE);
10392 gimple_seq_add_seq (&ilist, initlist);
10394 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
10395 NULL);
10396 TREE_THIS_VOLATILE (clobber) = 1;
10397 gimple_seq_add_stmt (&olist,
10398 gimple_build_assign (TREE_VEC_ELT (t, 1),
10399 clobber));
10402 tree clobber = build_constructor (ctx->record_type, NULL);
10403 TREE_THIS_VOLATILE (clobber) = 1;
10404 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10405 clobber));
10408 /* Once all the expansions are done, sequence all the different
10409 fragments inside gimple_omp_body. */
10411 new_body = NULL;
10413 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
10415 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10416 /* fixup_child_record_type might have changed receiver_decl's type. */
10417 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10418 gimple_seq_add_stmt (&new_body,
10419 gimple_build_assign (ctx->receiver_decl, t));
10422 if (kind == GF_OMP_TARGET_KIND_REGION)
10424 gimple_seq_add_seq (&new_body, tgt_body);
10425 new_body = maybe_catch_exception (new_body);
10427 else if (kind == GF_OMP_TARGET_KIND_DATA)
10428 new_body = tgt_body;
10429 if (kind != GF_OMP_TARGET_KIND_UPDATE)
10431 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10432 gimple_omp_set_body (stmt, new_body);
10435 bind = gimple_build_bind (NULL, NULL,
10436 tgt_bind ? gimple_bind_block (tgt_bind)
10437 : NULL_TREE);
10438 gsi_replace (gsi_p, bind, true);
10439 gimple_bind_add_seq (bind, ilist);
10440 gimple_bind_add_stmt (bind, stmt);
10441 gimple_bind_add_seq (bind, olist);
10443 pop_gimplify_context (NULL);
10446 /* Expand code for an OpenMP teams directive. */
10448 static void
10449 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10451 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
10452 push_gimplify_context ();
10454 tree block = make_node (BLOCK);
10455 gbind *bind = gimple_build_bind (NULL, NULL, block);
10456 gsi_replace (gsi_p, bind, true);
10457 gimple_seq bind_body = NULL;
10458 gimple_seq dlist = NULL;
10459 gimple_seq olist = NULL;
10461 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10462 OMP_CLAUSE_NUM_TEAMS);
10463 if (num_teams == NULL_TREE)
10464 num_teams = build_int_cst (unsigned_type_node, 0);
10465 else
10467 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
10468 num_teams = fold_convert (unsigned_type_node, num_teams);
10469 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
10471 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10472 OMP_CLAUSE_THREAD_LIMIT);
10473 if (thread_limit == NULL_TREE)
10474 thread_limit = build_int_cst (unsigned_type_node, 0);
10475 else
10477 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10478 thread_limit = fold_convert (unsigned_type_node, thread_limit);
10479 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
10480 fb_rvalue);
10483 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
10484 &bind_body, &dlist, ctx, NULL);
10485 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
10486 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
10487 gimple_seq_add_stmt (&bind_body, teams_stmt);
10489 location_t loc = gimple_location (teams_stmt);
10490 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
10491 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10492 gimple_set_location (call, loc);
10493 gimple_seq_add_stmt (&bind_body, call);
10495 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10496 gimple_omp_set_body (teams_stmt, NULL);
10497 gimple_seq_add_seq (&bind_body, olist);
10498 gimple_seq_add_seq (&bind_body, dlist);
10499 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10500 gimple_bind_set_body (bind, bind_body);
10502 pop_gimplify_context (bind);
10504 gimple_bind_append_vars (bind, ctx->block_vars);
10505 BLOCK_VARS (block) = ctx->block_vars;
10506 if (BLOCK_VARS (block))
10507 TREE_USED (block) = 1;
10511 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10512 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10513 of OpenMP context, but with task_shared_vars set. */
10515 static tree
10516 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10517 void *data)
10519 tree t = *tp;
10521 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10522 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
10523 return t;
10525 if (task_shared_vars
10526 && DECL_P (t)
10527 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10528 return t;
10530 /* If a global variable has been privatized, TREE_CONSTANT on
10531 ADDR_EXPR might be wrong. */
10532 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10533 recompute_tree_invariant_for_addr_expr (t);
10535 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10536 return NULL_TREE;
10539 static void
10540 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10542 gimple stmt = gsi_stmt (*gsi_p);
10543 struct walk_stmt_info wi;
10544 gcall *call_stmt;
10546 if (gimple_has_location (stmt))
10547 input_location = gimple_location (stmt);
10549 if (task_shared_vars)
10550 memset (&wi, '\0', sizeof (wi));
10552 /* If we have issued syntax errors, avoid doing any heavy lifting.
10553 Just replace the OpenMP directives with a NOP to avoid
10554 confusing RTL expansion. */
10555 if (seen_error () && is_gimple_omp (stmt))
10557 gsi_replace (gsi_p, gimple_build_nop (), true);
10558 return;
10561 switch (gimple_code (stmt))
10563 case GIMPLE_COND:
10565 gcond *cond_stmt = as_a <gcond *> (stmt);
10566 if ((ctx || task_shared_vars)
10567 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
10568 lower_omp_regimplify_p,
10569 ctx ? NULL : &wi, NULL)
10570 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
10571 lower_omp_regimplify_p,
10572 ctx ? NULL : &wi, NULL)))
10573 gimple_regimplify_operands (cond_stmt, gsi_p);
10575 break;
10576 case GIMPLE_CATCH:
10577 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
10578 break;
10579 case GIMPLE_EH_FILTER:
10580 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10581 break;
10582 case GIMPLE_TRY:
10583 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10584 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10585 break;
10586 case GIMPLE_TRANSACTION:
10587 lower_omp (gimple_transaction_body_ptr (
10588 as_a <gtransaction *> (stmt)),
10589 ctx);
10590 break;
10591 case GIMPLE_BIND:
10592 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
10593 break;
10594 case GIMPLE_OMP_PARALLEL:
10595 case GIMPLE_OMP_TASK:
10596 ctx = maybe_lookup_ctx (stmt);
10597 gcc_assert (ctx);
10598 if (ctx->cancellable)
10599 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10600 lower_omp_taskreg (gsi_p, ctx);
10601 break;
10602 case GIMPLE_OMP_FOR:
10603 ctx = maybe_lookup_ctx (stmt);
10604 gcc_assert (ctx);
10605 if (ctx->cancellable)
10606 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10607 lower_omp_for (gsi_p, ctx);
10608 break;
10609 case GIMPLE_OMP_SECTIONS:
10610 ctx = maybe_lookup_ctx (stmt);
10611 gcc_assert (ctx);
10612 if (ctx->cancellable)
10613 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10614 lower_omp_sections (gsi_p, ctx);
10615 break;
10616 case GIMPLE_OMP_SINGLE:
10617 ctx = maybe_lookup_ctx (stmt);
10618 gcc_assert (ctx);
10619 lower_omp_single (gsi_p, ctx);
10620 break;
10621 case GIMPLE_OMP_MASTER:
10622 ctx = maybe_lookup_ctx (stmt);
10623 gcc_assert (ctx);
10624 lower_omp_master (gsi_p, ctx);
10625 break;
10626 case GIMPLE_OMP_TASKGROUP:
10627 ctx = maybe_lookup_ctx (stmt);
10628 gcc_assert (ctx);
10629 lower_omp_taskgroup (gsi_p, ctx);
10630 break;
10631 case GIMPLE_OMP_ORDERED:
10632 ctx = maybe_lookup_ctx (stmt);
10633 gcc_assert (ctx);
10634 lower_omp_ordered (gsi_p, ctx);
10635 break;
10636 case GIMPLE_OMP_CRITICAL:
10637 ctx = maybe_lookup_ctx (stmt);
10638 gcc_assert (ctx);
10639 lower_omp_critical (gsi_p, ctx);
10640 break;
10641 case GIMPLE_OMP_ATOMIC_LOAD:
10642 if ((ctx || task_shared_vars)
10643 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
10644 as_a <gomp_atomic_load *> (stmt)),
10645 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10646 gimple_regimplify_operands (stmt, gsi_p);
10647 break;
10648 case GIMPLE_OMP_TARGET:
10649 ctx = maybe_lookup_ctx (stmt);
10650 gcc_assert (ctx);
10651 lower_omp_target (gsi_p, ctx);
10652 break;
10653 case GIMPLE_OMP_TEAMS:
10654 ctx = maybe_lookup_ctx (stmt);
10655 gcc_assert (ctx);
10656 lower_omp_teams (gsi_p, ctx);
10657 break;
10658 case GIMPLE_CALL:
10659 tree fndecl;
10660 call_stmt = as_a <gcall *> (stmt);
10661 fndecl = gimple_call_fndecl (call_stmt);
10662 if (fndecl
10663 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10664 switch (DECL_FUNCTION_CODE (fndecl))
10666 case BUILT_IN_GOMP_BARRIER:
10667 if (ctx == NULL)
10668 break;
10669 /* FALLTHRU */
10670 case BUILT_IN_GOMP_CANCEL:
10671 case BUILT_IN_GOMP_CANCELLATION_POINT:
10672 omp_context *cctx;
10673 cctx = ctx;
10674 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10675 cctx = cctx->outer;
10676 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
10677 if (!cctx->cancellable)
10679 if (DECL_FUNCTION_CODE (fndecl)
10680 == BUILT_IN_GOMP_CANCELLATION_POINT)
10682 stmt = gimple_build_nop ();
10683 gsi_replace (gsi_p, stmt, false);
10685 break;
10687 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10689 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10690 gimple_call_set_fndecl (call_stmt, fndecl);
10691 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
10693 tree lhs;
10694 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
10695 gimple_call_set_lhs (call_stmt, lhs);
10696 tree fallthru_label;
10697 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10698 gimple g;
10699 g = gimple_build_label (fallthru_label);
10700 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10701 g = gimple_build_cond (NE_EXPR, lhs,
10702 fold_convert (TREE_TYPE (lhs),
10703 boolean_false_node),
10704 cctx->cancel_label, fallthru_label);
10705 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10706 break;
10707 default:
10708 break;
10710 /* FALLTHRU */
10711 default:
10712 if ((ctx || task_shared_vars)
10713 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10714 ctx ? NULL : &wi))
10716 /* Just remove clobbers, this should happen only if we have
10717 "privatized" local addressable variables in SIMD regions,
10718 the clobber isn't needed in that case and gimplifying address
10719 of the ARRAY_REF into a pointer and creating MEM_REF based
10720 clobber would create worse code than we get with the clobber
10721 dropped. */
10722 if (gimple_clobber_p (stmt))
10724 gsi_replace (gsi_p, gimple_build_nop (), true);
10725 break;
10727 gimple_regimplify_operands (stmt, gsi_p);
10729 break;
10733 static void
10734 lower_omp (gimple_seq *body, omp_context *ctx)
10736 location_t saved_location = input_location;
10737 gimple_stmt_iterator gsi;
10738 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10739 lower_omp_1 (&gsi, ctx);
10740 /* During gimplification, we have not always invoked fold_stmt
10741 (gimplify.c:maybe_fold_stmt); call it now. */
10742 if (target_nesting_level)
10743 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10744 fold_stmt (&gsi);
10745 input_location = saved_location;
10748 /* Main entry point. */
10750 static unsigned int
10751 execute_lower_omp (void)
10753 gimple_seq body;
10754 int i;
10755 omp_context *ctx;
10757 /* This pass always runs, to provide PROP_gimple_lomp.
10758 But there is nothing to do unless -fopenmp is given. */
10759 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10760 return 0;
10762 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10763 delete_omp_context);
10765 body = gimple_body (current_function_decl);
10766 scan_omp (&body, NULL);
10767 gcc_assert (taskreg_nesting_level == 0);
10768 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
10769 finish_taskreg_scan (ctx);
10770 taskreg_contexts.release ();
10772 if (all_contexts->root)
10774 if (task_shared_vars)
10775 push_gimplify_context ();
10776 lower_omp (&body, NULL);
10777 if (task_shared_vars)
10778 pop_gimplify_context (NULL);
10781 if (all_contexts)
10783 splay_tree_delete (all_contexts);
10784 all_contexts = NULL;
10786 BITMAP_FREE (task_shared_vars);
10787 return 0;
10790 namespace {
10792 const pass_data pass_data_lower_omp =
10794 GIMPLE_PASS, /* type */
10795 "omplower", /* name */
10796 OPTGROUP_NONE, /* optinfo_flags */
10797 TV_NONE, /* tv_id */
10798 PROP_gimple_any, /* properties_required */
10799 PROP_gimple_lomp, /* properties_provided */
10800 0, /* properties_destroyed */
10801 0, /* todo_flags_start */
10802 0, /* todo_flags_finish */
10805 class pass_lower_omp : public gimple_opt_pass
10807 public:
10808 pass_lower_omp (gcc::context *ctxt)
10809 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10812 /* opt_pass methods: */
10813 virtual unsigned int execute (function *) { return execute_lower_omp (); }
10815 }; // class pass_lower_omp
10817 } // anon namespace
10819 gimple_opt_pass *
10820 make_pass_lower_omp (gcc::context *ctxt)
10822 return new pass_lower_omp (ctxt);
10825 /* The following is a utility to diagnose OpenMP structured block violations.
10826 It is not part of the "omplower" pass, as that's invoked too late. It
10827 should be invoked by the respective front ends after gimplification. */
10829 static splay_tree all_labels;
10831 /* Check for mismatched contexts and generate an error if needed. Return
10832 true if an error is detected. */
10834 static bool
10835 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10836 gimple branch_ctx, gimple label_ctx)
10838 if (label_ctx == branch_ctx)
10839 return false;
10843 Previously we kept track of the label's entire context in diagnose_sb_[12]
10844 so we could traverse it and issue a correct "exit" or "enter" error
10845 message upon a structured block violation.
10847 We built the context by building a list with tree_cons'ing, but there is
10848 no easy counterpart in gimple tuples. It seems like far too much work
10849 for issuing exit/enter error messages. If someone really misses the
10850 distinct error message... patches welcome.
10853 #if 0
10854 /* Try to avoid confusing the user by producing and error message
10855 with correct "exit" or "enter" verbiage. We prefer "exit"
10856 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10857 if (branch_ctx == NULL)
10858 exit_p = false;
10859 else
10861 while (label_ctx)
10863 if (TREE_VALUE (label_ctx) == branch_ctx)
10865 exit_p = false;
10866 break;
10868 label_ctx = TREE_CHAIN (label_ctx);
10872 if (exit_p)
10873 error ("invalid exit from OpenMP structured block");
10874 else
10875 error ("invalid entry to OpenMP structured block");
10876 #endif
10878 bool cilkplus_block = false;
10879 if (flag_cilkplus)
10881 if ((branch_ctx
10882 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10883 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10884 || (label_ctx
10885 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10886 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10887 cilkplus_block = true;
10890 /* If it's obvious we have an invalid entry, be specific about the error. */
10891 if (branch_ctx == NULL)
10893 if (cilkplus_block)
10894 error ("invalid entry to Cilk Plus structured block");
10895 else
10896 error ("invalid entry to OpenMP structured block");
10898 else
10900 /* Otherwise, be vague and lazy, but efficient. */
10901 if (cilkplus_block)
10902 error ("invalid branch to/from a Cilk Plus structured block");
10903 else
10904 error ("invalid branch to/from an OpenMP structured block");
10907 gsi_replace (gsi_p, gimple_build_nop (), false);
10908 return true;
10911 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10912 where each label is found. */
10914 static tree
10915 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10916 struct walk_stmt_info *wi)
10918 gimple context = (gimple) wi->info;
10919 gimple inner_context;
10920 gimple stmt = gsi_stmt (*gsi_p);
10922 *handled_ops_p = true;
10924 switch (gimple_code (stmt))
10926 WALK_SUBSTMTS;
10928 case GIMPLE_OMP_PARALLEL:
10929 case GIMPLE_OMP_TASK:
10930 case GIMPLE_OMP_SECTIONS:
10931 case GIMPLE_OMP_SINGLE:
10932 case GIMPLE_OMP_SECTION:
10933 case GIMPLE_OMP_MASTER:
10934 case GIMPLE_OMP_ORDERED:
10935 case GIMPLE_OMP_CRITICAL:
10936 case GIMPLE_OMP_TARGET:
10937 case GIMPLE_OMP_TEAMS:
10938 case GIMPLE_OMP_TASKGROUP:
10939 /* The minimal context here is just the current OMP construct. */
10940 inner_context = stmt;
10941 wi->info = inner_context;
10942 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10943 wi->info = context;
10944 break;
10946 case GIMPLE_OMP_FOR:
10947 inner_context = stmt;
10948 wi->info = inner_context;
10949 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10950 walk them. */
10951 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10952 diagnose_sb_1, NULL, wi);
10953 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10954 wi->info = context;
10955 break;
10957 case GIMPLE_LABEL:
10958 splay_tree_insert (all_labels,
10959 (splay_tree_key) gimple_label_label (
10960 as_a <glabel *> (stmt)),
10961 (splay_tree_value) context);
10962 break;
10964 default:
10965 break;
10968 return NULL_TREE;
10971 /* Pass 2: Check each branch and see if its context differs from that of
10972 the destination label's context. */
10974 static tree
10975 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10976 struct walk_stmt_info *wi)
10978 gimple context = (gimple) wi->info;
10979 splay_tree_node n;
10980 gimple stmt = gsi_stmt (*gsi_p);
10982 *handled_ops_p = true;
10984 switch (gimple_code (stmt))
10986 WALK_SUBSTMTS;
10988 case GIMPLE_OMP_PARALLEL:
10989 case GIMPLE_OMP_TASK:
10990 case GIMPLE_OMP_SECTIONS:
10991 case GIMPLE_OMP_SINGLE:
10992 case GIMPLE_OMP_SECTION:
10993 case GIMPLE_OMP_MASTER:
10994 case GIMPLE_OMP_ORDERED:
10995 case GIMPLE_OMP_CRITICAL:
10996 case GIMPLE_OMP_TARGET:
10997 case GIMPLE_OMP_TEAMS:
10998 case GIMPLE_OMP_TASKGROUP:
10999 wi->info = stmt;
11000 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
11001 wi->info = context;
11002 break;
11004 case GIMPLE_OMP_FOR:
11005 wi->info = stmt;
11006 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
11007 walk them. */
11008 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
11009 diagnose_sb_2, NULL, wi);
11010 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
11011 wi->info = context;
11012 break;
11014 case GIMPLE_COND:
11016 gcond *cond_stmt = as_a <gcond *> (stmt);
11017 tree lab = gimple_cond_true_label (cond_stmt);
11018 if (lab)
11020 n = splay_tree_lookup (all_labels,
11021 (splay_tree_key) lab);
11022 diagnose_sb_0 (gsi_p, context,
11023 n ? (gimple) n->value : NULL);
11025 lab = gimple_cond_false_label (cond_stmt);
11026 if (lab)
11028 n = splay_tree_lookup (all_labels,
11029 (splay_tree_key) lab);
11030 diagnose_sb_0 (gsi_p, context,
11031 n ? (gimple) n->value : NULL);
11034 break;
11036 case GIMPLE_GOTO:
11038 tree lab = gimple_goto_dest (stmt);
11039 if (TREE_CODE (lab) != LABEL_DECL)
11040 break;
11042 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
11043 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
11045 break;
11047 case GIMPLE_SWITCH:
11049 gswitch *switch_stmt = as_a <gswitch *> (stmt);
11050 unsigned int i;
11051 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
11053 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
11054 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
11055 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
11056 break;
11059 break;
11061 case GIMPLE_RETURN:
11062 diagnose_sb_0 (gsi_p, context, NULL);
11063 break;
11065 default:
11066 break;
11069 return NULL_TREE;
11072 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
11073 codes. */
11074 bool
11075 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
11076 int *region_idx)
11078 gimple last = last_stmt (bb);
11079 enum gimple_code code = gimple_code (last);
11080 struct omp_region *cur_region = *region;
11081 bool fallthru = false;
11083 switch (code)
11085 case GIMPLE_OMP_PARALLEL:
11086 case GIMPLE_OMP_TASK:
11087 case GIMPLE_OMP_FOR:
11088 case GIMPLE_OMP_SINGLE:
11089 case GIMPLE_OMP_TEAMS:
11090 case GIMPLE_OMP_MASTER:
11091 case GIMPLE_OMP_TASKGROUP:
11092 case GIMPLE_OMP_ORDERED:
11093 case GIMPLE_OMP_CRITICAL:
11094 case GIMPLE_OMP_SECTION:
11095 cur_region = new_omp_region (bb, code, cur_region);
11096 fallthru = true;
11097 break;
11099 case GIMPLE_OMP_TARGET:
11100 cur_region = new_omp_region (bb, code, cur_region);
11101 fallthru = true;
11102 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
11103 cur_region = cur_region->outer;
11104 break;
11106 case GIMPLE_OMP_SECTIONS:
11107 cur_region = new_omp_region (bb, code, cur_region);
11108 fallthru = true;
11109 break;
11111 case GIMPLE_OMP_SECTIONS_SWITCH:
11112 fallthru = false;
11113 break;
11115 case GIMPLE_OMP_ATOMIC_LOAD:
11116 case GIMPLE_OMP_ATOMIC_STORE:
11117 fallthru = true;
11118 break;
11120 case GIMPLE_OMP_RETURN:
11121 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
11122 somewhere other than the next block. This will be
11123 created later. */
11124 cur_region->exit = bb;
11125 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
11126 cur_region = cur_region->outer;
11127 break;
11129 case GIMPLE_OMP_CONTINUE:
11130 cur_region->cont = bb;
11131 switch (cur_region->type)
11133 case GIMPLE_OMP_FOR:
11134 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11135 succs edges as abnormal to prevent splitting
11136 them. */
11137 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
11138 /* Make the loopback edge. */
11139 make_edge (bb, single_succ (cur_region->entry),
11140 EDGE_ABNORMAL);
11142 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11143 corresponds to the case that the body of the loop
11144 is not executed at all. */
11145 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
11146 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
11147 fallthru = false;
11148 break;
11150 case GIMPLE_OMP_SECTIONS:
11151 /* Wire up the edges into and out of the nested sections. */
11153 basic_block switch_bb = single_succ (cur_region->entry);
11155 struct omp_region *i;
11156 for (i = cur_region->inner; i ; i = i->next)
11158 gcc_assert (i->type == GIMPLE_OMP_SECTION);
11159 make_edge (switch_bb, i->entry, 0);
11160 make_edge (i->exit, bb, EDGE_FALLTHRU);
11163 /* Make the loopback edge to the block with
11164 GIMPLE_OMP_SECTIONS_SWITCH. */
11165 make_edge (bb, switch_bb, 0);
11167 /* Make the edge from the switch to exit. */
11168 make_edge (switch_bb, bb->next_bb, 0);
11169 fallthru = false;
11171 break;
11173 default:
11174 gcc_unreachable ();
11176 break;
11178 default:
11179 gcc_unreachable ();
11182 if (*region != cur_region)
11184 *region = cur_region;
11185 if (cur_region)
11186 *region_idx = cur_region->entry->index;
11187 else
11188 *region_idx = 0;
11191 return fallthru;
11194 static unsigned int
11195 diagnose_omp_structured_block_errors (void)
11197 struct walk_stmt_info wi;
11198 gimple_seq body = gimple_body (current_function_decl);
11200 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
11202 memset (&wi, 0, sizeof (wi));
11203 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
11205 memset (&wi, 0, sizeof (wi));
11206 wi.want_locations = true;
11207 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
11209 gimple_set_body (current_function_decl, body);
11211 splay_tree_delete (all_labels);
11212 all_labels = NULL;
11214 return 0;
11217 namespace {
11219 const pass_data pass_data_diagnose_omp_blocks =
11221 GIMPLE_PASS, /* type */
11222 "*diagnose_omp_blocks", /* name */
11223 OPTGROUP_NONE, /* optinfo_flags */
11224 TV_NONE, /* tv_id */
11225 PROP_gimple_any, /* properties_required */
11226 0, /* properties_provided */
11227 0, /* properties_destroyed */
11228 0, /* todo_flags_start */
11229 0, /* todo_flags_finish */
11232 class pass_diagnose_omp_blocks : public gimple_opt_pass
11234 public:
11235 pass_diagnose_omp_blocks (gcc::context *ctxt)
11236 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
11239 /* opt_pass methods: */
11240 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
11241 virtual unsigned int execute (function *)
11243 return diagnose_omp_structured_block_errors ();
11246 }; // class pass_diagnose_omp_blocks
11248 } // anon namespace
11250 gimple_opt_pass *
11251 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
11253 return new pass_diagnose_omp_blocks (ctxt);
11256 /* SIMD clone supporting code. */
11258 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11259 of arguments to reserve space for. */
11261 static struct cgraph_simd_clone *
11262 simd_clone_struct_alloc (int nargs)
11264 struct cgraph_simd_clone *clone_info;
11265 size_t len = (sizeof (struct cgraph_simd_clone)
11266 + nargs * sizeof (struct cgraph_simd_clone_arg));
11267 clone_info = (struct cgraph_simd_clone *)
11268 ggc_internal_cleared_alloc (len);
11269 return clone_info;
11272 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11274 static inline void
11275 simd_clone_struct_copy (struct cgraph_simd_clone *to,
11276 struct cgraph_simd_clone *from)
11278 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
11279 + ((from->nargs - from->inbranch)
11280 * sizeof (struct cgraph_simd_clone_arg))));
11283 /* Return vector of parameter types of function FNDECL. This uses
11284 TYPE_ARG_TYPES if available, otherwise falls back to types of
11285 DECL_ARGUMENTS types. */
11287 vec<tree>
11288 simd_clone_vector_of_formal_parm_types (tree fndecl)
11290 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
11291 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
11292 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
11293 unsigned int i;
11294 tree arg;
11295 FOR_EACH_VEC_ELT (args, i, arg)
11296 args[i] = TREE_TYPE (args[i]);
11297 return args;
11300 /* Given a simd function in NODE, extract the simd specific
11301 information from the OMP clauses passed in CLAUSES, and return
11302 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11303 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11304 otherwise set to FALSE. */
11306 static struct cgraph_simd_clone *
11307 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
11308 bool *inbranch_specified)
11310 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
11311 tree t;
11312 int n;
11313 *inbranch_specified = false;
11315 n = args.length ();
11316 if (n > 0 && args.last () == void_type_node)
11317 n--;
11319 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11320 be cloned have a distinctive artificial label in addition to "omp
11321 declare simd". */
11322 bool cilk_clone
11323 = (flag_cilkplus
11324 && lookup_attribute ("cilk simd function",
11325 DECL_ATTRIBUTES (node->decl)));
11327 /* Allocate one more than needed just in case this is an in-branch
11328 clone which will require a mask argument. */
11329 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
11330 clone_info->nargs = n;
11331 clone_info->cilk_elemental = cilk_clone;
11333 if (!clauses)
11335 args.release ();
11336 return clone_info;
11338 clauses = TREE_VALUE (clauses);
11339 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
11340 return clone_info;
11342 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
11344 switch (OMP_CLAUSE_CODE (t))
11346 case OMP_CLAUSE_INBRANCH:
11347 clone_info->inbranch = 1;
11348 *inbranch_specified = true;
11349 break;
11350 case OMP_CLAUSE_NOTINBRANCH:
11351 clone_info->inbranch = 0;
11352 *inbranch_specified = true;
11353 break;
11354 case OMP_CLAUSE_SIMDLEN:
11355 clone_info->simdlen
11356 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
11357 break;
11358 case OMP_CLAUSE_LINEAR:
11360 tree decl = OMP_CLAUSE_DECL (t);
11361 tree step = OMP_CLAUSE_LINEAR_STEP (t);
11362 int argno = TREE_INT_CST_LOW (decl);
11363 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
11365 clone_info->args[argno].arg_type
11366 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
11367 clone_info->args[argno].linear_step = tree_to_shwi (step);
11368 gcc_assert (clone_info->args[argno].linear_step >= 0
11369 && clone_info->args[argno].linear_step < n);
11371 else
11373 if (POINTER_TYPE_P (args[argno]))
11374 step = fold_convert (ssizetype, step);
11375 if (!tree_fits_shwi_p (step))
11377 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11378 "ignoring large linear step");
11379 args.release ();
11380 return NULL;
11382 else if (integer_zerop (step))
11384 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11385 "ignoring zero linear step");
11386 args.release ();
11387 return NULL;
11389 else
11391 clone_info->args[argno].arg_type
11392 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
11393 clone_info->args[argno].linear_step = tree_to_shwi (step);
11396 break;
11398 case OMP_CLAUSE_UNIFORM:
11400 tree decl = OMP_CLAUSE_DECL (t);
11401 int argno = tree_to_uhwi (decl);
11402 clone_info->args[argno].arg_type
11403 = SIMD_CLONE_ARG_TYPE_UNIFORM;
11404 break;
11406 case OMP_CLAUSE_ALIGNED:
11408 tree decl = OMP_CLAUSE_DECL (t);
11409 int argno = tree_to_uhwi (decl);
11410 clone_info->args[argno].alignment
11411 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
11412 break;
11414 default:
11415 break;
11418 args.release ();
11419 return clone_info;
11422 /* Given a SIMD clone in NODE, calculate the characteristic data
11423 type and return the coresponding type. The characteristic data
11424 type is computed as described in the Intel Vector ABI. */
11426 static tree
11427 simd_clone_compute_base_data_type (struct cgraph_node *node,
11428 struct cgraph_simd_clone *clone_info)
11430 tree type = integer_type_node;
11431 tree fndecl = node->decl;
11433 /* a) For non-void function, the characteristic data type is the
11434 return type. */
11435 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
11436 type = TREE_TYPE (TREE_TYPE (fndecl));
11438 /* b) If the function has any non-uniform, non-linear parameters,
11439 then the characteristic data type is the type of the first
11440 such parameter. */
11441 else
11443 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
11444 for (unsigned int i = 0; i < clone_info->nargs; ++i)
11445 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
11447 type = map[i];
11448 break;
11450 map.release ();
11453 /* c) If the characteristic data type determined by a) or b) above
11454 is struct, union, or class type which is pass-by-value (except
11455 for the type that maps to the built-in complex data type), the
11456 characteristic data type is int. */
11457 if (RECORD_OR_UNION_TYPE_P (type)
11458 && !aggregate_value_p (type, NULL)
11459 && TREE_CODE (type) != COMPLEX_TYPE)
11460 return integer_type_node;
11462 /* d) If none of the above three classes is applicable, the
11463 characteristic data type is int. */
11465 return type;
11467 /* e) For Intel Xeon Phi native and offload compilation, if the
11468 resulting characteristic data type is 8-bit or 16-bit integer
11469 data type, the characteristic data type is int. */
11470 /* Well, we don't handle Xeon Phi yet. */
11473 static tree
11474 simd_clone_mangle (struct cgraph_node *node,
11475 struct cgraph_simd_clone *clone_info)
11477 char vecsize_mangle = clone_info->vecsize_mangle;
11478 char mask = clone_info->inbranch ? 'M' : 'N';
11479 unsigned int simdlen = clone_info->simdlen;
11480 unsigned int n;
11481 pretty_printer pp;
11483 gcc_assert (vecsize_mangle && simdlen);
11485 pp_string (&pp, "_ZGV");
11486 pp_character (&pp, vecsize_mangle);
11487 pp_character (&pp, mask);
11488 pp_decimal_int (&pp, simdlen);
11490 for (n = 0; n < clone_info->nargs; ++n)
11492 struct cgraph_simd_clone_arg arg = clone_info->args[n];
11494 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
11495 pp_character (&pp, 'u');
11496 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11498 gcc_assert (arg.linear_step != 0);
11499 pp_character (&pp, 'l');
11500 if (arg.linear_step > 1)
11501 pp_unsigned_wide_integer (&pp, arg.linear_step);
11502 else if (arg.linear_step < 0)
11504 pp_character (&pp, 'n');
11505 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
11506 arg.linear_step));
11509 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11511 pp_character (&pp, 's');
11512 pp_unsigned_wide_integer (&pp, arg.linear_step);
11514 else
11515 pp_character (&pp, 'v');
11516 if (arg.alignment)
11518 pp_character (&pp, 'a');
11519 pp_decimal_int (&pp, arg.alignment);
11523 pp_underscore (&pp);
11524 pp_string (&pp,
11525 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11526 const char *str = pp_formatted_text (&pp);
11528 /* If there already is a SIMD clone with the same mangled name, don't
11529 add another one. This can happen e.g. for
11530 #pragma omp declare simd
11531 #pragma omp declare simd simdlen(8)
11532 int foo (int, int);
11533 if the simdlen is assumed to be 8 for the first one, etc. */
11534 for (struct cgraph_node *clone = node->simd_clones; clone;
11535 clone = clone->simdclone->next_clone)
11536 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11537 str) == 0)
11538 return NULL_TREE;
11540 return get_identifier (str);
11543 /* Create a simd clone of OLD_NODE and return it. */
11545 static struct cgraph_node *
11546 simd_clone_create (struct cgraph_node *old_node)
11548 struct cgraph_node *new_node;
11549 if (old_node->definition)
11551 if (!old_node->has_gimple_body_p ())
11552 return NULL;
11553 old_node->get_body ();
11554 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
11555 false, NULL, NULL,
11556 "simdclone");
11558 else
11560 tree old_decl = old_node->decl;
11561 tree new_decl = copy_node (old_node->decl);
11562 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11563 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11564 SET_DECL_RTL (new_decl, NULL);
11565 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11566 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11567 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
11568 symtab->call_cgraph_insertion_hooks (new_node);
11570 if (new_node == NULL)
11571 return new_node;
11573 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11575 /* The function cgraph_function_versioning () will force the new
11576 symbol local. Undo this, and inherit external visability from
11577 the old node. */
11578 new_node->local.local = old_node->local.local;
11579 new_node->externally_visible = old_node->externally_visible;
11581 return new_node;
11584 /* Adjust the return type of the given function to its appropriate
11585 vector counterpart. Returns a simd array to be used throughout the
11586 function as a return value. */
11588 static tree
11589 simd_clone_adjust_return_type (struct cgraph_node *node)
11591 tree fndecl = node->decl;
11592 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11593 unsigned int veclen;
11594 tree t;
11596 /* Adjust the function return type. */
11597 if (orig_rettype == void_type_node)
11598 return NULL_TREE;
11599 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11600 t = TREE_TYPE (TREE_TYPE (fndecl));
11601 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
11602 veclen = node->simdclone->vecsize_int;
11603 else
11604 veclen = node->simdclone->vecsize_float;
11605 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
11606 if (veclen > node->simdclone->simdlen)
11607 veclen = node->simdclone->simdlen;
11608 if (POINTER_TYPE_P (t))
11609 t = pointer_sized_int_node;
11610 if (veclen == node->simdclone->simdlen)
11611 t = build_vector_type (t, node->simdclone->simdlen);
11612 else
11614 t = build_vector_type (t, veclen);
11615 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11617 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11618 if (!node->definition)
11619 return NULL_TREE;
11621 t = DECL_RESULT (fndecl);
11622 /* Adjust the DECL_RESULT. */
11623 gcc_assert (TREE_TYPE (t) != void_type_node);
11624 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11625 relayout_decl (t);
11627 tree atype = build_array_type_nelts (orig_rettype,
11628 node->simdclone->simdlen);
11629 if (veclen != node->simdclone->simdlen)
11630 return build1 (VIEW_CONVERT_EXPR, atype, t);
11632 /* Set up a SIMD array to use as the return value. */
11633 tree retval = create_tmp_var_raw (atype, "retval");
11634 gimple_add_tmp_var (retval);
11635 return retval;
11638 /* Each vector argument has a corresponding array to be used locally
11639 as part of the eventual loop. Create such temporary array and
11640 return it.
11642 PREFIX is the prefix to be used for the temporary.
11644 TYPE is the inner element type.
11646 SIMDLEN is the number of elements. */
11648 static tree
11649 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11651 tree atype = build_array_type_nelts (type, simdlen);
11652 tree avar = create_tmp_var_raw (atype, prefix);
11653 gimple_add_tmp_var (avar);
11654 return avar;
11657 /* Modify the function argument types to their corresponding vector
11658 counterparts if appropriate. Also, create one array for each simd
11659 argument to be used locally when using the function arguments as
11660 part of the loop.
11662 NODE is the function whose arguments are to be adjusted.
11664 Returns an adjustment vector that will be filled describing how the
11665 argument types will be adjusted. */
11667 static ipa_parm_adjustment_vec
11668 simd_clone_adjust_argument_types (struct cgraph_node *node)
11670 vec<tree> args;
11671 ipa_parm_adjustment_vec adjustments;
11673 if (node->definition)
11674 args = ipa_get_vector_of_formal_parms (node->decl);
11675 else
11676 args = simd_clone_vector_of_formal_parm_types (node->decl);
11677 adjustments.create (args.length ());
11678 unsigned i, j, veclen;
11679 struct ipa_parm_adjustment adj;
11680 for (i = 0; i < node->simdclone->nargs; ++i)
11682 memset (&adj, 0, sizeof (adj));
11683 tree parm = args[i];
11684 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11685 adj.base_index = i;
11686 adj.base = parm;
11688 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11689 node->simdclone->args[i].orig_type = parm_type;
11691 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11693 /* No adjustment necessary for scalar arguments. */
11694 adj.op = IPA_PARM_OP_COPY;
11696 else
11698 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11699 veclen = node->simdclone->vecsize_int;
11700 else
11701 veclen = node->simdclone->vecsize_float;
11702 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11703 if (veclen > node->simdclone->simdlen)
11704 veclen = node->simdclone->simdlen;
11705 adj.arg_prefix = "simd";
11706 if (POINTER_TYPE_P (parm_type))
11707 adj.type = build_vector_type (pointer_sized_int_node, veclen);
11708 else
11709 adj.type = build_vector_type (parm_type, veclen);
11710 node->simdclone->args[i].vector_type = adj.type;
11711 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11713 adjustments.safe_push (adj);
11714 if (j == veclen)
11716 memset (&adj, 0, sizeof (adj));
11717 adj.op = IPA_PARM_OP_NEW;
11718 adj.arg_prefix = "simd";
11719 adj.base_index = i;
11720 adj.type = node->simdclone->args[i].vector_type;
11724 if (node->definition)
11725 node->simdclone->args[i].simd_array
11726 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11727 parm_type, node->simdclone->simdlen);
11729 adjustments.safe_push (adj);
11732 if (node->simdclone->inbranch)
11734 tree base_type
11735 = simd_clone_compute_base_data_type (node->simdclone->origin,
11736 node->simdclone);
11738 memset (&adj, 0, sizeof (adj));
11739 adj.op = IPA_PARM_OP_NEW;
11740 adj.arg_prefix = "mask";
11742 adj.base_index = i;
11743 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11744 veclen = node->simdclone->vecsize_int;
11745 else
11746 veclen = node->simdclone->vecsize_float;
11747 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11748 if (veclen > node->simdclone->simdlen)
11749 veclen = node->simdclone->simdlen;
11750 if (POINTER_TYPE_P (base_type))
11751 adj.type = build_vector_type (pointer_sized_int_node, veclen);
11752 else
11753 adj.type = build_vector_type (base_type, veclen);
11754 adjustments.safe_push (adj);
11756 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11757 adjustments.safe_push (adj);
11759 /* We have previously allocated one extra entry for the mask. Use
11760 it and fill it. */
11761 struct cgraph_simd_clone *sc = node->simdclone;
11762 sc->nargs++;
11763 if (node->definition)
11765 sc->args[i].orig_arg
11766 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11767 sc->args[i].simd_array
11768 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11770 sc->args[i].orig_type = base_type;
11771 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11774 if (node->definition)
11775 ipa_modify_formal_parameters (node->decl, adjustments);
11776 else
11778 tree new_arg_types = NULL_TREE, new_reversed;
11779 bool last_parm_void = false;
11780 if (args.length () > 0 && args.last () == void_type_node)
11781 last_parm_void = true;
11783 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11784 j = adjustments.length ();
11785 for (i = 0; i < j; i++)
11787 struct ipa_parm_adjustment *adj = &adjustments[i];
11788 tree ptype;
11789 if (adj->op == IPA_PARM_OP_COPY)
11790 ptype = args[adj->base_index];
11791 else
11792 ptype = adj->type;
11793 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11795 new_reversed = nreverse (new_arg_types);
11796 if (last_parm_void)
11798 if (new_reversed)
11799 TREE_CHAIN (new_arg_types) = void_list_node;
11800 else
11801 new_reversed = void_list_node;
11804 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11805 TYPE_ARG_TYPES (new_type) = new_reversed;
11806 TREE_TYPE (node->decl) = new_type;
11808 adjustments.release ();
11810 args.release ();
11811 return adjustments;
11814 /* Initialize and copy the function arguments in NODE to their
11815 corresponding local simd arrays. Returns a fresh gimple_seq with
11816 the instruction sequence generated. */
11818 static gimple_seq
11819 simd_clone_init_simd_arrays (struct cgraph_node *node,
11820 ipa_parm_adjustment_vec adjustments)
11822 gimple_seq seq = NULL;
11823 unsigned i = 0, j = 0, k;
11825 for (tree arg = DECL_ARGUMENTS (node->decl);
11826 arg;
11827 arg = DECL_CHAIN (arg), i++, j++)
11829 if (adjustments[j].op == IPA_PARM_OP_COPY)
11830 continue;
11832 node->simdclone->args[i].vector_arg = arg;
11834 tree array = node->simdclone->args[i].simd_array;
11835 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11837 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11838 tree ptr = build_fold_addr_expr (array);
11839 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11840 build_int_cst (ptype, 0));
11841 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11842 gimplify_and_add (t, &seq);
11844 else
11846 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11847 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11848 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11850 tree ptr = build_fold_addr_expr (array);
11851 int elemsize;
11852 if (k)
11854 arg = DECL_CHAIN (arg);
11855 j++;
11857 elemsize
11858 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11859 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11860 build_int_cst (ptype, k * elemsize));
11861 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11862 gimplify_and_add (t, &seq);
11866 return seq;
11869 /* Callback info for ipa_simd_modify_stmt_ops below. */
11871 struct modify_stmt_info {
11872 ipa_parm_adjustment_vec adjustments;
11873 gimple stmt;
11874 /* True if the parent statement was modified by
11875 ipa_simd_modify_stmt_ops. */
11876 bool modified;
11879 /* Callback for walk_gimple_op.
11881 Adjust operands from a given statement as specified in the
11882 adjustments vector in the callback data. */
11884 static tree
11885 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11887 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11888 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11889 tree *orig_tp = tp;
11890 if (TREE_CODE (*tp) == ADDR_EXPR)
11891 tp = &TREE_OPERAND (*tp, 0);
11892 struct ipa_parm_adjustment *cand = NULL;
11893 if (TREE_CODE (*tp) == PARM_DECL)
11894 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11895 else
11897 if (TYPE_P (*tp))
11898 *walk_subtrees = 0;
11901 tree repl = NULL_TREE;
11902 if (cand)
11903 repl = unshare_expr (cand->new_decl);
11904 else
11906 if (tp != orig_tp)
11908 *walk_subtrees = 0;
11909 bool modified = info->modified;
11910 info->modified = false;
11911 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11912 if (!info->modified)
11914 info->modified = modified;
11915 return NULL_TREE;
11917 info->modified = modified;
11918 repl = *tp;
11920 else
11921 return NULL_TREE;
11924 if (tp != orig_tp)
11926 repl = build_fold_addr_expr (repl);
11927 gimple stmt;
11928 if (is_gimple_debug (info->stmt))
11930 tree vexpr = make_node (DEBUG_EXPR_DECL);
11931 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
11932 DECL_ARTIFICIAL (vexpr) = 1;
11933 TREE_TYPE (vexpr) = TREE_TYPE (repl);
11934 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
11935 repl = vexpr;
11937 else
11939 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
11940 repl = gimple_assign_lhs (stmt);
11942 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11943 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11944 *orig_tp = repl;
11946 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11948 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11949 *tp = vce;
11951 else
11952 *tp = repl;
11954 info->modified = true;
11955 return NULL_TREE;
11958 /* Traverse the function body and perform all modifications as
11959 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11960 modified such that the replacement/reduction value will now be an
11961 offset into the corresponding simd_array.
11963 This function will replace all function argument uses with their
11964 corresponding simd array elements, and ajust the return values
11965 accordingly. */
11967 static void
11968 ipa_simd_modify_function_body (struct cgraph_node *node,
11969 ipa_parm_adjustment_vec adjustments,
11970 tree retval_array, tree iter)
11972 basic_block bb;
11973 unsigned int i, j, l;
11975 /* Re-use the adjustments array, but this time use it to replace
11976 every function argument use to an offset into the corresponding
11977 simd_array. */
11978 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11980 if (!node->simdclone->args[i].vector_arg)
11981 continue;
11983 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11984 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11985 adjustments[j].new_decl
11986 = build4 (ARRAY_REF,
11987 basetype,
11988 node->simdclone->args[i].simd_array,
11989 iter,
11990 NULL_TREE, NULL_TREE);
11991 if (adjustments[j].op == IPA_PARM_OP_NONE
11992 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11993 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11996 l = adjustments.length ();
11997 for (i = 1; i < num_ssa_names; i++)
11999 tree name = ssa_name (i);
12000 if (name
12001 && SSA_NAME_VAR (name)
12002 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
12004 for (j = 0; j < l; j++)
12005 if (SSA_NAME_VAR (name) == adjustments[j].base
12006 && adjustments[j].new_decl)
12008 tree base_var;
12009 if (adjustments[j].new_ssa_base == NULL_TREE)
12011 base_var
12012 = copy_var_decl (adjustments[j].base,
12013 DECL_NAME (adjustments[j].base),
12014 TREE_TYPE (adjustments[j].base));
12015 adjustments[j].new_ssa_base = base_var;
12017 else
12018 base_var = adjustments[j].new_ssa_base;
12019 if (SSA_NAME_IS_DEFAULT_DEF (name))
12021 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12022 gimple_stmt_iterator gsi = gsi_after_labels (bb);
12023 tree new_decl = unshare_expr (adjustments[j].new_decl);
12024 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
12025 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
12026 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
12027 gimple stmt = gimple_build_assign (name, new_decl);
12028 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
12030 else
12031 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
12036 struct modify_stmt_info info;
12037 info.adjustments = adjustments;
12039 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
12041 gimple_stmt_iterator gsi;
12043 gsi = gsi_start_bb (bb);
12044 while (!gsi_end_p (gsi))
12046 gimple stmt = gsi_stmt (gsi);
12047 info.stmt = stmt;
12048 struct walk_stmt_info wi;
12050 memset (&wi, 0, sizeof (wi));
12051 info.modified = false;
12052 wi.info = &info;
12053 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
12055 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
12057 tree retval = gimple_return_retval (return_stmt);
12058 if (!retval)
12060 gsi_remove (&gsi, true);
12061 continue;
12064 /* Replace `return foo' with `retval_array[iter] = foo'. */
12065 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
12066 retval_array, iter, NULL, NULL);
12067 stmt = gimple_build_assign (ref, retval);
12068 gsi_replace (&gsi, stmt, true);
12069 info.modified = true;
12072 if (info.modified)
12074 update_stmt (stmt);
12075 if (maybe_clean_eh_stmt (stmt))
12076 gimple_purge_dead_eh_edges (gimple_bb (stmt));
12078 gsi_next (&gsi);
12083 /* Adjust the argument types in NODE to their appropriate vector
12084 counterparts. */
12086 static void
12087 simd_clone_adjust (struct cgraph_node *node)
12089 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
12091 targetm.simd_clone.adjust (node);
12093 tree retval = simd_clone_adjust_return_type (node);
12094 ipa_parm_adjustment_vec adjustments
12095 = simd_clone_adjust_argument_types (node);
12097 push_gimplify_context ();
12099 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
12101 /* Adjust all uses of vector arguments accordingly. Adjust all
12102 return values accordingly. */
12103 tree iter = create_tmp_var (unsigned_type_node, "iter");
12104 tree iter1 = make_ssa_name (iter);
12105 tree iter2 = make_ssa_name (iter);
12106 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
12108 /* Initialize the iteration variable. */
12109 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12110 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
12111 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
12112 /* Insert the SIMD array and iv initialization at function
12113 entry. */
12114 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
12116 pop_gimplify_context (NULL);
12118 /* Create a new BB right before the original exit BB, to hold the
12119 iteration increment and the condition/branch. */
12120 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
12121 basic_block incr_bb = create_empty_bb (orig_exit);
12122 add_bb_to_loop (incr_bb, body_bb->loop_father);
12123 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
12124 flag. Set it now to be a FALLTHRU_EDGE. */
12125 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
12126 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
12127 for (unsigned i = 0;
12128 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
12130 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
12131 redirect_edge_succ (e, incr_bb);
12133 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
12134 e->probability = REG_BR_PROB_BASE;
12135 gsi = gsi_last_bb (incr_bb);
12136 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
12137 build_int_cst (unsigned_type_node, 1));
12138 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12140 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12141 struct loop *loop = alloc_loop ();
12142 cfun->has_force_vectorize_loops = true;
12143 loop->safelen = node->simdclone->simdlen;
12144 loop->force_vectorize = true;
12145 loop->header = body_bb;
12147 /* Branch around the body if the mask applies. */
12148 if (node->simdclone->inbranch)
12150 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
12151 tree mask_array
12152 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
12153 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
12154 tree aref = build4 (ARRAY_REF,
12155 TREE_TYPE (TREE_TYPE (mask_array)),
12156 mask_array, iter1,
12157 NULL, NULL);
12158 g = gimple_build_assign (mask, aref);
12159 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12160 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
12161 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
12163 aref = build1 (VIEW_CONVERT_EXPR,
12164 build_nonstandard_integer_type (bitsize, 0), mask);
12165 mask = make_ssa_name (TREE_TYPE (aref));
12166 g = gimple_build_assign (mask, aref);
12167 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12170 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
12171 NULL, NULL);
12172 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12173 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
12174 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
12177 /* Generate the condition. */
12178 g = gimple_build_cond (LT_EXPR,
12179 iter2,
12180 build_int_cst (unsigned_type_node,
12181 node->simdclone->simdlen),
12182 NULL, NULL);
12183 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12184 e = split_block (incr_bb, gsi_stmt (gsi));
12185 basic_block latch_bb = e->dest;
12186 basic_block new_exit_bb;
12187 new_exit_bb = split_block (latch_bb, NULL)->dest;
12188 loop->latch = latch_bb;
12190 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
12192 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
12193 /* The successor of incr_bb is already pointing to latch_bb; just
12194 change the flags.
12195 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12196 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
12198 gphi *phi = create_phi_node (iter1, body_bb);
12199 edge preheader_edge = find_edge (entry_bb, body_bb);
12200 edge latch_edge = single_succ_edge (latch_bb);
12201 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
12202 UNKNOWN_LOCATION);
12203 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12205 /* Generate the new return. */
12206 gsi = gsi_last_bb (new_exit_bb);
12207 if (retval
12208 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
12209 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
12210 retval = TREE_OPERAND (retval, 0);
12211 else if (retval)
12213 retval = build1 (VIEW_CONVERT_EXPR,
12214 TREE_TYPE (TREE_TYPE (node->decl)),
12215 retval);
12216 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
12217 false, GSI_CONTINUE_LINKING);
12219 g = gimple_build_return (retval);
12220 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12222 /* Handle aligned clauses by replacing default defs of the aligned
12223 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12224 lhs. Handle linear by adding PHIs. */
12225 for (unsigned i = 0; i < node->simdclone->nargs; i++)
12226 if (node->simdclone->args[i].alignment
12227 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
12228 && (node->simdclone->args[i].alignment
12229 & (node->simdclone->args[i].alignment - 1)) == 0
12230 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
12231 == POINTER_TYPE)
12233 unsigned int alignment = node->simdclone->args[i].alignment;
12234 tree orig_arg = node->simdclone->args[i].orig_arg;
12235 tree def = ssa_default_def (cfun, orig_arg);
12236 if (def && !has_zero_uses (def))
12238 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
12239 gimple_seq seq = NULL;
12240 bool need_cvt = false;
12241 gcall *call
12242 = gimple_build_call (fn, 2, def, size_int (alignment));
12243 g = call;
12244 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
12245 ptr_type_node))
12246 need_cvt = true;
12247 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
12248 gimple_call_set_lhs (g, t);
12249 gimple_seq_add_stmt_without_update (&seq, g);
12250 if (need_cvt)
12252 t = make_ssa_name (orig_arg);
12253 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
12254 gimple_seq_add_stmt_without_update (&seq, g);
12256 gsi_insert_seq_on_edge_immediate
12257 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
12259 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12260 int freq = compute_call_stmt_bb_frequency (current_function_decl,
12261 entry_bb);
12262 node->create_edge (cgraph_node::get_create (fn),
12263 call, entry_bb->count, freq);
12265 imm_use_iterator iter;
12266 use_operand_p use_p;
12267 gimple use_stmt;
12268 tree repl = gimple_get_lhs (g);
12269 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12270 if (is_gimple_debug (use_stmt) || use_stmt == call)
12271 continue;
12272 else
12273 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12274 SET_USE (use_p, repl);
12277 else if (node->simdclone->args[i].arg_type
12278 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12280 tree orig_arg = node->simdclone->args[i].orig_arg;
12281 tree def = ssa_default_def (cfun, orig_arg);
12282 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12283 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
12284 if (def && !has_zero_uses (def))
12286 iter1 = make_ssa_name (orig_arg);
12287 iter2 = make_ssa_name (orig_arg);
12288 phi = create_phi_node (iter1, body_bb);
12289 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
12290 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12291 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12292 ? PLUS_EXPR : POINTER_PLUS_EXPR;
12293 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12294 ? TREE_TYPE (orig_arg) : sizetype;
12295 tree addcst
12296 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
12297 g = gimple_build_assign (iter2, code, iter1, addcst);
12298 gsi = gsi_last_bb (incr_bb);
12299 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12301 imm_use_iterator iter;
12302 use_operand_p use_p;
12303 gimple use_stmt;
12304 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12305 if (use_stmt == phi)
12306 continue;
12307 else
12308 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12309 SET_USE (use_p, iter1);
12313 calculate_dominance_info (CDI_DOMINATORS);
12314 add_loop (loop, loop->header->loop_father);
12315 update_ssa (TODO_update_ssa);
12317 pop_cfun ();
12320 /* If the function in NODE is tagged as an elemental SIMD function,
12321 create the appropriate SIMD clones. */
12323 static void
12324 expand_simd_clones (struct cgraph_node *node)
12326 tree attr = lookup_attribute ("omp declare simd",
12327 DECL_ATTRIBUTES (node->decl));
12328 if (attr == NULL_TREE
12329 || node->global.inlined_to
12330 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
12331 return;
12333 /* Ignore
12334 #pragma omp declare simd
12335 extern int foo ();
12336 in C, there we don't know the argument types at all. */
12337 if (!node->definition
12338 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
12339 return;
12343 /* Start with parsing the "omp declare simd" attribute(s). */
12344 bool inbranch_clause_specified;
12345 struct cgraph_simd_clone *clone_info
12346 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
12347 &inbranch_clause_specified);
12348 if (clone_info == NULL)
12349 continue;
12351 int orig_simdlen = clone_info->simdlen;
12352 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
12353 /* The target can return 0 (no simd clones should be created),
12354 1 (just one ISA of simd clones should be created) or higher
12355 count of ISA variants. In that case, clone_info is initialized
12356 for the first ISA variant. */
12357 int count
12358 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
12359 base_type, 0);
12360 if (count == 0)
12361 continue;
12363 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12364 also create one inbranch and one !inbranch clone of it. */
12365 for (int i = 0; i < count * 2; i++)
12367 struct cgraph_simd_clone *clone = clone_info;
12368 if (inbranch_clause_specified && (i & 1) != 0)
12369 continue;
12371 if (i != 0)
12373 clone = simd_clone_struct_alloc (clone_info->nargs
12374 + ((i & 1) != 0));
12375 simd_clone_struct_copy (clone, clone_info);
12376 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12377 and simd_clone_adjust_argument_types did to the first
12378 clone's info. */
12379 clone->nargs -= clone_info->inbranch;
12380 clone->simdlen = orig_simdlen;
12381 /* And call the target hook again to get the right ISA. */
12382 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
12383 base_type,
12384 i / 2);
12385 if ((i & 1) != 0)
12386 clone->inbranch = 1;
12389 /* simd_clone_mangle might fail if such a clone has been created
12390 already. */
12391 tree id = simd_clone_mangle (node, clone);
12392 if (id == NULL_TREE)
12393 continue;
12395 /* Only when we are sure we want to create the clone actually
12396 clone the function (or definitions) or create another
12397 extern FUNCTION_DECL (for prototypes without definitions). */
12398 struct cgraph_node *n = simd_clone_create (node);
12399 if (n == NULL)
12400 continue;
12402 n->simdclone = clone;
12403 clone->origin = node;
12404 clone->next_clone = NULL;
12405 if (node->simd_clones == NULL)
12407 clone->prev_clone = n;
12408 node->simd_clones = n;
12410 else
12412 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
12413 clone->prev_clone->simdclone->next_clone = n;
12414 node->simd_clones->simdclone->prev_clone = n;
12416 symtab->change_decl_assembler_name (n->decl, id);
12417 /* And finally adjust the return type, parameters and for
12418 definitions also function body. */
12419 if (node->definition)
12420 simd_clone_adjust (n);
12421 else
12423 simd_clone_adjust_return_type (n);
12424 simd_clone_adjust_argument_types (n);
12428 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
12431 /* Entry point for IPA simd clone creation pass. */
12433 static unsigned int
12434 ipa_omp_simd_clone (void)
12436 struct cgraph_node *node;
12437 FOR_EACH_FUNCTION (node)
12438 expand_simd_clones (node);
12439 return 0;
12442 namespace {
12444 const pass_data pass_data_omp_simd_clone =
12446 SIMPLE_IPA_PASS, /* type */
12447 "simdclone", /* name */
12448 OPTGROUP_NONE, /* optinfo_flags */
12449 TV_NONE, /* tv_id */
12450 ( PROP_ssa | PROP_cfg ), /* properties_required */
12451 0, /* properties_provided */
12452 0, /* properties_destroyed */
12453 0, /* todo_flags_start */
12454 0, /* todo_flags_finish */
12457 class pass_omp_simd_clone : public simple_ipa_opt_pass
12459 public:
12460 pass_omp_simd_clone(gcc::context *ctxt)
12461 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
12464 /* opt_pass methods: */
12465 virtual bool gate (function *);
12466 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
12469 bool
12470 pass_omp_simd_clone::gate (function *)
12472 return ((flag_openmp || flag_openmp_simd
12473 || flag_cilkplus
12474 || (in_lto_p && !flag_wpa))
12475 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
12478 } // anon namespace
12480 simple_ipa_opt_pass *
12481 make_pass_omp_simd_clone (gcc::context *ctxt)
12483 return new pass_omp_simd_clone (ctxt);
12486 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
12487 adds their addresses and sizes to constructor-vector V_CTOR. */
12488 static void
12489 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
12490 vec<constructor_elt, va_gc> *v_ctor)
12492 unsigned len = vec_safe_length (v_decls);
12493 for (unsigned i = 0; i < len; i++)
12495 tree it = (*v_decls)[i];
12496 bool is_function = TREE_CODE (it) != VAR_DECL;
12498 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
12499 if (!is_function)
12500 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
12501 fold_convert (const_ptr_type_node,
12502 DECL_SIZE_UNIT (it)));
12506 /* Create new symbols containing (address, size) pairs for global variables,
12507 marked with "omp declare target" attribute, as well as addresses for the
12508 functions, which are outlined target regions. */
12509 void
12510 omp_finish_file (void)
12512 unsigned num_funcs = vec_safe_length (offload_funcs);
12513 unsigned num_vars = vec_safe_length (offload_vars);
12515 if (num_funcs == 0 && num_vars == 0)
12516 return;
12518 if (targetm_common.have_named_sections)
12520 vec<constructor_elt, va_gc> *v_f, *v_v;
12521 vec_alloc (v_f, num_funcs);
12522 vec_alloc (v_v, num_vars * 2);
12524 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
12525 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
12527 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
12528 num_vars * 2);
12529 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
12530 num_funcs);
12531 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
12532 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
12533 tree ctor_v = build_constructor (vars_decl_type, v_v);
12534 tree ctor_f = build_constructor (funcs_decl_type, v_f);
12535 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
12536 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
12537 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
12538 get_identifier (".offload_func_table"),
12539 funcs_decl_type);
12540 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
12541 get_identifier (".offload_var_table"),
12542 vars_decl_type);
12543 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
12544 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
12545 otherwise a joint table in a binary will contain padding between
12546 tables from multiple object files. */
12547 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
12548 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
12549 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
12550 DECL_INITIAL (funcs_decl) = ctor_f;
12551 DECL_INITIAL (vars_decl) = ctor_v;
12552 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
12553 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
12555 varpool_node::finalize_decl (vars_decl);
12556 varpool_node::finalize_decl (funcs_decl);
12558 else
12560 for (unsigned i = 0; i < num_funcs; i++)
12562 tree it = (*offload_funcs)[i];
12563 targetm.record_offload_symbol (it);
12565 for (unsigned i = 0; i < num_vars; i++)
12567 tree it = (*offload_vars)[i];
12568 targetm.record_offload_symbol (it);
12573 #include "gt-omp-low.h"