svn merge -r 219682:220584 svn+ssh://gcc.gnu.org/svn/gcc/trunk
[official-gcc.git] / gcc / omp-low.c
blobc686efe82fbc944f5d1cdc934721f219b38beae4
1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "hash-set.h"
30 #include "machmode.h"
31 #include "vec.h"
32 #include "double-int.h"
33 #include "input.h"
34 #include "alias.h"
35 #include "symtab.h"
36 #include "wide-int.h"
37 #include "inchash.h"
38 #include "tree.h"
39 #include "fold-const.h"
40 #include "stringpool.h"
41 #include "stor-layout.h"
42 #include "rtl.h"
43 #include "predict.h"
44 #include "hard-reg-set.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 "hashtab.h"
75 #include "flags.h"
76 #include "statistics.h"
77 #include "real.h"
78 #include "fixed-value.h"
79 #include "insn-config.h"
80 #include "expmed.h"
81 #include "dojump.h"
82 #include "explow.h"
83 #include "calls.h"
84 #include "emit-rtl.h"
85 #include "varasm.h"
86 #include "stmt.h"
87 #include "expr.h"
88 #include "tree-dfa.h"
89 #include "tree-ssa.h"
90 #include "tree-pass.h"
91 #include "except.h"
92 #include "splay-tree.h"
93 #include "insn-codes.h"
94 #include "optabs.h"
95 #include "cfgloop.h"
96 #include "target.h"
97 #include "common/common-target.h"
98 #include "omp-low.h"
99 #include "gimple-low.h"
100 #include "tree-cfgcleanup.h"
101 #include "pretty-print.h"
102 #include "alloc-pool.h"
103 #include "symbol-summary.h"
104 #include "ipa-prop.h"
105 #include "tree-nested.h"
106 #include "tree-eh.h"
107 #include "cilk.h"
108 #include "context.h"
109 #include "lto-section-names.h"
110 #include "gomp-constants.h"
113 /* Lowering of OMP parallel and workshare constructs proceeds in two
114 phases. The first phase scans the function looking for OMP statements
115 and then for variables that must be replaced to satisfy data sharing
116 clauses. The second phase expands code for the constructs, as well as
117 re-gimplifying things when variables have been replaced with complex
118 expressions.
120 Final code generation is done by pass_expand_omp. The flowgraph is
121 scanned for regions which are then moved to a new
122 function, to be invoked by the thread library, or offloaded. */
124 /* OMP region information. Every parallel and workshare
125 directive is enclosed between two markers, the OMP_* directive
126 and a corresponding OMP_RETURN statement. */
128 struct omp_region
130 /* The enclosing region. */
131 struct omp_region *outer;
133 /* First child region. */
134 struct omp_region *inner;
136 /* Next peer region. */
137 struct omp_region *next;
139 /* Block containing the omp directive as its last stmt. */
140 basic_block entry;
142 /* Block containing the OMP_RETURN as its last stmt. */
143 basic_block exit;
145 /* Block containing the OMP_CONTINUE as its last stmt. */
146 basic_block cont;
148 /* If this is a combined parallel+workshare region, this is a list
149 of additional arguments needed by the combined parallel+workshare
150 library call. */
151 vec<tree, va_gc> *ws_args;
153 /* The code for the omp directive of this region. */
154 enum gimple_code type;
156 /* Schedule kind, only used for OMP_FOR type regions. */
157 enum omp_clause_schedule_kind sched_kind;
159 /* True if this is a combined parallel+workshare region. */
160 bool is_combined_parallel;
163 /* Levels of parallelism as defined by OpenACC. Increasing numbers
164 correspond to deeper loop nesting levels. */
165 #define MASK_GANG 1
166 #define MASK_WORKER 2
167 #define MASK_VECTOR 4
169 /* Context structure. Used to store information about each parallel
170 directive in the code. */
172 typedef struct omp_context
174 /* This field must be at the beginning, as we do "inheritance": Some
175 callback functions for tree-inline.c (e.g., omp_copy_decl)
176 receive a copy_body_data pointer that is up-casted to an
177 omp_context pointer. */
178 copy_body_data cb;
180 /* The tree of contexts corresponding to the encountered constructs. */
181 struct omp_context *outer;
182 gimple stmt;
184 /* Map variables to fields in a structure that allows communication
185 between sending and receiving threads. */
186 splay_tree field_map;
187 tree record_type;
188 tree sender_decl;
189 tree receiver_decl;
191 /* These are used just by task contexts, if task firstprivate fn is
192 needed. srecord_type is used to communicate from the thread
193 that encountered the task construct to task firstprivate fn,
194 record_type is allocated by GOMP_task, initialized by task firstprivate
195 fn and passed to the task body fn. */
196 splay_tree sfield_map;
197 tree srecord_type;
199 /* A chain of variables to add to the top-level block surrounding the
200 construct. In the case of a parallel, this is in the child function. */
201 tree block_vars;
203 /* A map of reduction pointer variables. For accelerators, each
204 reduction variable is replaced with an array. Each thread, in turn,
205 is assigned to a slot on that array. */
206 splay_tree reduction_map;
208 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
209 barriers should jump to during omplower pass. */
210 tree cancel_label;
212 /* What to do with variables with implicitly determined sharing
213 attributes. */
214 enum omp_clause_default_kind default_kind;
216 /* Nesting depth of this context. Used to beautify error messages re
217 invalid gotos. The outermost ctx is depth 1, with depth 0 being
218 reserved for the main body of the function. */
219 int depth;
221 /* True if this parallel directive is nested within another. */
222 bool is_nested;
224 /* True if this construct can be cancelled. */
225 bool cancellable;
227 /* For OpenACC loops, a mask of gang, worker and vector used at
228 levels below this one. */
229 int gwv_below;
230 /* For OpenACC loops, a mask of gang, worker and vector used at
231 this level and above. For parallel and kernels clauses, a mask
232 indicating which of num_gangs/num_workers/num_vectors was used. */
233 int gwv_this;
234 } omp_context;
236 /* A structure holding the elements of:
237 for (V = N1; V cond N2; V += STEP) [...] */
239 struct omp_for_data_loop
241 tree v, n1, n2, step;
242 enum tree_code cond_code;
245 /* A structure describing the main elements of a parallel loop. */
247 struct omp_for_data
249 struct omp_for_data_loop loop;
250 tree chunk_size;
251 gomp_for *for_stmt;
252 tree pre, iter_type;
253 int collapse;
254 bool have_nowait, have_ordered;
255 enum omp_clause_schedule_kind sched_kind;
256 struct omp_for_data_loop *loops;
260 static splay_tree all_contexts;
261 static int taskreg_nesting_level;
262 static int target_nesting_level;
263 static struct omp_region *root_omp_region;
264 static bitmap task_shared_vars;
265 static vec<omp_context *> taskreg_contexts;
267 static void scan_omp (gimple_seq *, omp_context *);
268 static tree scan_omp_1_op (tree *, int *, void *);
270 #define WALK_SUBSTMTS \
271 case GIMPLE_BIND: \
272 case GIMPLE_TRY: \
273 case GIMPLE_CATCH: \
274 case GIMPLE_EH_FILTER: \
275 case GIMPLE_TRANSACTION: \
276 /* The sub-statements for these should be walked. */ \
277 *handled_ops_p = false; \
278 break;
280 /* Helper function to get the name of the array containing the partial
281 reductions for OpenACC reductions. */
282 static const char *
283 oacc_get_reduction_array_id (tree node)
285 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
286 int len = strlen ("OACC") + strlen (id);
287 char *temp_name = XALLOCAVEC (char, len + 1);
288 snprintf (temp_name, len + 1, "OACC%s", id);
289 return IDENTIFIER_POINTER (get_identifier (temp_name));
292 /* Determine the number of threads OpenACC threads used to determine the
293 size of the array of partial reductions. Currently, this is num_gangs
294 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
295 because it is independed of the device used. */
297 static tree
298 oacc_max_threads (omp_context *ctx)
300 tree nthreads, vector_length, gangs, clauses;
302 gangs = fold_convert (sizetype, integer_one_node);
303 vector_length = gangs;
305 /* The reduction clause may be nested inside a loop directive.
306 Scan for the innermost vector_length clause. */
307 for (omp_context *oc = ctx; oc; oc = oc->outer)
309 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
310 || (gimple_omp_target_kind (oc->stmt)
311 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
312 continue;
314 clauses = gimple_omp_target_clauses (oc->stmt);
316 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
317 if (vector_length)
318 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
319 sizetype,
320 OMP_CLAUSE_VECTOR_LENGTH_EXPR
321 (vector_length));
322 else
323 vector_length = fold_convert (sizetype, integer_one_node);
325 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
326 if (gangs)
327 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
328 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
329 else
330 gangs = fold_convert (sizetype, integer_one_node);
332 break;
335 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
337 return nthreads;
340 /* Holds offload tables with decls. */
341 vec<tree, va_gc> *offload_funcs, *offload_vars;
343 /* Convenience function for calling scan_omp_1_op on tree operands. */
345 static inline tree
346 scan_omp_op (tree *tp, omp_context *ctx)
348 struct walk_stmt_info wi;
350 memset (&wi, 0, sizeof (wi));
351 wi.info = ctx;
352 wi.want_locations = true;
354 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
357 static void lower_omp (gimple_seq *, omp_context *);
358 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
359 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
361 /* Find an OMP clause of type KIND within CLAUSES. */
363 tree
364 find_omp_clause (tree clauses, enum omp_clause_code kind)
366 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
367 if (OMP_CLAUSE_CODE (clauses) == kind)
368 return clauses;
370 return NULL_TREE;
373 /* Return true if CTX is for an omp parallel. */
375 static inline bool
376 is_parallel_ctx (omp_context *ctx)
378 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
382 /* Return true if CTX is for an omp task. */
384 static inline bool
385 is_task_ctx (omp_context *ctx)
387 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
391 /* Return true if CTX is for an omp parallel or omp task. */
393 static inline bool
394 is_taskreg_ctx (omp_context *ctx)
396 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
397 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
401 /* Return true if REGION is a combined parallel+workshare region. */
403 static inline bool
404 is_combined_parallel (struct omp_region *region)
406 return region->is_combined_parallel;
410 /* Extract the header elements of parallel loop FOR_STMT and store
411 them into *FD. */
413 static void
414 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
415 struct omp_for_data_loop *loops)
417 tree t, var, *collapse_iter, *collapse_count;
418 tree count = NULL_TREE, iter_type = long_integer_type_node;
419 struct omp_for_data_loop *loop;
420 int i;
421 struct omp_for_data_loop dummy_loop;
422 location_t loc = gimple_location (for_stmt);
423 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
424 bool distribute = gimple_omp_for_kind (for_stmt)
425 == GF_OMP_FOR_KIND_DISTRIBUTE;
427 fd->for_stmt = for_stmt;
428 fd->pre = NULL;
429 fd->collapse = gimple_omp_for_collapse (for_stmt);
430 if (fd->collapse > 1)
431 fd->loops = loops;
432 else
433 fd->loops = &fd->loop;
435 fd->have_nowait = distribute || simd;
436 fd->have_ordered = false;
437 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
438 fd->chunk_size = NULL_TREE;
439 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
440 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
441 collapse_iter = NULL;
442 collapse_count = NULL;
444 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
445 switch (OMP_CLAUSE_CODE (t))
447 case OMP_CLAUSE_NOWAIT:
448 fd->have_nowait = true;
449 break;
450 case OMP_CLAUSE_ORDERED:
451 fd->have_ordered = true;
452 break;
453 case OMP_CLAUSE_SCHEDULE:
454 gcc_assert (!distribute);
455 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
456 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
457 break;
458 case OMP_CLAUSE_DIST_SCHEDULE:
459 gcc_assert (distribute);
460 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
461 break;
462 case OMP_CLAUSE_COLLAPSE:
463 if (fd->collapse > 1)
465 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
466 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
468 break;
469 default:
470 break;
473 /* FIXME: for now map schedule(auto) to schedule(static).
474 There should be analysis to determine whether all iterations
475 are approximately the same amount of work (then schedule(static)
476 is best) or if it varies (then schedule(dynamic,N) is better). */
477 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
479 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
480 gcc_assert (fd->chunk_size == NULL);
482 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
483 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
484 gcc_assert (fd->chunk_size == NULL);
485 else if (fd->chunk_size == NULL)
487 /* We only need to compute a default chunk size for ordered
488 static loops and dynamic loops. */
489 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
490 || fd->have_ordered)
491 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
492 ? integer_zero_node : integer_one_node;
495 for (i = 0; i < fd->collapse; i++)
497 if (fd->collapse == 1)
498 loop = &fd->loop;
499 else if (loops != NULL)
500 loop = loops + i;
501 else
502 loop = &dummy_loop;
504 loop->v = gimple_omp_for_index (for_stmt, i);
505 gcc_assert (SSA_VAR_P (loop->v));
506 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
507 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
508 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
509 loop->n1 = gimple_omp_for_initial (for_stmt, i);
511 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
512 loop->n2 = gimple_omp_for_final (for_stmt, i);
513 switch (loop->cond_code)
515 case LT_EXPR:
516 case GT_EXPR:
517 break;
518 case NE_EXPR:
519 gcc_assert (gimple_omp_for_kind (for_stmt)
520 == GF_OMP_FOR_KIND_CILKSIMD
521 || (gimple_omp_for_kind (for_stmt)
522 == GF_OMP_FOR_KIND_CILKFOR));
523 break;
524 case LE_EXPR:
525 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
526 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
527 else
528 loop->n2 = fold_build2_loc (loc,
529 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
530 build_int_cst (TREE_TYPE (loop->n2), 1));
531 loop->cond_code = LT_EXPR;
532 break;
533 case GE_EXPR:
534 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
535 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
536 else
537 loop->n2 = fold_build2_loc (loc,
538 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
539 build_int_cst (TREE_TYPE (loop->n2), 1));
540 loop->cond_code = GT_EXPR;
541 break;
542 default:
543 gcc_unreachable ();
546 t = gimple_omp_for_incr (for_stmt, i);
547 gcc_assert (TREE_OPERAND (t, 0) == var);
548 switch (TREE_CODE (t))
550 case PLUS_EXPR:
551 loop->step = TREE_OPERAND (t, 1);
552 break;
553 case POINTER_PLUS_EXPR:
554 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
555 break;
556 case MINUS_EXPR:
557 loop->step = TREE_OPERAND (t, 1);
558 loop->step = fold_build1_loc (loc,
559 NEGATE_EXPR, TREE_TYPE (loop->step),
560 loop->step);
561 break;
562 default:
563 gcc_unreachable ();
566 if (simd
567 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
568 && !fd->have_ordered))
570 if (fd->collapse == 1)
571 iter_type = TREE_TYPE (loop->v);
572 else if (i == 0
573 || TYPE_PRECISION (iter_type)
574 < TYPE_PRECISION (TREE_TYPE (loop->v)))
575 iter_type
576 = build_nonstandard_integer_type
577 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
579 else if (iter_type != long_long_unsigned_type_node)
581 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
582 iter_type = long_long_unsigned_type_node;
583 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
584 && TYPE_PRECISION (TREE_TYPE (loop->v))
585 >= TYPE_PRECISION (iter_type))
587 tree n;
589 if (loop->cond_code == LT_EXPR)
590 n = fold_build2_loc (loc,
591 PLUS_EXPR, TREE_TYPE (loop->v),
592 loop->n2, loop->step);
593 else
594 n = loop->n1;
595 if (TREE_CODE (n) != INTEGER_CST
596 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
597 iter_type = long_long_unsigned_type_node;
599 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
600 > TYPE_PRECISION (iter_type))
602 tree n1, n2;
604 if (loop->cond_code == LT_EXPR)
606 n1 = loop->n1;
607 n2 = fold_build2_loc (loc,
608 PLUS_EXPR, TREE_TYPE (loop->v),
609 loop->n2, loop->step);
611 else
613 n1 = fold_build2_loc (loc,
614 MINUS_EXPR, TREE_TYPE (loop->v),
615 loop->n2, loop->step);
616 n2 = loop->n1;
618 if (TREE_CODE (n1) != INTEGER_CST
619 || TREE_CODE (n2) != INTEGER_CST
620 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
621 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
622 iter_type = long_long_unsigned_type_node;
626 if (collapse_count && *collapse_count == NULL)
628 t = fold_binary (loop->cond_code, boolean_type_node,
629 fold_convert (TREE_TYPE (loop->v), loop->n1),
630 fold_convert (TREE_TYPE (loop->v), loop->n2));
631 if (t && integer_zerop (t))
632 count = build_zero_cst (long_long_unsigned_type_node);
633 else if ((i == 0 || count != NULL_TREE)
634 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
635 && TREE_CONSTANT (loop->n1)
636 && TREE_CONSTANT (loop->n2)
637 && TREE_CODE (loop->step) == INTEGER_CST)
639 tree itype = TREE_TYPE (loop->v);
641 if (POINTER_TYPE_P (itype))
642 itype = signed_type_for (itype);
643 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
644 t = fold_build2_loc (loc,
645 PLUS_EXPR, itype,
646 fold_convert_loc (loc, itype, loop->step), t);
647 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
648 fold_convert_loc (loc, itype, loop->n2));
649 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
650 fold_convert_loc (loc, itype, loop->n1));
651 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
652 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
653 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
654 fold_build1_loc (loc, NEGATE_EXPR, itype,
655 fold_convert_loc (loc, itype,
656 loop->step)));
657 else
658 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
659 fold_convert_loc (loc, itype, loop->step));
660 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
661 if (count != NULL_TREE)
662 count = fold_build2_loc (loc,
663 MULT_EXPR, long_long_unsigned_type_node,
664 count, t);
665 else
666 count = t;
667 if (TREE_CODE (count) != INTEGER_CST)
668 count = NULL_TREE;
670 else if (count && !integer_zerop (count))
671 count = NULL_TREE;
675 if (count
676 && !simd
677 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
678 || fd->have_ordered))
680 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
681 iter_type = long_long_unsigned_type_node;
682 else
683 iter_type = long_integer_type_node;
685 else if (collapse_iter && *collapse_iter != NULL)
686 iter_type = TREE_TYPE (*collapse_iter);
687 fd->iter_type = iter_type;
688 if (collapse_iter && *collapse_iter == NULL)
689 *collapse_iter = create_tmp_var (iter_type, ".iter");
690 if (collapse_count && *collapse_count == NULL)
692 if (count)
693 *collapse_count = fold_convert_loc (loc, iter_type, count);
694 else
695 *collapse_count = create_tmp_var (iter_type, ".count");
698 if (fd->collapse > 1)
700 fd->loop.v = *collapse_iter;
701 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
702 fd->loop.n2 = *collapse_count;
703 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
704 fd->loop.cond_code = LT_EXPR;
707 /* For OpenACC loops, force a chunk size of one, as this avoids the default
708 scheduling where several subsequent iterations are being executed by the
709 same thread. */
710 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
712 gcc_assert (fd->chunk_size == NULL_TREE);
713 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
718 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
719 is the immediate dominator of PAR_ENTRY_BB, return true if there
720 are no data dependencies that would prevent expanding the parallel
721 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
723 When expanding a combined parallel+workshare region, the call to
724 the child function may need additional arguments in the case of
725 GIMPLE_OMP_FOR regions. In some cases, these arguments are
726 computed out of variables passed in from the parent to the child
727 via 'struct .omp_data_s'. For instance:
729 #pragma omp parallel for schedule (guided, i * 4)
730 for (j ...)
732 Is lowered into:
734 # BLOCK 2 (PAR_ENTRY_BB)
735 .omp_data_o.i = i;
736 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
738 # BLOCK 3 (WS_ENTRY_BB)
739 .omp_data_i = &.omp_data_o;
740 D.1667 = .omp_data_i->i;
741 D.1598 = D.1667 * 4;
742 #pragma omp for schedule (guided, D.1598)
744 When we outline the parallel region, the call to the child function
745 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
746 that value is computed *after* the call site. So, in principle we
747 cannot do the transformation.
749 To see whether the code in WS_ENTRY_BB blocks the combined
750 parallel+workshare call, we collect all the variables used in the
751 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
752 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
753 call.
755 FIXME. If we had the SSA form built at this point, we could merely
756 hoist the code in block 3 into block 2 and be done with it. But at
757 this point we don't have dataflow information and though we could
758 hack something up here, it is really not worth the aggravation. */
760 static bool
761 workshare_safe_to_combine_p (basic_block ws_entry_bb)
763 struct omp_for_data fd;
764 gimple ws_stmt = last_stmt (ws_entry_bb);
766 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
767 return true;
769 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
771 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
773 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
774 return false;
775 if (fd.iter_type != long_integer_type_node)
776 return false;
778 /* FIXME. We give up too easily here. If any of these arguments
779 are not constants, they will likely involve variables that have
780 been mapped into fields of .omp_data_s for sharing with the child
781 function. With appropriate data flow, it would be possible to
782 see through this. */
783 if (!is_gimple_min_invariant (fd.loop.n1)
784 || !is_gimple_min_invariant (fd.loop.n2)
785 || !is_gimple_min_invariant (fd.loop.step)
786 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
787 return false;
789 return true;
793 /* Collect additional arguments needed to emit a combined
794 parallel+workshare call. WS_STMT is the workshare directive being
795 expanded. */
797 static vec<tree, va_gc> *
798 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
800 tree t;
801 location_t loc = gimple_location (ws_stmt);
802 vec<tree, va_gc> *ws_args;
804 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
806 struct omp_for_data fd;
807 tree n1, n2;
809 extract_omp_for_data (for_stmt, &fd, NULL);
810 n1 = fd.loop.n1;
811 n2 = fd.loop.n2;
813 if (gimple_omp_for_combined_into_p (for_stmt))
815 tree innerc
816 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
817 OMP_CLAUSE__LOOPTEMP_);
818 gcc_assert (innerc);
819 n1 = OMP_CLAUSE_DECL (innerc);
820 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
821 OMP_CLAUSE__LOOPTEMP_);
822 gcc_assert (innerc);
823 n2 = OMP_CLAUSE_DECL (innerc);
826 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
828 t = fold_convert_loc (loc, long_integer_type_node, n1);
829 ws_args->quick_push (t);
831 t = fold_convert_loc (loc, long_integer_type_node, n2);
832 ws_args->quick_push (t);
834 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
835 ws_args->quick_push (t);
837 if (fd.chunk_size)
839 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
840 ws_args->quick_push (t);
843 return ws_args;
845 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
847 /* Number of sections is equal to the number of edges from the
848 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
849 the exit of the sections region. */
850 basic_block bb = single_succ (gimple_bb (ws_stmt));
851 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
852 vec_alloc (ws_args, 1);
853 ws_args->quick_push (t);
854 return ws_args;
857 gcc_unreachable ();
861 /* Discover whether REGION is a combined parallel+workshare region. */
863 static void
864 determine_parallel_type (struct omp_region *region)
866 basic_block par_entry_bb, par_exit_bb;
867 basic_block ws_entry_bb, ws_exit_bb;
869 if (region == NULL || region->inner == NULL
870 || region->exit == NULL || region->inner->exit == NULL
871 || region->inner->cont == NULL)
872 return;
874 /* We only support parallel+for and parallel+sections. */
875 if (region->type != GIMPLE_OMP_PARALLEL
876 || (region->inner->type != GIMPLE_OMP_FOR
877 && region->inner->type != GIMPLE_OMP_SECTIONS))
878 return;
880 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
881 WS_EXIT_BB -> PAR_EXIT_BB. */
882 par_entry_bb = region->entry;
883 par_exit_bb = region->exit;
884 ws_entry_bb = region->inner->entry;
885 ws_exit_bb = region->inner->exit;
887 if (single_succ (par_entry_bb) == ws_entry_bb
888 && single_succ (ws_exit_bb) == par_exit_bb
889 && workshare_safe_to_combine_p (ws_entry_bb)
890 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
891 || (last_and_only_stmt (ws_entry_bb)
892 && last_and_only_stmt (par_exit_bb))))
894 gimple par_stmt = last_stmt (par_entry_bb);
895 gimple ws_stmt = last_stmt (ws_entry_bb);
897 if (region->inner->type == GIMPLE_OMP_FOR)
899 /* If this is a combined parallel loop, we need to determine
900 whether or not to use the combined library calls. There
901 are two cases where we do not apply the transformation:
902 static loops and any kind of ordered loop. In the first
903 case, we already open code the loop so there is no need
904 to do anything else. In the latter case, the combined
905 parallel loop call would still need extra synchronization
906 to implement ordered semantics, so there would not be any
907 gain in using the combined call. */
908 tree clauses = gimple_omp_for_clauses (ws_stmt);
909 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
910 if (c == NULL
911 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
912 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
914 region->is_combined_parallel = false;
915 region->inner->is_combined_parallel = false;
916 return;
920 region->is_combined_parallel = true;
921 region->inner->is_combined_parallel = true;
922 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
927 /* Return true if EXPR is variable sized. */
929 static inline bool
930 is_variable_sized (const_tree expr)
932 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
935 /* Return true if DECL is a reference type. */
937 static inline bool
938 is_reference (tree decl)
940 return lang_hooks.decls.omp_privatize_by_reference (decl);
943 /* Return the type of a decl. If the decl is reference type,
944 return its base type. */
945 static inline tree
946 get_base_type (tree decl)
948 tree type = TREE_TYPE (decl);
949 if (is_reference (decl))
950 type = TREE_TYPE (type);
951 return type;
954 /* Lookup variables. The "maybe" form
955 allows for the variable form to not have been entered, otherwise we
956 assert that the variable must have been entered. */
958 static inline tree
959 lookup_decl (tree var, omp_context *ctx)
961 tree *n = ctx->cb.decl_map->get (var);
962 return *n;
965 static inline tree
966 maybe_lookup_decl (const_tree var, omp_context *ctx)
968 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
969 return n ? *n : NULL_TREE;
972 static inline tree
973 lookup_field (tree var, omp_context *ctx)
975 splay_tree_node n;
976 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
977 return (tree) n->value;
980 static inline tree
981 lookup_sfield (tree var, omp_context *ctx)
983 splay_tree_node n;
984 n = splay_tree_lookup (ctx->sfield_map
985 ? ctx->sfield_map : ctx->field_map,
986 (splay_tree_key) var);
987 return (tree) n->value;
990 static inline tree
991 maybe_lookup_field (tree var, omp_context *ctx)
993 splay_tree_node n;
994 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
995 return n ? (tree) n->value : NULL_TREE;
998 static inline tree
999 lookup_oacc_reduction (const char *id, omp_context *ctx)
1001 splay_tree_node n;
1002 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
1003 return (tree) n->value;
1006 static inline tree
1007 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
1009 splay_tree_node n = NULL;
1010 if (ctx->reduction_map)
1011 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
1012 return n ? (tree) n->value : NULL_TREE;
1015 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1016 the parallel context if DECL is to be shared. */
1018 static bool
1019 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1021 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1022 return true;
1024 /* We can only use copy-in/copy-out semantics for shared variables
1025 when we know the value is not accessible from an outer scope. */
1026 if (shared_ctx)
1028 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1030 /* ??? Trivially accessible from anywhere. But why would we even
1031 be passing an address in this case? Should we simply assert
1032 this to be false, or should we have a cleanup pass that removes
1033 these from the list of mappings? */
1034 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1035 return true;
1037 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1038 without analyzing the expression whether or not its location
1039 is accessible to anyone else. In the case of nested parallel
1040 regions it certainly may be. */
1041 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1042 return true;
1044 /* Do not use copy-in/copy-out for variables that have their
1045 address taken. */
1046 if (TREE_ADDRESSABLE (decl))
1047 return true;
1049 /* lower_send_shared_vars only uses copy-in, but not copy-out
1050 for these. */
1051 if (TREE_READONLY (decl)
1052 || ((TREE_CODE (decl) == RESULT_DECL
1053 || TREE_CODE (decl) == PARM_DECL)
1054 && DECL_BY_REFERENCE (decl)))
1055 return false;
1057 /* Disallow copy-in/out in nested parallel if
1058 decl is shared in outer parallel, otherwise
1059 each thread could store the shared variable
1060 in its own copy-in location, making the
1061 variable no longer really shared. */
1062 if (shared_ctx->is_nested)
1064 omp_context *up;
1066 for (up = shared_ctx->outer; up; up = up->outer)
1067 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1068 break;
1070 if (up)
1072 tree c;
1074 for (c = gimple_omp_taskreg_clauses (up->stmt);
1075 c; c = OMP_CLAUSE_CHAIN (c))
1076 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1077 && OMP_CLAUSE_DECL (c) == decl)
1078 break;
1080 if (c)
1081 goto maybe_mark_addressable_and_ret;
1085 /* For tasks avoid using copy-in/out. As tasks can be
1086 deferred or executed in different thread, when GOMP_task
1087 returns, the task hasn't necessarily terminated. */
1088 if (is_task_ctx (shared_ctx))
1090 tree outer;
1091 maybe_mark_addressable_and_ret:
1092 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1093 if (is_gimple_reg (outer))
1095 /* Taking address of OUTER in lower_send_shared_vars
1096 might need regimplification of everything that uses the
1097 variable. */
1098 if (!task_shared_vars)
1099 task_shared_vars = BITMAP_ALLOC (NULL);
1100 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1101 TREE_ADDRESSABLE (outer) = 1;
1103 return true;
1107 return false;
1110 /* Construct a new automatic decl similar to VAR. */
1112 static tree
1113 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1115 tree copy = copy_var_decl (var, name, type);
1117 DECL_CONTEXT (copy) = current_function_decl;
1118 DECL_CHAIN (copy) = ctx->block_vars;
1119 ctx->block_vars = copy;
1121 return copy;
1124 static tree
1125 omp_copy_decl_1 (tree var, omp_context *ctx)
1127 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1130 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1131 as appropriate. */
1132 static tree
1133 omp_build_component_ref (tree obj, tree field)
1135 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1136 if (TREE_THIS_VOLATILE (field))
1137 TREE_THIS_VOLATILE (ret) |= 1;
1138 if (TREE_READONLY (field))
1139 TREE_READONLY (ret) |= 1;
1140 return ret;
1143 /* Build tree nodes to access the field for VAR on the receiver side. */
1145 static tree
1146 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1148 tree x, field = lookup_field (var, ctx);
1150 /* If the receiver record type was remapped in the child function,
1151 remap the field into the new record type. */
1152 x = maybe_lookup_field (field, ctx);
1153 if (x != NULL)
1154 field = x;
1156 x = build_simple_mem_ref (ctx->receiver_decl);
1157 x = omp_build_component_ref (x, field);
1158 if (by_ref)
1159 x = build_simple_mem_ref (x);
1161 return x;
1164 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1165 of a parallel, this is a component reference; for workshare constructs
1166 this is some variable. */
1168 static tree
1169 build_outer_var_ref (tree var, omp_context *ctx)
1171 tree x;
1173 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1174 x = var;
1175 else if (is_variable_sized (var))
1177 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1178 x = build_outer_var_ref (x, ctx);
1179 x = build_simple_mem_ref (x);
1181 else if (is_taskreg_ctx (ctx))
1183 bool by_ref = use_pointer_for_field (var, NULL);
1184 x = build_receiver_ref (var, by_ref, ctx);
1186 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1187 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1189 /* #pragma omp simd isn't a worksharing construct, and can reference even
1190 private vars in its linear etc. clauses. */
1191 x = NULL_TREE;
1192 if (ctx->outer && is_taskreg_ctx (ctx))
1193 x = lookup_decl (var, ctx->outer);
1194 else if (ctx->outer)
1195 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1196 if (x == NULL_TREE)
1197 x = var;
1199 else if (ctx->outer)
1200 x = lookup_decl (var, ctx->outer);
1201 else if (is_reference (var))
1202 /* This can happen with orphaned constructs. If var is reference, it is
1203 possible it is shared and as such valid. */
1204 x = var;
1205 else
1206 gcc_unreachable ();
1208 if (is_reference (var))
1209 x = build_simple_mem_ref (x);
1211 return x;
1214 /* Build tree nodes to access the field for VAR on the sender side. */
1216 static tree
1217 build_sender_ref (tree var, omp_context *ctx)
1219 tree field = lookup_sfield (var, ctx);
1220 return omp_build_component_ref (ctx->sender_decl, field);
1223 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1225 static void
1226 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1228 tree field, type, sfield = NULL_TREE;
1230 gcc_assert ((mask & 1) == 0
1231 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1232 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1233 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1234 gcc_assert ((mask & 3) == 3
1235 || !is_gimple_omp_oacc (ctx->stmt));
1237 type = TREE_TYPE (var);
1238 if (mask & 4)
1240 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1241 type = build_pointer_type (build_pointer_type (type));
1243 else if (by_ref)
1244 type = build_pointer_type (type);
1245 else if ((mask & 3) == 1 && is_reference (var))
1246 type = TREE_TYPE (type);
1248 field = build_decl (DECL_SOURCE_LOCATION (var),
1249 FIELD_DECL, DECL_NAME (var), type);
1251 /* Remember what variable this field was created for. This does have a
1252 side effect of making dwarf2out ignore this member, so for helpful
1253 debugging we clear it later in delete_omp_context. */
1254 DECL_ABSTRACT_ORIGIN (field) = var;
1255 if (type == TREE_TYPE (var))
1257 DECL_ALIGN (field) = DECL_ALIGN (var);
1258 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1259 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1261 else
1262 DECL_ALIGN (field) = TYPE_ALIGN (type);
1264 if ((mask & 3) == 3)
1266 insert_field_into_struct (ctx->record_type, field);
1267 if (ctx->srecord_type)
1269 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1270 FIELD_DECL, DECL_NAME (var), type);
1271 DECL_ABSTRACT_ORIGIN (sfield) = var;
1272 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1273 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1274 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1275 insert_field_into_struct (ctx->srecord_type, sfield);
1278 else
1280 if (ctx->srecord_type == NULL_TREE)
1282 tree t;
1284 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1285 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1286 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1288 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1289 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1290 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1291 insert_field_into_struct (ctx->srecord_type, sfield);
1292 splay_tree_insert (ctx->sfield_map,
1293 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1294 (splay_tree_value) sfield);
1297 sfield = field;
1298 insert_field_into_struct ((mask & 1) ? ctx->record_type
1299 : ctx->srecord_type, field);
1302 if (mask & 1)
1303 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1304 (splay_tree_value) field);
1305 if ((mask & 2) && ctx->sfield_map)
1306 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1307 (splay_tree_value) sfield);
1310 static tree
1311 install_var_local (tree var, omp_context *ctx)
1313 tree new_var = omp_copy_decl_1 (var, ctx);
1314 insert_decl_map (&ctx->cb, var, new_var);
1315 return new_var;
1318 /* Adjust the replacement for DECL in CTX for the new context. This means
1319 copying the DECL_VALUE_EXPR, and fixing up the type. */
1321 static void
1322 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1324 tree new_decl, size;
1326 new_decl = lookup_decl (decl, ctx);
1328 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1330 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1331 && DECL_HAS_VALUE_EXPR_P (decl))
1333 tree ve = DECL_VALUE_EXPR (decl);
1334 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1335 SET_DECL_VALUE_EXPR (new_decl, ve);
1336 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1339 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1341 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1342 if (size == error_mark_node)
1343 size = TYPE_SIZE (TREE_TYPE (new_decl));
1344 DECL_SIZE (new_decl) = size;
1346 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1347 if (size == error_mark_node)
1348 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1349 DECL_SIZE_UNIT (new_decl) = size;
1353 /* The callback for remap_decl. Search all containing contexts for a
1354 mapping of the variable; this avoids having to duplicate the splay
1355 tree ahead of time. We know a mapping doesn't already exist in the
1356 given context. Create new mappings to implement default semantics. */
1358 static tree
1359 omp_copy_decl (tree var, copy_body_data *cb)
1361 omp_context *ctx = (omp_context *) cb;
1362 tree new_var;
1364 if (TREE_CODE (var) == LABEL_DECL)
1366 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1367 DECL_CONTEXT (new_var) = current_function_decl;
1368 insert_decl_map (&ctx->cb, var, new_var);
1369 return new_var;
1372 while (!is_taskreg_ctx (ctx))
1374 ctx = ctx->outer;
1375 if (ctx == NULL)
1376 return var;
1377 new_var = maybe_lookup_decl (var, ctx);
1378 if (new_var)
1379 return new_var;
1382 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1383 return var;
1385 return error_mark_node;
1389 /* Debugging dumps for parallel regions. */
1390 void dump_omp_region (FILE *, struct omp_region *, int);
1391 void debug_omp_region (struct omp_region *);
1392 void debug_all_omp_regions (void);
1394 /* Dump the parallel region tree rooted at REGION. */
1396 void
1397 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1399 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1400 gimple_code_name[region->type]);
1402 if (region->inner)
1403 dump_omp_region (file, region->inner, indent + 4);
1405 if (region->cont)
1407 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1408 region->cont->index);
1411 if (region->exit)
1412 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1413 region->exit->index);
1414 else
1415 fprintf (file, "%*s[no exit marker]\n", indent, "");
1417 if (region->next)
1418 dump_omp_region (file, region->next, indent);
1421 DEBUG_FUNCTION void
1422 debug_omp_region (struct omp_region *region)
1424 dump_omp_region (stderr, region, 0);
1427 DEBUG_FUNCTION void
1428 debug_all_omp_regions (void)
1430 dump_omp_region (stderr, root_omp_region, 0);
1434 /* Create a new parallel region starting at STMT inside region PARENT. */
1436 static struct omp_region *
1437 new_omp_region (basic_block bb, enum gimple_code type,
1438 struct omp_region *parent)
1440 struct omp_region *region = XCNEW (struct omp_region);
1442 region->outer = parent;
1443 region->entry = bb;
1444 region->type = type;
1446 if (parent)
1448 /* This is a nested region. Add it to the list of inner
1449 regions in PARENT. */
1450 region->next = parent->inner;
1451 parent->inner = region;
1453 else
1455 /* This is a toplevel region. Add it to the list of toplevel
1456 regions in ROOT_OMP_REGION. */
1457 region->next = root_omp_region;
1458 root_omp_region = region;
1461 return region;
1464 /* Release the memory associated with the region tree rooted at REGION. */
1466 static void
1467 free_omp_region_1 (struct omp_region *region)
1469 struct omp_region *i, *n;
1471 for (i = region->inner; i ; i = n)
1473 n = i->next;
1474 free_omp_region_1 (i);
1477 free (region);
1480 /* Release the memory for the entire omp region tree. */
1482 void
1483 free_omp_regions (void)
1485 struct omp_region *r, *n;
1486 for (r = root_omp_region; r ; r = n)
1488 n = r->next;
1489 free_omp_region_1 (r);
1491 root_omp_region = NULL;
1495 /* Create a new context, with OUTER_CTX being the surrounding context. */
1497 static omp_context *
1498 new_omp_context (gimple stmt, omp_context *outer_ctx)
1500 omp_context *ctx = XCNEW (omp_context);
1502 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1503 (splay_tree_value) ctx);
1504 ctx->stmt = stmt;
1506 if (outer_ctx)
1508 ctx->outer = outer_ctx;
1509 ctx->cb = outer_ctx->cb;
1510 ctx->cb.block = NULL;
1511 ctx->depth = outer_ctx->depth + 1;
1512 ctx->reduction_map = outer_ctx->reduction_map;
1514 else
1516 ctx->cb.src_fn = current_function_decl;
1517 ctx->cb.dst_fn = current_function_decl;
1518 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1519 gcc_checking_assert (ctx->cb.src_node);
1520 ctx->cb.dst_node = ctx->cb.src_node;
1521 ctx->cb.src_cfun = cfun;
1522 ctx->cb.copy_decl = omp_copy_decl;
1523 ctx->cb.eh_lp_nr = 0;
1524 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1525 ctx->depth = 1;
1528 ctx->cb.decl_map = new hash_map<tree, tree>;
1530 return ctx;
1533 static gimple_seq maybe_catch_exception (gimple_seq);
1535 /* Finalize task copyfn. */
1537 static void
1538 finalize_task_copyfn (gomp_task *task_stmt)
1540 struct function *child_cfun;
1541 tree child_fn;
1542 gimple_seq seq = NULL, new_seq;
1543 gbind *bind;
1545 child_fn = gimple_omp_task_copy_fn (task_stmt);
1546 if (child_fn == NULL_TREE)
1547 return;
1549 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1550 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1552 push_cfun (child_cfun);
1553 bind = gimplify_body (child_fn, false);
1554 gimple_seq_add_stmt (&seq, bind);
1555 new_seq = maybe_catch_exception (seq);
1556 if (new_seq != seq)
1558 bind = gimple_build_bind (NULL, new_seq, NULL);
1559 seq = NULL;
1560 gimple_seq_add_stmt (&seq, bind);
1562 gimple_set_body (child_fn, seq);
1563 pop_cfun ();
1565 /* Inform the callgraph about the new function. */
1566 cgraph_node::add_new_function (child_fn, false);
1569 /* Destroy a omp_context data structures. Called through the splay tree
1570 value delete callback. */
1572 static void
1573 delete_omp_context (splay_tree_value value)
1575 omp_context *ctx = (omp_context *) value;
1577 delete ctx->cb.decl_map;
1579 if (ctx->field_map)
1580 splay_tree_delete (ctx->field_map);
1581 if (ctx->sfield_map)
1582 splay_tree_delete (ctx->sfield_map);
1583 if (ctx->reduction_map
1584 /* Shared over several omp_contexts. */
1585 && (ctx->outer == NULL
1586 || ctx->reduction_map != ctx->outer->reduction_map))
1587 splay_tree_delete (ctx->reduction_map);
1589 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1590 it produces corrupt debug information. */
1591 if (ctx->record_type)
1593 tree t;
1594 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1595 DECL_ABSTRACT_ORIGIN (t) = NULL;
1597 if (ctx->srecord_type)
1599 tree t;
1600 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1601 DECL_ABSTRACT_ORIGIN (t) = NULL;
1604 if (is_task_ctx (ctx))
1605 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1607 XDELETE (ctx);
1610 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1611 context. */
1613 static void
1614 fixup_child_record_type (omp_context *ctx)
1616 tree f, type = ctx->record_type;
1618 /* ??? It isn't sufficient to just call remap_type here, because
1619 variably_modified_type_p doesn't work the way we expect for
1620 record types. Testing each field for whether it needs remapping
1621 and creating a new record by hand works, however. */
1622 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1623 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1624 break;
1625 if (f)
1627 tree name, new_fields = NULL;
1629 type = lang_hooks.types.make_type (RECORD_TYPE);
1630 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1631 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1632 TYPE_DECL, name, type);
1633 TYPE_NAME (type) = name;
1635 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1637 tree new_f = copy_node (f);
1638 DECL_CONTEXT (new_f) = type;
1639 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1640 DECL_CHAIN (new_f) = new_fields;
1641 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1642 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1643 &ctx->cb, NULL);
1644 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1645 &ctx->cb, NULL);
1646 new_fields = new_f;
1648 /* Arrange to be able to look up the receiver field
1649 given the sender field. */
1650 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1651 (splay_tree_value) new_f);
1653 TYPE_FIELDS (type) = nreverse (new_fields);
1654 layout_type (type);
1657 TREE_TYPE (ctx->receiver_decl)
1658 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1661 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1662 specified by CLAUSES. */
1664 static void
1665 scan_sharing_clauses (tree clauses, omp_context *ctx)
1667 tree c, decl;
1668 bool scan_array_reductions = false;
1670 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1672 bool by_ref;
1674 switch (OMP_CLAUSE_CODE (c))
1676 case OMP_CLAUSE_PRIVATE:
1677 decl = OMP_CLAUSE_DECL (c);
1678 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1679 goto do_private;
1680 else if (!is_variable_sized (decl))
1681 install_var_local (decl, ctx);
1682 break;
1684 case OMP_CLAUSE_SHARED:
1685 decl = OMP_CLAUSE_DECL (c);
1686 /* Ignore shared directives in teams construct. */
1687 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1689 /* Global variables don't need to be copied,
1690 the receiver side will use them directly. */
1691 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1692 if (is_global_var (odecl))
1693 break;
1694 insert_decl_map (&ctx->cb, decl, odecl);
1695 break;
1697 gcc_assert (is_taskreg_ctx (ctx));
1698 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1699 || !is_variable_sized (decl));
1700 /* Global variables don't need to be copied,
1701 the receiver side will use them directly. */
1702 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1703 break;
1704 by_ref = use_pointer_for_field (decl, ctx);
1705 if (! TREE_READONLY (decl)
1706 || TREE_ADDRESSABLE (decl)
1707 || by_ref
1708 || is_reference (decl))
1710 install_var_field (decl, by_ref, 3, ctx);
1711 install_var_local (decl, ctx);
1712 break;
1714 /* We don't need to copy const scalar vars back. */
1715 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1716 goto do_private;
1718 case OMP_CLAUSE_LASTPRIVATE:
1719 /* Let the corresponding firstprivate clause create
1720 the variable. */
1721 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1722 break;
1723 /* FALLTHRU */
1725 case OMP_CLAUSE_FIRSTPRIVATE:
1726 if (is_gimple_omp_oacc (ctx->stmt))
1728 sorry ("clause not supported yet");
1729 break;
1731 /* FALLTHRU */
1732 case OMP_CLAUSE_REDUCTION:
1733 case OMP_CLAUSE_LINEAR:
1734 decl = OMP_CLAUSE_DECL (c);
1735 do_private:
1736 if (is_variable_sized (decl))
1738 if (is_task_ctx (ctx))
1739 install_var_field (decl, false, 1, ctx);
1740 break;
1742 else if (is_taskreg_ctx (ctx))
1744 bool global
1745 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1746 by_ref = use_pointer_for_field (decl, NULL);
1748 if (is_task_ctx (ctx)
1749 && (global || by_ref || is_reference (decl)))
1751 install_var_field (decl, false, 1, ctx);
1752 if (!global)
1753 install_var_field (decl, by_ref, 2, ctx);
1755 else if (!global)
1756 install_var_field (decl, by_ref, 3, ctx);
1758 install_var_local (decl, ctx);
1759 if (is_gimple_omp_oacc (ctx->stmt)
1760 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1762 /* Create a decl for the reduction array. */
1763 tree var = OMP_CLAUSE_DECL (c);
1764 tree type = get_base_type (var);
1765 tree ptype = build_pointer_type (type);
1766 tree array = create_tmp_var (ptype,
1767 oacc_get_reduction_array_id (var));
1768 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1769 install_var_field (array, true, 3, c);
1770 install_var_local (array, c);
1772 /* Insert it into the current context. */
1773 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1774 oacc_get_reduction_array_id (var),
1775 (splay_tree_value) array);
1776 splay_tree_insert (ctx->reduction_map,
1777 (splay_tree_key) array,
1778 (splay_tree_value) array);
1780 break;
1782 case OMP_CLAUSE__LOOPTEMP_:
1783 gcc_assert (is_parallel_ctx (ctx));
1784 decl = OMP_CLAUSE_DECL (c);
1785 install_var_field (decl, false, 3, ctx);
1786 install_var_local (decl, ctx);
1787 break;
1789 case OMP_CLAUSE_COPYPRIVATE:
1790 case OMP_CLAUSE_COPYIN:
1791 decl = OMP_CLAUSE_DECL (c);
1792 by_ref = use_pointer_for_field (decl, NULL);
1793 install_var_field (decl, by_ref, 3, ctx);
1794 break;
1796 case OMP_CLAUSE_DEFAULT:
1797 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1798 break;
1800 case OMP_CLAUSE_FINAL:
1801 case OMP_CLAUSE_IF:
1802 case OMP_CLAUSE_NUM_THREADS:
1803 case OMP_CLAUSE_NUM_TEAMS:
1804 case OMP_CLAUSE_THREAD_LIMIT:
1805 case OMP_CLAUSE_DEVICE:
1806 case OMP_CLAUSE_SCHEDULE:
1807 case OMP_CLAUSE_DIST_SCHEDULE:
1808 case OMP_CLAUSE_DEPEND:
1809 case OMP_CLAUSE__CILK_FOR_COUNT_:
1810 case OMP_CLAUSE_NUM_GANGS:
1811 case OMP_CLAUSE_NUM_WORKERS:
1812 case OMP_CLAUSE_VECTOR_LENGTH:
1813 if (ctx->outer)
1814 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1815 break;
1817 case OMP_CLAUSE_TO:
1818 case OMP_CLAUSE_FROM:
1819 case OMP_CLAUSE_MAP:
1820 if (ctx->outer)
1821 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1822 decl = OMP_CLAUSE_DECL (c);
1823 /* Global variables with "omp declare target" attribute
1824 don't need to be copied, the receiver side will use them
1825 directly. */
1826 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1827 && DECL_P (decl)
1828 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1829 && varpool_node::get_create (decl)->offloadable)
1830 break;
1831 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1832 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1834 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1835 not offloaded; there is nothing to map for those. */
1836 if (!is_gimple_omp_offloaded (ctx->stmt)
1837 && !POINTER_TYPE_P (TREE_TYPE (decl))
1838 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
1839 break;
1841 if (DECL_P (decl))
1843 if (DECL_SIZE (decl)
1844 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1846 tree decl2 = DECL_VALUE_EXPR (decl);
1847 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1848 decl2 = TREE_OPERAND (decl2, 0);
1849 gcc_assert (DECL_P (decl2));
1850 install_var_field (decl2, true, 3, ctx);
1851 install_var_local (decl2, ctx);
1852 install_var_local (decl, ctx);
1854 else
1856 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1857 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1858 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1859 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1860 install_var_field (decl, true, 7, ctx);
1861 else
1862 install_var_field (decl, true, 3, ctx);
1863 if (is_gimple_omp_offloaded (ctx->stmt))
1864 install_var_local (decl, ctx);
1867 else
1869 tree base = get_base_address (decl);
1870 tree nc = OMP_CLAUSE_CHAIN (c);
1871 if (DECL_P (base)
1872 && nc != NULL_TREE
1873 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1874 && OMP_CLAUSE_DECL (nc) == base
1875 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1876 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1878 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1879 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1881 else
1883 if (ctx->outer)
1885 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1886 decl = OMP_CLAUSE_DECL (c);
1888 gcc_assert (!splay_tree_lookup (ctx->field_map,
1889 (splay_tree_key) decl));
1890 tree field
1891 = build_decl (OMP_CLAUSE_LOCATION (c),
1892 FIELD_DECL, NULL_TREE, ptr_type_node);
1893 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1894 insert_field_into_struct (ctx->record_type, field);
1895 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1896 (splay_tree_value) field);
1899 break;
1901 case OMP_CLAUSE_NOWAIT:
1902 case OMP_CLAUSE_ORDERED:
1903 case OMP_CLAUSE_COLLAPSE:
1904 case OMP_CLAUSE_UNTIED:
1905 case OMP_CLAUSE_MERGEABLE:
1906 case OMP_CLAUSE_PROC_BIND:
1907 case OMP_CLAUSE_SAFELEN:
1908 case OMP_CLAUSE_ASYNC:
1909 case OMP_CLAUSE_WAIT:
1910 case OMP_CLAUSE_GANG:
1911 case OMP_CLAUSE_WORKER:
1912 case OMP_CLAUSE_VECTOR:
1913 break;
1915 case OMP_CLAUSE_ALIGNED:
1916 decl = OMP_CLAUSE_DECL (c);
1917 if (is_global_var (decl)
1918 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1919 install_var_local (decl, ctx);
1920 break;
1922 case OMP_CLAUSE_DEVICE_RESIDENT:
1923 case OMP_CLAUSE_USE_DEVICE:
1924 case OMP_CLAUSE__CACHE_:
1925 case OMP_CLAUSE_INDEPENDENT:
1926 case OMP_CLAUSE_AUTO:
1927 case OMP_CLAUSE_SEQ:
1928 sorry ("Clause not supported yet");
1929 break;
1931 default:
1932 gcc_unreachable ();
1936 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1938 switch (OMP_CLAUSE_CODE (c))
1940 case OMP_CLAUSE_LASTPRIVATE:
1941 /* Let the corresponding firstprivate clause create
1942 the variable. */
1943 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1944 scan_array_reductions = true;
1945 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1946 break;
1947 /* FALLTHRU */
1949 case OMP_CLAUSE_FIRSTPRIVATE:
1950 if (is_gimple_omp_oacc (ctx->stmt))
1952 sorry ("clause not supported yet");
1953 break;
1955 /* FALLTHRU */
1956 case OMP_CLAUSE_PRIVATE:
1957 case OMP_CLAUSE_REDUCTION:
1958 case OMP_CLAUSE_LINEAR:
1959 decl = OMP_CLAUSE_DECL (c);
1960 if (is_variable_sized (decl))
1961 install_var_local (decl, ctx);
1962 fixup_remapped_decl (decl, ctx,
1963 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1964 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1965 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1966 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1967 scan_array_reductions = true;
1968 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1969 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1970 scan_array_reductions = true;
1971 break;
1973 case OMP_CLAUSE_SHARED:
1974 /* Ignore shared directives in teams construct. */
1975 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1976 break;
1977 decl = OMP_CLAUSE_DECL (c);
1978 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1979 fixup_remapped_decl (decl, ctx, false);
1980 break;
1982 case OMP_CLAUSE_MAP:
1983 if (!is_gimple_omp_offloaded (ctx->stmt))
1984 break;
1985 decl = OMP_CLAUSE_DECL (c);
1986 if (DECL_P (decl)
1987 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1988 && varpool_node::get_create (decl)->offloadable)
1989 break;
1990 if (DECL_P (decl))
1992 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1993 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1994 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1996 tree new_decl = lookup_decl (decl, ctx);
1997 TREE_TYPE (new_decl)
1998 = remap_type (TREE_TYPE (decl), &ctx->cb);
2000 else if (DECL_SIZE (decl)
2001 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2003 tree decl2 = DECL_VALUE_EXPR (decl);
2004 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2005 decl2 = TREE_OPERAND (decl2, 0);
2006 gcc_assert (DECL_P (decl2));
2007 fixup_remapped_decl (decl2, ctx, false);
2008 fixup_remapped_decl (decl, ctx, true);
2010 else
2011 fixup_remapped_decl (decl, ctx, false);
2013 break;
2015 case OMP_CLAUSE_COPYPRIVATE:
2016 case OMP_CLAUSE_COPYIN:
2017 case OMP_CLAUSE_DEFAULT:
2018 case OMP_CLAUSE_IF:
2019 case OMP_CLAUSE_NUM_THREADS:
2020 case OMP_CLAUSE_NUM_TEAMS:
2021 case OMP_CLAUSE_THREAD_LIMIT:
2022 case OMP_CLAUSE_DEVICE:
2023 case OMP_CLAUSE_SCHEDULE:
2024 case OMP_CLAUSE_DIST_SCHEDULE:
2025 case OMP_CLAUSE_NOWAIT:
2026 case OMP_CLAUSE_ORDERED:
2027 case OMP_CLAUSE_COLLAPSE:
2028 case OMP_CLAUSE_UNTIED:
2029 case OMP_CLAUSE_FINAL:
2030 case OMP_CLAUSE_MERGEABLE:
2031 case OMP_CLAUSE_PROC_BIND:
2032 case OMP_CLAUSE_SAFELEN:
2033 case OMP_CLAUSE_ALIGNED:
2034 case OMP_CLAUSE_DEPEND:
2035 case OMP_CLAUSE__LOOPTEMP_:
2036 case OMP_CLAUSE_TO:
2037 case OMP_CLAUSE_FROM:
2038 case OMP_CLAUSE__CILK_FOR_COUNT_:
2039 case OMP_CLAUSE_ASYNC:
2040 case OMP_CLAUSE_WAIT:
2041 case OMP_CLAUSE_NUM_GANGS:
2042 case OMP_CLAUSE_NUM_WORKERS:
2043 case OMP_CLAUSE_VECTOR_LENGTH:
2044 case OMP_CLAUSE_GANG:
2045 case OMP_CLAUSE_WORKER:
2046 case OMP_CLAUSE_VECTOR:
2047 break;
2049 case OMP_CLAUSE_DEVICE_RESIDENT:
2050 case OMP_CLAUSE_USE_DEVICE:
2051 case OMP_CLAUSE__CACHE_:
2052 case OMP_CLAUSE_INDEPENDENT:
2053 case OMP_CLAUSE_AUTO:
2054 case OMP_CLAUSE_SEQ:
2055 sorry ("Clause not supported yet");
2056 break;
2058 default:
2059 gcc_unreachable ();
2063 gcc_checking_assert (!scan_array_reductions
2064 || !is_gimple_omp_oacc (ctx->stmt));
2065 if (scan_array_reductions)
2066 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2067 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2068 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2070 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2071 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2073 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2074 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2075 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2076 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2077 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2078 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2081 /* Create a new name for omp child function. Returns an identifier. If
2082 IS_CILK_FOR is true then the suffix for the child function is
2083 "_cilk_for_fn." */
2085 static tree
2086 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2088 if (is_cilk_for)
2089 return clone_function_name (current_function_decl, "_cilk_for_fn");
2090 return clone_function_name (current_function_decl,
2091 task_copy ? "_omp_cpyfn" : "_omp_fn");
2094 /* Returns the type of the induction variable for the child function for
2095 _Cilk_for and the types for _high and _low variables based on TYPE. */
2097 static tree
2098 cilk_for_check_loop_diff_type (tree type)
2100 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2102 if (TYPE_UNSIGNED (type))
2103 return uint32_type_node;
2104 else
2105 return integer_type_node;
2107 else
2109 if (TYPE_UNSIGNED (type))
2110 return uint64_type_node;
2111 else
2112 return long_long_integer_type_node;
2116 /* Build a decl for the omp child function. It'll not contain a body
2117 yet, just the bare decl. */
2119 static void
2120 create_omp_child_function (omp_context *ctx, bool task_copy)
2122 tree decl, type, name, t;
2124 tree cilk_for_count
2125 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2126 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2127 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2128 tree cilk_var_type = NULL_TREE;
2130 name = create_omp_child_function_name (task_copy,
2131 cilk_for_count != NULL_TREE);
2132 if (task_copy)
2133 type = build_function_type_list (void_type_node, ptr_type_node,
2134 ptr_type_node, NULL_TREE);
2135 else if (cilk_for_count)
2137 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2138 cilk_var_type = cilk_for_check_loop_diff_type (type);
2139 type = build_function_type_list (void_type_node, ptr_type_node,
2140 cilk_var_type, cilk_var_type, NULL_TREE);
2142 else
2143 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2145 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2147 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2148 || !task_copy);
2149 if (!task_copy)
2150 ctx->cb.dst_fn = decl;
2151 else
2152 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2154 TREE_STATIC (decl) = 1;
2155 TREE_USED (decl) = 1;
2156 DECL_ARTIFICIAL (decl) = 1;
2157 DECL_IGNORED_P (decl) = 0;
2158 TREE_PUBLIC (decl) = 0;
2159 DECL_UNINLINABLE (decl) = 1;
2160 DECL_EXTERNAL (decl) = 0;
2161 DECL_CONTEXT (decl) = NULL_TREE;
2162 DECL_INITIAL (decl) = make_node (BLOCK);
2163 if (cgraph_node::get (current_function_decl)->offloadable)
2164 cgraph_node::get_create (decl)->offloadable = 1;
2165 else
2167 omp_context *octx;
2168 for (octx = ctx; octx; octx = octx->outer)
2169 if (is_gimple_omp_offloaded (octx->stmt))
2171 cgraph_node::get_create (decl)->offloadable = 1;
2172 #ifdef ENABLE_OFFLOADING
2173 g->have_offload = true;
2174 #endif
2175 break;
2179 t = build_decl (DECL_SOURCE_LOCATION (decl),
2180 RESULT_DECL, NULL_TREE, void_type_node);
2181 DECL_ARTIFICIAL (t) = 1;
2182 DECL_IGNORED_P (t) = 1;
2183 DECL_CONTEXT (t) = decl;
2184 DECL_RESULT (decl) = t;
2186 /* _Cilk_for's child function requires two extra parameters called
2187 __low and __high that are set the by Cilk runtime when it calls this
2188 function. */
2189 if (cilk_for_count)
2191 t = build_decl (DECL_SOURCE_LOCATION (decl),
2192 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2193 DECL_ARTIFICIAL (t) = 1;
2194 DECL_NAMELESS (t) = 1;
2195 DECL_ARG_TYPE (t) = ptr_type_node;
2196 DECL_CONTEXT (t) = current_function_decl;
2197 TREE_USED (t) = 1;
2198 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2199 DECL_ARGUMENTS (decl) = t;
2201 t = build_decl (DECL_SOURCE_LOCATION (decl),
2202 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2203 DECL_ARTIFICIAL (t) = 1;
2204 DECL_NAMELESS (t) = 1;
2205 DECL_ARG_TYPE (t) = ptr_type_node;
2206 DECL_CONTEXT (t) = current_function_decl;
2207 TREE_USED (t) = 1;
2208 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2209 DECL_ARGUMENTS (decl) = t;
2212 tree data_name = get_identifier (".omp_data_i");
2213 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2214 ptr_type_node);
2215 DECL_ARTIFICIAL (t) = 1;
2216 DECL_NAMELESS (t) = 1;
2217 DECL_ARG_TYPE (t) = ptr_type_node;
2218 DECL_CONTEXT (t) = current_function_decl;
2219 TREE_USED (t) = 1;
2220 if (cilk_for_count)
2221 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2222 DECL_ARGUMENTS (decl) = t;
2223 if (!task_copy)
2224 ctx->receiver_decl = t;
2225 else
2227 t = build_decl (DECL_SOURCE_LOCATION (decl),
2228 PARM_DECL, get_identifier (".omp_data_o"),
2229 ptr_type_node);
2230 DECL_ARTIFICIAL (t) = 1;
2231 DECL_NAMELESS (t) = 1;
2232 DECL_ARG_TYPE (t) = ptr_type_node;
2233 DECL_CONTEXT (t) = current_function_decl;
2234 TREE_USED (t) = 1;
2235 TREE_ADDRESSABLE (t) = 1;
2236 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2237 DECL_ARGUMENTS (decl) = t;
2240 /* Allocate memory for the function structure. The call to
2241 allocate_struct_function clobbers CFUN, so we need to restore
2242 it afterward. */
2243 push_struct_function (decl);
2244 cfun->function_end_locus = gimple_location (ctx->stmt);
2245 pop_cfun ();
2248 /* Callback for walk_gimple_seq. Check if combined parallel
2249 contains gimple_omp_for_combined_into_p OMP_FOR. */
2251 static tree
2252 find_combined_for (gimple_stmt_iterator *gsi_p,
2253 bool *handled_ops_p,
2254 struct walk_stmt_info *wi)
2256 gimple stmt = gsi_stmt (*gsi_p);
2258 *handled_ops_p = true;
2259 switch (gimple_code (stmt))
2261 WALK_SUBSTMTS;
2263 case GIMPLE_OMP_FOR:
2264 if (gimple_omp_for_combined_into_p (stmt)
2265 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2267 wi->info = stmt;
2268 return integer_zero_node;
2270 break;
2271 default:
2272 break;
2274 return NULL;
2277 /* Scan an OpenMP parallel directive. */
2279 static void
2280 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2282 omp_context *ctx;
2283 tree name;
2284 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2286 /* Ignore parallel directives with empty bodies, unless there
2287 are copyin clauses. */
2288 if (optimize > 0
2289 && empty_body_p (gimple_omp_body (stmt))
2290 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2291 OMP_CLAUSE_COPYIN) == NULL)
2293 gsi_replace (gsi, gimple_build_nop (), false);
2294 return;
2297 if (gimple_omp_parallel_combined_p (stmt))
2299 struct walk_stmt_info wi;
2301 memset (&wi, 0, sizeof (wi));
2302 wi.val_only = true;
2303 walk_gimple_seq (gimple_omp_body (stmt),
2304 find_combined_for, NULL, &wi);
2305 if (wi.info)
2307 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2308 struct omp_for_data fd;
2309 extract_omp_for_data (for_stmt, &fd, NULL);
2310 /* We need two temporaries with fd.loop.v type (istart/iend)
2311 and then (fd.collapse - 1) temporaries with the same
2312 type for count2 ... countN-1 vars if not constant. */
2313 size_t count = 2, i;
2314 tree type = fd.iter_type;
2315 if (fd.collapse > 1
2316 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2317 count += fd.collapse - 1;
2318 for (i = 0; i < count; i++)
2320 tree temp = create_tmp_var (type);
2321 tree c = build_omp_clause (UNKNOWN_LOCATION,
2322 OMP_CLAUSE__LOOPTEMP_);
2323 insert_decl_map (&outer_ctx->cb, temp, temp);
2324 OMP_CLAUSE_DECL (c) = temp;
2325 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2326 gimple_omp_parallel_set_clauses (stmt, c);
2331 ctx = new_omp_context (stmt, outer_ctx);
2332 taskreg_contexts.safe_push (ctx);
2333 if (taskreg_nesting_level > 1)
2334 ctx->is_nested = true;
2335 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2336 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2337 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2338 name = create_tmp_var_name (".omp_data_s");
2339 name = build_decl (gimple_location (stmt),
2340 TYPE_DECL, name, ctx->record_type);
2341 DECL_ARTIFICIAL (name) = 1;
2342 DECL_NAMELESS (name) = 1;
2343 TYPE_NAME (ctx->record_type) = name;
2344 create_omp_child_function (ctx, false);
2345 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2347 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2348 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2350 if (TYPE_FIELDS (ctx->record_type) == NULL)
2351 ctx->record_type = ctx->receiver_decl = NULL;
2354 /* Scan an OpenMP task directive. */
2356 static void
2357 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2359 omp_context *ctx;
2360 tree name, t;
2361 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2363 /* Ignore task directives with empty bodies. */
2364 if (optimize > 0
2365 && empty_body_p (gimple_omp_body (stmt)))
2367 gsi_replace (gsi, gimple_build_nop (), false);
2368 return;
2371 ctx = new_omp_context (stmt, outer_ctx);
2372 taskreg_contexts.safe_push (ctx);
2373 if (taskreg_nesting_level > 1)
2374 ctx->is_nested = true;
2375 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2376 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2377 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2378 name = create_tmp_var_name (".omp_data_s");
2379 name = build_decl (gimple_location (stmt),
2380 TYPE_DECL, name, ctx->record_type);
2381 DECL_ARTIFICIAL (name) = 1;
2382 DECL_NAMELESS (name) = 1;
2383 TYPE_NAME (ctx->record_type) = name;
2384 create_omp_child_function (ctx, false);
2385 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2387 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2389 if (ctx->srecord_type)
2391 name = create_tmp_var_name (".omp_data_a");
2392 name = build_decl (gimple_location (stmt),
2393 TYPE_DECL, name, ctx->srecord_type);
2394 DECL_ARTIFICIAL (name) = 1;
2395 DECL_NAMELESS (name) = 1;
2396 TYPE_NAME (ctx->srecord_type) = name;
2397 create_omp_child_function (ctx, true);
2400 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2402 if (TYPE_FIELDS (ctx->record_type) == NULL)
2404 ctx->record_type = ctx->receiver_decl = NULL;
2405 t = build_int_cst (long_integer_type_node, 0);
2406 gimple_omp_task_set_arg_size (stmt, t);
2407 t = build_int_cst (long_integer_type_node, 1);
2408 gimple_omp_task_set_arg_align (stmt, t);
2413 /* If any decls have been made addressable during scan_omp,
2414 adjust their fields if needed, and layout record types
2415 of parallel/task constructs. */
2417 static void
2418 finish_taskreg_scan (omp_context *ctx)
2420 if (ctx->record_type == NULL_TREE)
2421 return;
2423 /* If any task_shared_vars were needed, verify all
2424 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2425 statements if use_pointer_for_field hasn't changed
2426 because of that. If it did, update field types now. */
2427 if (task_shared_vars)
2429 tree c;
2431 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2432 c; c = OMP_CLAUSE_CHAIN (c))
2433 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2435 tree decl = OMP_CLAUSE_DECL (c);
2437 /* Global variables don't need to be copied,
2438 the receiver side will use them directly. */
2439 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2440 continue;
2441 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2442 || !use_pointer_for_field (decl, ctx))
2443 continue;
2444 tree field = lookup_field (decl, ctx);
2445 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2446 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2447 continue;
2448 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2449 TREE_THIS_VOLATILE (field) = 0;
2450 DECL_USER_ALIGN (field) = 0;
2451 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2452 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2453 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2454 if (ctx->srecord_type)
2456 tree sfield = lookup_sfield (decl, ctx);
2457 TREE_TYPE (sfield) = TREE_TYPE (field);
2458 TREE_THIS_VOLATILE (sfield) = 0;
2459 DECL_USER_ALIGN (sfield) = 0;
2460 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2461 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2462 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2467 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2469 layout_type (ctx->record_type);
2470 fixup_child_record_type (ctx);
2472 else
2474 location_t loc = gimple_location (ctx->stmt);
2475 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2476 /* Move VLA fields to the end. */
2477 p = &TYPE_FIELDS (ctx->record_type);
2478 while (*p)
2479 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2480 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2482 *q = *p;
2483 *p = TREE_CHAIN (*p);
2484 TREE_CHAIN (*q) = NULL_TREE;
2485 q = &TREE_CHAIN (*q);
2487 else
2488 p = &DECL_CHAIN (*p);
2489 *p = vla_fields;
2490 layout_type (ctx->record_type);
2491 fixup_child_record_type (ctx);
2492 if (ctx->srecord_type)
2493 layout_type (ctx->srecord_type);
2494 tree t = fold_convert_loc (loc, long_integer_type_node,
2495 TYPE_SIZE_UNIT (ctx->record_type));
2496 gimple_omp_task_set_arg_size (ctx->stmt, t);
2497 t = build_int_cst (long_integer_type_node,
2498 TYPE_ALIGN_UNIT (ctx->record_type));
2499 gimple_omp_task_set_arg_align (ctx->stmt, t);
2504 static omp_context *
2505 enclosing_target_ctx (omp_context *ctx)
2507 while (ctx != NULL
2508 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2509 ctx = ctx->outer;
2510 gcc_assert (ctx != NULL);
2511 return ctx;
2514 static bool
2515 oacc_loop_or_target_p (gimple stmt)
2517 enum gimple_code outer_type = gimple_code (stmt);
2518 return ((outer_type == GIMPLE_OMP_TARGET
2519 && ((gimple_omp_target_kind (stmt)
2520 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2521 || (gimple_omp_target_kind (stmt)
2522 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2523 || (outer_type == GIMPLE_OMP_FOR
2524 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2527 /* Scan a GIMPLE_OMP_FOR. */
2529 static void
2530 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2532 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2533 omp_context *ctx;
2534 size_t i;
2535 tree clauses = gimple_omp_for_clauses (stmt);
2537 if (outer_ctx)
2538 outer_type = gimple_code (outer_ctx->stmt);
2540 ctx = new_omp_context (stmt, outer_ctx);
2542 if (is_gimple_omp_oacc (stmt))
2544 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2545 ctx->gwv_this = outer_ctx->gwv_this;
2546 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2548 int val;
2549 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2550 val = MASK_GANG;
2551 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2552 val = MASK_WORKER;
2553 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2554 val = MASK_VECTOR;
2555 else
2556 continue;
2557 ctx->gwv_this |= val;
2558 if (!outer_ctx)
2560 /* Skip; not nested inside a region. */
2561 continue;
2563 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2565 /* Skip; not nested inside an OpenACC region. */
2566 continue;
2568 if (outer_type == GIMPLE_OMP_FOR)
2569 outer_ctx->gwv_below |= val;
2570 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2572 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2573 if (gimple_omp_target_kind (enclosing->stmt)
2574 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2575 error_at (gimple_location (stmt),
2576 "no arguments allowed to gang, worker and vector clauses inside parallel");
2581 scan_sharing_clauses (clauses, ctx);
2583 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2584 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2586 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2587 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2588 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2589 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2591 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2593 if (is_gimple_omp_oacc (stmt))
2595 if (ctx->gwv_this & ctx->gwv_below)
2596 error_at (gimple_location (stmt),
2597 "gang, worker and vector may occur only once in a loop nest");
2598 else if (ctx->gwv_below != 0
2599 && ctx->gwv_this > ctx->gwv_below)
2600 error_at (gimple_location (stmt),
2601 "gang, worker and vector must occur in this order in a loop nest");
2602 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2603 outer_ctx->gwv_below |= ctx->gwv_below;
2607 /* Scan an OpenMP sections directive. */
2609 static void
2610 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2612 omp_context *ctx;
2614 ctx = new_omp_context (stmt, outer_ctx);
2615 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2616 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2619 /* Scan an OpenMP single directive. */
2621 static void
2622 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2624 omp_context *ctx;
2625 tree name;
2627 ctx = new_omp_context (stmt, outer_ctx);
2628 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2629 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2630 name = create_tmp_var_name (".omp_copy_s");
2631 name = build_decl (gimple_location (stmt),
2632 TYPE_DECL, name, ctx->record_type);
2633 TYPE_NAME (ctx->record_type) = name;
2635 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2636 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2638 if (TYPE_FIELDS (ctx->record_type) == NULL)
2639 ctx->record_type = NULL;
2640 else
2641 layout_type (ctx->record_type);
2644 /* Scan a GIMPLE_OMP_TARGET. */
2646 static void
2647 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2649 omp_context *ctx;
2650 tree name;
2651 bool offloaded = is_gimple_omp_offloaded (stmt);
2652 tree clauses = gimple_omp_target_clauses (stmt);
2654 ctx = new_omp_context (stmt, outer_ctx);
2655 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2656 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2657 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2658 name = create_tmp_var_name (".omp_data_t");
2659 name = build_decl (gimple_location (stmt),
2660 TYPE_DECL, name, ctx->record_type);
2661 DECL_ARTIFICIAL (name) = 1;
2662 DECL_NAMELESS (name) = 1;
2663 TYPE_NAME (ctx->record_type) = name;
2664 if (offloaded)
2666 if (is_gimple_omp_oacc (stmt))
2667 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2668 0, 0);
2670 create_omp_child_function (ctx, false);
2671 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2674 if (is_gimple_omp_oacc (stmt))
2676 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2678 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2679 ctx->gwv_this |= MASK_GANG;
2680 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2681 ctx->gwv_this |= MASK_WORKER;
2682 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2683 ctx->gwv_this |= MASK_VECTOR;
2687 scan_sharing_clauses (clauses, ctx);
2688 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2690 if (TYPE_FIELDS (ctx->record_type) == NULL)
2691 ctx->record_type = ctx->receiver_decl = NULL;
2692 else
2694 TYPE_FIELDS (ctx->record_type)
2695 = nreverse (TYPE_FIELDS (ctx->record_type));
2696 #ifdef ENABLE_CHECKING
2697 tree field;
2698 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2699 for (field = TYPE_FIELDS (ctx->record_type);
2700 field;
2701 field = DECL_CHAIN (field))
2702 gcc_assert (DECL_ALIGN (field) == align);
2703 #endif
2704 layout_type (ctx->record_type);
2705 if (offloaded)
2706 fixup_child_record_type (ctx);
2710 /* Scan an OpenMP teams directive. */
2712 static void
2713 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2715 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2716 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2717 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2720 /* Check nesting restrictions. */
2721 static bool
2722 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2724 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2725 inside an OpenACC CTX. */
2726 if (!(is_gimple_omp (stmt)
2727 && is_gimple_omp_oacc (stmt)))
2729 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2730 if (is_gimple_omp (ctx_->stmt)
2731 && is_gimple_omp_oacc (ctx_->stmt))
2733 error_at (gimple_location (stmt),
2734 "non-OpenACC construct inside of OpenACC region");
2735 return false;
2739 if (ctx != NULL)
2741 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2742 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2744 error_at (gimple_location (stmt),
2745 "OpenMP constructs may not be nested inside simd region");
2746 return false;
2748 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2750 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2751 || (gimple_omp_for_kind (stmt)
2752 != GF_OMP_FOR_KIND_DISTRIBUTE))
2753 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2755 error_at (gimple_location (stmt),
2756 "only distribute or parallel constructs are allowed to "
2757 "be closely nested inside teams construct");
2758 return false;
2762 switch (gimple_code (stmt))
2764 case GIMPLE_OMP_FOR:
2765 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2766 return true;
2767 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2769 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2771 error_at (gimple_location (stmt),
2772 "distribute construct must be closely nested inside "
2773 "teams construct");
2774 return false;
2776 return true;
2778 /* FALLTHRU */
2779 case GIMPLE_CALL:
2780 if (is_gimple_call (stmt)
2781 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2782 == BUILT_IN_GOMP_CANCEL
2783 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2784 == BUILT_IN_GOMP_CANCELLATION_POINT))
2786 const char *bad = NULL;
2787 const char *kind = NULL;
2788 if (ctx == NULL)
2790 error_at (gimple_location (stmt), "orphaned %qs construct",
2791 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2792 == BUILT_IN_GOMP_CANCEL
2793 ? "#pragma omp cancel"
2794 : "#pragma omp cancellation point");
2795 return false;
2797 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2798 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2799 : 0)
2801 case 1:
2802 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2803 bad = "#pragma omp parallel";
2804 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2805 == BUILT_IN_GOMP_CANCEL
2806 && !integer_zerop (gimple_call_arg (stmt, 1)))
2807 ctx->cancellable = true;
2808 kind = "parallel";
2809 break;
2810 case 2:
2811 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2812 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2813 bad = "#pragma omp for";
2814 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2815 == BUILT_IN_GOMP_CANCEL
2816 && !integer_zerop (gimple_call_arg (stmt, 1)))
2818 ctx->cancellable = true;
2819 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2820 OMP_CLAUSE_NOWAIT))
2821 warning_at (gimple_location (stmt), 0,
2822 "%<#pragma omp cancel for%> inside "
2823 "%<nowait%> for construct");
2824 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2825 OMP_CLAUSE_ORDERED))
2826 warning_at (gimple_location (stmt), 0,
2827 "%<#pragma omp cancel for%> inside "
2828 "%<ordered%> for construct");
2830 kind = "for";
2831 break;
2832 case 4:
2833 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2834 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2835 bad = "#pragma omp sections";
2836 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2837 == BUILT_IN_GOMP_CANCEL
2838 && !integer_zerop (gimple_call_arg (stmt, 1)))
2840 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2842 ctx->cancellable = true;
2843 if (find_omp_clause (gimple_omp_sections_clauses
2844 (ctx->stmt),
2845 OMP_CLAUSE_NOWAIT))
2846 warning_at (gimple_location (stmt), 0,
2847 "%<#pragma omp cancel sections%> inside "
2848 "%<nowait%> sections construct");
2850 else
2852 gcc_assert (ctx->outer
2853 && gimple_code (ctx->outer->stmt)
2854 == GIMPLE_OMP_SECTIONS);
2855 ctx->outer->cancellable = true;
2856 if (find_omp_clause (gimple_omp_sections_clauses
2857 (ctx->outer->stmt),
2858 OMP_CLAUSE_NOWAIT))
2859 warning_at (gimple_location (stmt), 0,
2860 "%<#pragma omp cancel sections%> inside "
2861 "%<nowait%> sections construct");
2864 kind = "sections";
2865 break;
2866 case 8:
2867 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2868 bad = "#pragma omp task";
2869 else
2870 ctx->cancellable = true;
2871 kind = "taskgroup";
2872 break;
2873 default:
2874 error_at (gimple_location (stmt), "invalid arguments");
2875 return false;
2877 if (bad)
2879 error_at (gimple_location (stmt),
2880 "%<%s %s%> construct not closely nested inside of %qs",
2881 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2882 == BUILT_IN_GOMP_CANCEL
2883 ? "#pragma omp cancel"
2884 : "#pragma omp cancellation point", kind, bad);
2885 return false;
2888 /* FALLTHRU */
2889 case GIMPLE_OMP_SECTIONS:
2890 case GIMPLE_OMP_SINGLE:
2891 for (; ctx != NULL; ctx = ctx->outer)
2892 switch (gimple_code (ctx->stmt))
2894 case GIMPLE_OMP_FOR:
2895 case GIMPLE_OMP_SECTIONS:
2896 case GIMPLE_OMP_SINGLE:
2897 case GIMPLE_OMP_ORDERED:
2898 case GIMPLE_OMP_MASTER:
2899 case GIMPLE_OMP_TASK:
2900 case GIMPLE_OMP_CRITICAL:
2901 if (is_gimple_call (stmt))
2903 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2904 != BUILT_IN_GOMP_BARRIER)
2905 return true;
2906 error_at (gimple_location (stmt),
2907 "barrier region may not be closely nested inside "
2908 "of work-sharing, critical, ordered, master or "
2909 "explicit task region");
2910 return false;
2912 error_at (gimple_location (stmt),
2913 "work-sharing region may not be closely nested inside "
2914 "of work-sharing, critical, ordered, master or explicit "
2915 "task region");
2916 return false;
2917 case GIMPLE_OMP_PARALLEL:
2918 return true;
2919 default:
2920 break;
2922 break;
2923 case GIMPLE_OMP_MASTER:
2924 for (; ctx != NULL; ctx = ctx->outer)
2925 switch (gimple_code (ctx->stmt))
2927 case GIMPLE_OMP_FOR:
2928 case GIMPLE_OMP_SECTIONS:
2929 case GIMPLE_OMP_SINGLE:
2930 case GIMPLE_OMP_TASK:
2931 error_at (gimple_location (stmt),
2932 "master region may not be closely nested inside "
2933 "of work-sharing or explicit task region");
2934 return false;
2935 case GIMPLE_OMP_PARALLEL:
2936 return true;
2937 default:
2938 break;
2940 break;
2941 case GIMPLE_OMP_ORDERED:
2942 for (; ctx != NULL; ctx = ctx->outer)
2943 switch (gimple_code (ctx->stmt))
2945 case GIMPLE_OMP_CRITICAL:
2946 case GIMPLE_OMP_TASK:
2947 error_at (gimple_location (stmt),
2948 "ordered region may not be closely nested inside "
2949 "of critical or explicit task region");
2950 return false;
2951 case GIMPLE_OMP_FOR:
2952 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2953 OMP_CLAUSE_ORDERED) == NULL)
2955 error_at (gimple_location (stmt),
2956 "ordered region must be closely nested inside "
2957 "a loop region with an ordered clause");
2958 return false;
2960 return true;
2961 case GIMPLE_OMP_PARALLEL:
2962 error_at (gimple_location (stmt),
2963 "ordered region must be closely nested inside "
2964 "a loop region with an ordered clause");
2965 return false;
2966 default:
2967 break;
2969 break;
2970 case GIMPLE_OMP_CRITICAL:
2972 tree this_stmt_name
2973 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2974 for (; ctx != NULL; ctx = ctx->outer)
2975 if (gomp_critical *other_crit
2976 = dyn_cast <gomp_critical *> (ctx->stmt))
2977 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2979 error_at (gimple_location (stmt),
2980 "critical region may not be nested inside a critical "
2981 "region with the same name");
2982 return false;
2985 break;
2986 case GIMPLE_OMP_TEAMS:
2987 if (ctx == NULL
2988 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2989 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2991 error_at (gimple_location (stmt),
2992 "teams construct not closely nested inside of target "
2993 "region");
2994 return false;
2996 break;
2997 case GIMPLE_OMP_TARGET:
2998 for (; ctx != NULL; ctx = ctx->outer)
3000 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3002 if (is_gimple_omp (stmt)
3003 && is_gimple_omp_oacc (stmt)
3004 && is_gimple_omp (ctx->stmt))
3006 error_at (gimple_location (stmt),
3007 "OpenACC construct inside of non-OpenACC region");
3008 return false;
3010 continue;
3013 const char *stmt_name, *ctx_stmt_name;
3014 switch (gimple_omp_target_kind (stmt))
3016 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3017 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3018 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3019 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3020 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3021 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3022 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3023 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3024 default: gcc_unreachable ();
3026 switch (gimple_omp_target_kind (ctx->stmt))
3028 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3029 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3030 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3031 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3032 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3033 default: gcc_unreachable ();
3036 /* OpenACC/OpenMP mismatch? */
3037 if (is_gimple_omp_oacc (stmt)
3038 != is_gimple_omp_oacc (ctx->stmt))
3040 error_at (gimple_location (stmt),
3041 "%s %s construct inside of %s %s region",
3042 (is_gimple_omp_oacc (stmt)
3043 ? "OpenACC" : "OpenMP"), stmt_name,
3044 (is_gimple_omp_oacc (ctx->stmt)
3045 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3046 return false;
3048 if (is_gimple_omp_offloaded (ctx->stmt))
3050 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3051 if (is_gimple_omp_oacc (ctx->stmt))
3053 error_at (gimple_location (stmt),
3054 "%s construct inside of %s region",
3055 stmt_name, ctx_stmt_name);
3056 return false;
3058 else
3060 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3061 warning_at (gimple_location (stmt), 0,
3062 "%s construct inside of %s region",
3063 stmt_name, ctx_stmt_name);
3067 break;
3068 default:
3069 break;
3071 return true;
3075 /* Helper function scan_omp.
3077 Callback for walk_tree or operators in walk_gimple_stmt used to
3078 scan for OMP directives in TP. */
3080 static tree
3081 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3083 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3084 omp_context *ctx = (omp_context *) wi->info;
3085 tree t = *tp;
3087 switch (TREE_CODE (t))
3089 case VAR_DECL:
3090 case PARM_DECL:
3091 case LABEL_DECL:
3092 case RESULT_DECL:
3093 if (ctx)
3094 *tp = remap_decl (t, &ctx->cb);
3095 break;
3097 default:
3098 if (ctx && TYPE_P (t))
3099 *tp = remap_type (t, &ctx->cb);
3100 else if (!DECL_P (t))
3102 *walk_subtrees = 1;
3103 if (ctx)
3105 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3106 if (tem != TREE_TYPE (t))
3108 if (TREE_CODE (t) == INTEGER_CST)
3109 *tp = wide_int_to_tree (tem, t);
3110 else
3111 TREE_TYPE (t) = tem;
3115 break;
3118 return NULL_TREE;
3121 /* Return true if FNDECL is a setjmp or a longjmp. */
3123 static bool
3124 setjmp_or_longjmp_p (const_tree fndecl)
3126 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3127 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3128 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3129 return true;
3131 tree declname = DECL_NAME (fndecl);
3132 if (!declname)
3133 return false;
3134 const char *name = IDENTIFIER_POINTER (declname);
3135 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3139 /* Helper function for scan_omp.
3141 Callback for walk_gimple_stmt used to scan for OMP directives in
3142 the current statement in GSI. */
3144 static tree
3145 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3146 struct walk_stmt_info *wi)
3148 gimple stmt = gsi_stmt (*gsi);
3149 omp_context *ctx = (omp_context *) wi->info;
3151 if (gimple_has_location (stmt))
3152 input_location = gimple_location (stmt);
3154 /* Check the nesting restrictions. */
3155 bool remove = false;
3156 if (is_gimple_omp (stmt))
3157 remove = !check_omp_nesting_restrictions (stmt, ctx);
3158 else if (is_gimple_call (stmt))
3160 tree fndecl = gimple_call_fndecl (stmt);
3161 if (fndecl)
3163 if (setjmp_or_longjmp_p (fndecl)
3164 && ctx
3165 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3166 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3168 remove = true;
3169 error_at (gimple_location (stmt),
3170 "setjmp/longjmp inside simd construct");
3172 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3173 switch (DECL_FUNCTION_CODE (fndecl))
3175 case BUILT_IN_GOMP_BARRIER:
3176 case BUILT_IN_GOMP_CANCEL:
3177 case BUILT_IN_GOMP_CANCELLATION_POINT:
3178 case BUILT_IN_GOMP_TASKYIELD:
3179 case BUILT_IN_GOMP_TASKWAIT:
3180 case BUILT_IN_GOMP_TASKGROUP_START:
3181 case BUILT_IN_GOMP_TASKGROUP_END:
3182 remove = !check_omp_nesting_restrictions (stmt, ctx);
3183 break;
3184 default:
3185 break;
3189 if (remove)
3191 stmt = gimple_build_nop ();
3192 gsi_replace (gsi, stmt, false);
3195 *handled_ops_p = true;
3197 switch (gimple_code (stmt))
3199 case GIMPLE_OMP_PARALLEL:
3200 taskreg_nesting_level++;
3201 scan_omp_parallel (gsi, ctx);
3202 taskreg_nesting_level--;
3203 break;
3205 case GIMPLE_OMP_TASK:
3206 taskreg_nesting_level++;
3207 scan_omp_task (gsi, ctx);
3208 taskreg_nesting_level--;
3209 break;
3211 case GIMPLE_OMP_FOR:
3212 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3213 break;
3215 case GIMPLE_OMP_SECTIONS:
3216 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3217 break;
3219 case GIMPLE_OMP_SINGLE:
3220 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3221 break;
3223 case GIMPLE_OMP_SECTION:
3224 case GIMPLE_OMP_MASTER:
3225 case GIMPLE_OMP_TASKGROUP:
3226 case GIMPLE_OMP_ORDERED:
3227 case GIMPLE_OMP_CRITICAL:
3228 ctx = new_omp_context (stmt, ctx);
3229 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3230 break;
3232 case GIMPLE_OMP_TARGET:
3233 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3234 break;
3236 case GIMPLE_OMP_TEAMS:
3237 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3238 break;
3240 case GIMPLE_BIND:
3242 tree var;
3244 *handled_ops_p = false;
3245 if (ctx)
3246 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3247 var ;
3248 var = DECL_CHAIN (var))
3249 insert_decl_map (&ctx->cb, var, var);
3251 break;
3252 default:
3253 *handled_ops_p = false;
3254 break;
3257 return NULL_TREE;
3261 /* Scan all the statements starting at the current statement. CTX
3262 contains context information about the OMP directives and
3263 clauses found during the scan. */
3265 static void
3266 scan_omp (gimple_seq *body_p, omp_context *ctx)
3268 location_t saved_location;
3269 struct walk_stmt_info wi;
3271 memset (&wi, 0, sizeof (wi));
3272 wi.info = ctx;
3273 wi.want_locations = true;
3275 saved_location = input_location;
3276 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3277 input_location = saved_location;
3280 /* Re-gimplification and code generation routines. */
3282 /* Build a call to GOMP_barrier. */
3284 static gimple
3285 build_omp_barrier (tree lhs)
3287 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3288 : BUILT_IN_GOMP_BARRIER);
3289 gcall *g = gimple_build_call (fndecl, 0);
3290 if (lhs)
3291 gimple_call_set_lhs (g, lhs);
3292 return g;
3295 /* If a context was created for STMT when it was scanned, return it. */
3297 static omp_context *
3298 maybe_lookup_ctx (gimple stmt)
3300 splay_tree_node n;
3301 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3302 return n ? (omp_context *) n->value : NULL;
3306 /* Find the mapping for DECL in CTX or the immediately enclosing
3307 context that has a mapping for DECL.
3309 If CTX is a nested parallel directive, we may have to use the decl
3310 mappings created in CTX's parent context. Suppose that we have the
3311 following parallel nesting (variable UIDs showed for clarity):
3313 iD.1562 = 0;
3314 #omp parallel shared(iD.1562) -> outer parallel
3315 iD.1562 = iD.1562 + 1;
3317 #omp parallel shared (iD.1562) -> inner parallel
3318 iD.1562 = iD.1562 - 1;
3320 Each parallel structure will create a distinct .omp_data_s structure
3321 for copying iD.1562 in/out of the directive:
3323 outer parallel .omp_data_s.1.i -> iD.1562
3324 inner parallel .omp_data_s.2.i -> iD.1562
3326 A shared variable mapping will produce a copy-out operation before
3327 the parallel directive and a copy-in operation after it. So, in
3328 this case we would have:
3330 iD.1562 = 0;
3331 .omp_data_o.1.i = iD.1562;
3332 #omp parallel shared(iD.1562) -> outer parallel
3333 .omp_data_i.1 = &.omp_data_o.1
3334 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3336 .omp_data_o.2.i = iD.1562; -> **
3337 #omp parallel shared(iD.1562) -> inner parallel
3338 .omp_data_i.2 = &.omp_data_o.2
3339 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3342 ** This is a problem. The symbol iD.1562 cannot be referenced
3343 inside the body of the outer parallel region. But since we are
3344 emitting this copy operation while expanding the inner parallel
3345 directive, we need to access the CTX structure of the outer
3346 parallel directive to get the correct mapping:
3348 .omp_data_o.2.i = .omp_data_i.1->i
3350 Since there may be other workshare or parallel directives enclosing
3351 the parallel directive, it may be necessary to walk up the context
3352 parent chain. This is not a problem in general because nested
3353 parallelism happens only rarely. */
3355 static tree
3356 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3358 tree t;
3359 omp_context *up;
3361 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3362 t = maybe_lookup_decl (decl, up);
3364 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3366 return t ? t : decl;
3370 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3371 in outer contexts. */
3373 static tree
3374 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3376 tree t = NULL;
3377 omp_context *up;
3379 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3380 t = maybe_lookup_decl (decl, up);
3382 return t ? t : decl;
3386 /* Construct the initialization value for reduction CLAUSE. */
3388 tree
3389 omp_reduction_init (tree clause, tree type)
3391 location_t loc = OMP_CLAUSE_LOCATION (clause);
3392 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3394 case PLUS_EXPR:
3395 case MINUS_EXPR:
3396 case BIT_IOR_EXPR:
3397 case BIT_XOR_EXPR:
3398 case TRUTH_OR_EXPR:
3399 case TRUTH_ORIF_EXPR:
3400 case TRUTH_XOR_EXPR:
3401 case NE_EXPR:
3402 return build_zero_cst (type);
3404 case MULT_EXPR:
3405 case TRUTH_AND_EXPR:
3406 case TRUTH_ANDIF_EXPR:
3407 case EQ_EXPR:
3408 return fold_convert_loc (loc, type, integer_one_node);
3410 case BIT_AND_EXPR:
3411 return fold_convert_loc (loc, type, integer_minus_one_node);
3413 case MAX_EXPR:
3414 if (SCALAR_FLOAT_TYPE_P (type))
3416 REAL_VALUE_TYPE max, min;
3417 if (HONOR_INFINITIES (type))
3419 real_inf (&max);
3420 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3422 else
3423 real_maxval (&min, 1, TYPE_MODE (type));
3424 return build_real (type, min);
3426 else
3428 gcc_assert (INTEGRAL_TYPE_P (type));
3429 return TYPE_MIN_VALUE (type);
3432 case MIN_EXPR:
3433 if (SCALAR_FLOAT_TYPE_P (type))
3435 REAL_VALUE_TYPE max;
3436 if (HONOR_INFINITIES (type))
3437 real_inf (&max);
3438 else
3439 real_maxval (&max, 0, TYPE_MODE (type));
3440 return build_real (type, max);
3442 else
3444 gcc_assert (INTEGRAL_TYPE_P (type));
3445 return TYPE_MAX_VALUE (type);
3448 default:
3449 gcc_unreachable ();
3453 /* Return alignment to be assumed for var in CLAUSE, which should be
3454 OMP_CLAUSE_ALIGNED. */
3456 static tree
3457 omp_clause_aligned_alignment (tree clause)
3459 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3460 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3462 /* Otherwise return implementation defined alignment. */
3463 unsigned int al = 1;
3464 machine_mode mode, vmode;
3465 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3466 if (vs)
3467 vs = 1 << floor_log2 (vs);
3468 static enum mode_class classes[]
3469 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3470 for (int i = 0; i < 4; i += 2)
3471 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3472 mode != VOIDmode;
3473 mode = GET_MODE_WIDER_MODE (mode))
3475 vmode = targetm.vectorize.preferred_simd_mode (mode);
3476 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3477 continue;
3478 while (vs
3479 && GET_MODE_SIZE (vmode) < vs
3480 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3481 vmode = GET_MODE_2XWIDER_MODE (vmode);
3483 tree type = lang_hooks.types.type_for_mode (mode, 1);
3484 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3485 continue;
3486 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3487 / GET_MODE_SIZE (mode));
3488 if (TYPE_MODE (type) != vmode)
3489 continue;
3490 if (TYPE_ALIGN_UNIT (type) > al)
3491 al = TYPE_ALIGN_UNIT (type);
3493 return build_int_cst (integer_type_node, al);
3496 /* Return maximum possible vectorization factor for the target. */
3498 static int
3499 omp_max_vf (void)
3501 if (!optimize
3502 || optimize_debug
3503 || !flag_tree_loop_optimize
3504 || (!flag_tree_loop_vectorize
3505 && (global_options_set.x_flag_tree_loop_vectorize
3506 || global_options_set.x_flag_tree_vectorize)))
3507 return 1;
3509 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3510 if (vs)
3512 vs = 1 << floor_log2 (vs);
3513 return vs;
3515 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3516 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3517 return GET_MODE_NUNITS (vqimode);
3518 return 1;
3521 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3522 privatization. */
3524 static bool
3525 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3526 tree &idx, tree &lane, tree &ivar, tree &lvar)
3528 if (max_vf == 0)
3530 max_vf = omp_max_vf ();
3531 if (max_vf > 1)
3533 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3534 OMP_CLAUSE_SAFELEN);
3535 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3536 max_vf = 1;
3537 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3538 max_vf) == -1)
3539 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3541 if (max_vf > 1)
3543 idx = create_tmp_var (unsigned_type_node);
3544 lane = create_tmp_var (unsigned_type_node);
3547 if (max_vf == 1)
3548 return false;
3550 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3551 tree avar = create_tmp_var_raw (atype);
3552 if (TREE_ADDRESSABLE (new_var))
3553 TREE_ADDRESSABLE (avar) = 1;
3554 DECL_ATTRIBUTES (avar)
3555 = tree_cons (get_identifier ("omp simd array"), NULL,
3556 DECL_ATTRIBUTES (avar));
3557 gimple_add_tmp_var (avar);
3558 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3559 NULL_TREE, NULL_TREE);
3560 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3561 NULL_TREE, NULL_TREE);
3562 if (DECL_P (new_var))
3564 SET_DECL_VALUE_EXPR (new_var, lvar);
3565 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3567 return true;
3570 /* Helper function of lower_rec_input_clauses. For a reference
3571 in simd reduction, add an underlying variable it will reference. */
3573 static void
3574 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3576 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3577 if (TREE_CONSTANT (z))
3579 const char *name = NULL;
3580 if (DECL_NAME (new_vard))
3581 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3583 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3584 gimple_add_tmp_var (z);
3585 TREE_ADDRESSABLE (z) = 1;
3586 z = build_fold_addr_expr_loc (loc, z);
3587 gimplify_assign (new_vard, z, ilist);
3591 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3592 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3593 private variables. Initialization statements go in ILIST, while calls
3594 to destructors go in DLIST. */
3596 static void
3597 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3598 omp_context *ctx, struct omp_for_data *fd)
3600 tree c, dtor, copyin_seq, x, ptr;
3601 bool copyin_by_ref = false;
3602 bool lastprivate_firstprivate = false;
3603 bool reduction_omp_orig_ref = false;
3604 int pass;
3605 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3606 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3607 int max_vf = 0;
3608 tree lane = NULL_TREE, idx = NULL_TREE;
3609 tree ivar = NULL_TREE, lvar = NULL_TREE;
3610 gimple_seq llist[2] = { NULL, NULL };
3612 copyin_seq = NULL;
3614 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3615 with data sharing clauses referencing variable sized vars. That
3616 is unnecessarily hard to support and very unlikely to result in
3617 vectorized code anyway. */
3618 if (is_simd)
3619 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3620 switch (OMP_CLAUSE_CODE (c))
3622 case OMP_CLAUSE_LINEAR:
3623 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3624 max_vf = 1;
3625 /* FALLTHRU */
3626 case OMP_CLAUSE_REDUCTION:
3627 case OMP_CLAUSE_PRIVATE:
3628 case OMP_CLAUSE_FIRSTPRIVATE:
3629 case OMP_CLAUSE_LASTPRIVATE:
3630 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3631 max_vf = 1;
3632 break;
3633 default:
3634 continue;
3637 /* Do all the fixed sized types in the first pass, and the variable sized
3638 types in the second pass. This makes sure that the scalar arguments to
3639 the variable sized types are processed before we use them in the
3640 variable sized operations. */
3641 for (pass = 0; pass < 2; ++pass)
3643 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3645 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3646 tree var, new_var;
3647 bool by_ref;
3648 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3650 switch (c_kind)
3652 case OMP_CLAUSE_PRIVATE:
3653 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3654 continue;
3655 break;
3656 case OMP_CLAUSE_SHARED:
3657 /* Ignore shared directives in teams construct. */
3658 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3659 continue;
3660 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3662 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3663 continue;
3665 case OMP_CLAUSE_FIRSTPRIVATE:
3666 case OMP_CLAUSE_COPYIN:
3667 case OMP_CLAUSE_LINEAR:
3668 break;
3669 case OMP_CLAUSE_REDUCTION:
3670 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3671 reduction_omp_orig_ref = true;
3672 break;
3673 case OMP_CLAUSE__LOOPTEMP_:
3674 /* Handle _looptemp_ clauses only on parallel. */
3675 if (fd)
3676 continue;
3677 break;
3678 case OMP_CLAUSE_LASTPRIVATE:
3679 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3681 lastprivate_firstprivate = true;
3682 if (pass != 0)
3683 continue;
3685 /* Even without corresponding firstprivate, if
3686 decl is Fortran allocatable, it needs outer var
3687 reference. */
3688 else if (pass == 0
3689 && lang_hooks.decls.omp_private_outer_ref
3690 (OMP_CLAUSE_DECL (c)))
3691 lastprivate_firstprivate = true;
3692 break;
3693 case OMP_CLAUSE_ALIGNED:
3694 if (pass == 0)
3695 continue;
3696 var = OMP_CLAUSE_DECL (c);
3697 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3698 && !is_global_var (var))
3700 new_var = maybe_lookup_decl (var, ctx);
3701 if (new_var == NULL_TREE)
3702 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3703 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3704 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3705 omp_clause_aligned_alignment (c));
3706 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3707 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3708 gimplify_and_add (x, ilist);
3710 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3711 && is_global_var (var))
3713 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3714 new_var = lookup_decl (var, ctx);
3715 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3716 t = build_fold_addr_expr_loc (clause_loc, t);
3717 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3718 t = build_call_expr_loc (clause_loc, t2, 2, t,
3719 omp_clause_aligned_alignment (c));
3720 t = fold_convert_loc (clause_loc, ptype, t);
3721 x = create_tmp_var (ptype);
3722 t = build2 (MODIFY_EXPR, ptype, x, t);
3723 gimplify_and_add (t, ilist);
3724 t = build_simple_mem_ref_loc (clause_loc, x);
3725 SET_DECL_VALUE_EXPR (new_var, t);
3726 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3728 continue;
3729 default:
3730 continue;
3733 new_var = var = OMP_CLAUSE_DECL (c);
3734 if (c_kind != OMP_CLAUSE_COPYIN)
3735 new_var = lookup_decl (var, ctx);
3737 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3739 if (pass != 0)
3740 continue;
3742 else if (is_variable_sized (var))
3744 /* For variable sized types, we need to allocate the
3745 actual storage here. Call alloca and store the
3746 result in the pointer decl that we created elsewhere. */
3747 if (pass == 0)
3748 continue;
3750 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3752 gcall *stmt;
3753 tree tmp, atmp;
3755 ptr = DECL_VALUE_EXPR (new_var);
3756 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3757 ptr = TREE_OPERAND (ptr, 0);
3758 gcc_assert (DECL_P (ptr));
3759 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3761 /* void *tmp = __builtin_alloca */
3762 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3763 stmt = gimple_build_call (atmp, 1, x);
3764 tmp = create_tmp_var_raw (ptr_type_node);
3765 gimple_add_tmp_var (tmp);
3766 gimple_call_set_lhs (stmt, tmp);
3768 gimple_seq_add_stmt (ilist, stmt);
3770 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3771 gimplify_assign (ptr, x, ilist);
3774 else if (is_reference (var))
3776 /* For references that are being privatized for Fortran,
3777 allocate new backing storage for the new pointer
3778 variable. This allows us to avoid changing all the
3779 code that expects a pointer to something that expects
3780 a direct variable. */
3781 if (pass == 0)
3782 continue;
3784 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3785 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3787 x = build_receiver_ref (var, false, ctx);
3788 x = build_fold_addr_expr_loc (clause_loc, x);
3790 else if (TREE_CONSTANT (x))
3792 /* For reduction in SIMD loop, defer adding the
3793 initialization of the reference, because if we decide
3794 to use SIMD array for it, the initilization could cause
3795 expansion ICE. */
3796 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3797 x = NULL_TREE;
3798 else
3800 const char *name = NULL;
3801 if (DECL_NAME (var))
3802 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3804 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3805 name);
3806 gimple_add_tmp_var (x);
3807 TREE_ADDRESSABLE (x) = 1;
3808 x = build_fold_addr_expr_loc (clause_loc, x);
3811 else
3813 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3814 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3817 if (x)
3819 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3820 gimplify_assign (new_var, x, ilist);
3823 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3825 else if (c_kind == OMP_CLAUSE_REDUCTION
3826 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3828 if (pass == 0)
3829 continue;
3831 else if (pass != 0)
3832 continue;
3834 switch (OMP_CLAUSE_CODE (c))
3836 case OMP_CLAUSE_SHARED:
3837 /* Ignore shared directives in teams construct. */
3838 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3839 continue;
3840 /* Shared global vars are just accessed directly. */
3841 if (is_global_var (new_var))
3842 break;
3843 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3844 needs to be delayed until after fixup_child_record_type so
3845 that we get the correct type during the dereference. */
3846 by_ref = use_pointer_for_field (var, ctx);
3847 x = build_receiver_ref (var, by_ref, ctx);
3848 SET_DECL_VALUE_EXPR (new_var, x);
3849 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3851 /* ??? If VAR is not passed by reference, and the variable
3852 hasn't been initialized yet, then we'll get a warning for
3853 the store into the omp_data_s structure. Ideally, we'd be
3854 able to notice this and not store anything at all, but
3855 we're generating code too early. Suppress the warning. */
3856 if (!by_ref)
3857 TREE_NO_WARNING (var) = 1;
3858 break;
3860 case OMP_CLAUSE_LASTPRIVATE:
3861 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3862 break;
3863 /* FALLTHRU */
3865 case OMP_CLAUSE_PRIVATE:
3866 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3867 x = build_outer_var_ref (var, ctx);
3868 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3870 if (is_task_ctx (ctx))
3871 x = build_receiver_ref (var, false, ctx);
3872 else
3873 x = build_outer_var_ref (var, ctx);
3875 else
3876 x = NULL;
3877 do_private:
3878 tree nx;
3879 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3880 if (is_simd)
3882 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3883 if ((TREE_ADDRESSABLE (new_var) || nx || y
3884 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3885 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3886 idx, lane, ivar, lvar))
3888 if (nx)
3889 x = lang_hooks.decls.omp_clause_default_ctor
3890 (c, unshare_expr (ivar), x);
3891 if (nx && x)
3892 gimplify_and_add (x, &llist[0]);
3893 if (y)
3895 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3896 if (y)
3898 gimple_seq tseq = NULL;
3900 dtor = y;
3901 gimplify_stmt (&dtor, &tseq);
3902 gimple_seq_add_seq (&llist[1], tseq);
3905 break;
3908 if (nx)
3909 gimplify_and_add (nx, ilist);
3910 /* FALLTHRU */
3912 do_dtor:
3913 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3914 if (x)
3916 gimple_seq tseq = NULL;
3918 dtor = x;
3919 gimplify_stmt (&dtor, &tseq);
3920 gimple_seq_add_seq (dlist, tseq);
3922 break;
3924 case OMP_CLAUSE_LINEAR:
3925 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3926 goto do_firstprivate;
3927 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3928 x = NULL;
3929 else
3930 x = build_outer_var_ref (var, ctx);
3931 goto do_private;
3933 case OMP_CLAUSE_FIRSTPRIVATE:
3934 if (is_task_ctx (ctx))
3936 if (is_reference (var) || is_variable_sized (var))
3937 goto do_dtor;
3938 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3939 ctx))
3940 || use_pointer_for_field (var, NULL))
3942 x = build_receiver_ref (var, false, ctx);
3943 SET_DECL_VALUE_EXPR (new_var, x);
3944 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3945 goto do_dtor;
3948 do_firstprivate:
3949 x = build_outer_var_ref (var, ctx);
3950 if (is_simd)
3952 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3953 && gimple_omp_for_combined_into_p (ctx->stmt))
3955 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3956 tree stept = TREE_TYPE (t);
3957 tree ct = find_omp_clause (clauses,
3958 OMP_CLAUSE__LOOPTEMP_);
3959 gcc_assert (ct);
3960 tree l = OMP_CLAUSE_DECL (ct);
3961 tree n1 = fd->loop.n1;
3962 tree step = fd->loop.step;
3963 tree itype = TREE_TYPE (l);
3964 if (POINTER_TYPE_P (itype))
3965 itype = signed_type_for (itype);
3966 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3967 if (TYPE_UNSIGNED (itype)
3968 && fd->loop.cond_code == GT_EXPR)
3969 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3970 fold_build1 (NEGATE_EXPR, itype, l),
3971 fold_build1 (NEGATE_EXPR,
3972 itype, step));
3973 else
3974 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3975 t = fold_build2 (MULT_EXPR, stept,
3976 fold_convert (stept, l), t);
3978 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3980 x = lang_hooks.decls.omp_clause_linear_ctor
3981 (c, new_var, x, t);
3982 gimplify_and_add (x, ilist);
3983 goto do_dtor;
3986 if (POINTER_TYPE_P (TREE_TYPE (x)))
3987 x = fold_build2 (POINTER_PLUS_EXPR,
3988 TREE_TYPE (x), x, t);
3989 else
3990 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3993 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3994 || TREE_ADDRESSABLE (new_var))
3995 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3996 idx, lane, ivar, lvar))
3998 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4000 tree iv = create_tmp_var (TREE_TYPE (new_var));
4001 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4002 gimplify_and_add (x, ilist);
4003 gimple_stmt_iterator gsi
4004 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4005 gassign *g
4006 = gimple_build_assign (unshare_expr (lvar), iv);
4007 gsi_insert_before_without_update (&gsi, g,
4008 GSI_SAME_STMT);
4009 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4010 enum tree_code code = PLUS_EXPR;
4011 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4012 code = POINTER_PLUS_EXPR;
4013 g = gimple_build_assign (iv, code, iv, t);
4014 gsi_insert_before_without_update (&gsi, g,
4015 GSI_SAME_STMT);
4016 break;
4018 x = lang_hooks.decls.omp_clause_copy_ctor
4019 (c, unshare_expr (ivar), x);
4020 gimplify_and_add (x, &llist[0]);
4021 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4022 if (x)
4024 gimple_seq tseq = NULL;
4026 dtor = x;
4027 gimplify_stmt (&dtor, &tseq);
4028 gimple_seq_add_seq (&llist[1], tseq);
4030 break;
4033 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4034 gimplify_and_add (x, ilist);
4035 goto do_dtor;
4037 case OMP_CLAUSE__LOOPTEMP_:
4038 gcc_assert (is_parallel_ctx (ctx));
4039 x = build_outer_var_ref (var, ctx);
4040 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4041 gimplify_and_add (x, ilist);
4042 break;
4044 case OMP_CLAUSE_COPYIN:
4045 by_ref = use_pointer_for_field (var, NULL);
4046 x = build_receiver_ref (var, by_ref, ctx);
4047 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4048 append_to_statement_list (x, &copyin_seq);
4049 copyin_by_ref |= by_ref;
4050 break;
4052 case OMP_CLAUSE_REDUCTION:
4053 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4055 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4056 gimple tseq;
4057 x = build_outer_var_ref (var, ctx);
4059 if (is_reference (var)
4060 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4061 TREE_TYPE (x)))
4062 x = build_fold_addr_expr_loc (clause_loc, x);
4063 SET_DECL_VALUE_EXPR (placeholder, x);
4064 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4065 tree new_vard = new_var;
4066 if (is_reference (var))
4068 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4069 new_vard = TREE_OPERAND (new_var, 0);
4070 gcc_assert (DECL_P (new_vard));
4072 if (is_simd
4073 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4074 idx, lane, ivar, lvar))
4076 if (new_vard == new_var)
4078 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4079 SET_DECL_VALUE_EXPR (new_var, ivar);
4081 else
4083 SET_DECL_VALUE_EXPR (new_vard,
4084 build_fold_addr_expr (ivar));
4085 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4087 x = lang_hooks.decls.omp_clause_default_ctor
4088 (c, unshare_expr (ivar),
4089 build_outer_var_ref (var, ctx));
4090 if (x)
4091 gimplify_and_add (x, &llist[0]);
4092 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4094 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4095 lower_omp (&tseq, ctx);
4096 gimple_seq_add_seq (&llist[0], tseq);
4098 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4099 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4100 lower_omp (&tseq, ctx);
4101 gimple_seq_add_seq (&llist[1], tseq);
4102 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4103 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4104 if (new_vard == new_var)
4105 SET_DECL_VALUE_EXPR (new_var, lvar);
4106 else
4107 SET_DECL_VALUE_EXPR (new_vard,
4108 build_fold_addr_expr (lvar));
4109 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4110 if (x)
4112 tseq = NULL;
4113 dtor = x;
4114 gimplify_stmt (&dtor, &tseq);
4115 gimple_seq_add_seq (&llist[1], tseq);
4117 break;
4119 /* If this is a reference to constant size reduction var
4120 with placeholder, we haven't emitted the initializer
4121 for it because it is undesirable if SIMD arrays are used.
4122 But if they aren't used, we need to emit the deferred
4123 initialization now. */
4124 else if (is_reference (var) && is_simd)
4125 handle_simd_reference (clause_loc, new_vard, ilist);
4126 x = lang_hooks.decls.omp_clause_default_ctor
4127 (c, unshare_expr (new_var),
4128 build_outer_var_ref (var, ctx));
4129 if (x)
4130 gimplify_and_add (x, ilist);
4131 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4133 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4134 lower_omp (&tseq, ctx);
4135 gimple_seq_add_seq (ilist, tseq);
4137 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4138 if (is_simd)
4140 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4141 lower_omp (&tseq, ctx);
4142 gimple_seq_add_seq (dlist, tseq);
4143 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4145 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4146 goto do_dtor;
4148 else
4150 x = omp_reduction_init (c, TREE_TYPE (new_var));
4151 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4152 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4154 /* reduction(-:var) sums up the partial results, so it
4155 acts identically to reduction(+:var). */
4156 if (code == MINUS_EXPR)
4157 code = PLUS_EXPR;
4159 tree new_vard = new_var;
4160 if (is_simd && is_reference (var))
4162 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4163 new_vard = TREE_OPERAND (new_var, 0);
4164 gcc_assert (DECL_P (new_vard));
4166 if (is_simd
4167 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4168 idx, lane, ivar, lvar))
4170 tree ref = build_outer_var_ref (var, ctx);
4172 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4174 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4175 ref = build_outer_var_ref (var, ctx);
4176 gimplify_assign (ref, x, &llist[1]);
4178 if (new_vard != new_var)
4180 SET_DECL_VALUE_EXPR (new_vard,
4181 build_fold_addr_expr (lvar));
4182 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4185 else
4187 if (is_reference (var) && is_simd)
4188 handle_simd_reference (clause_loc, new_vard, ilist);
4189 gimplify_assign (new_var, x, ilist);
4190 if (is_simd)
4192 tree ref = build_outer_var_ref (var, ctx);
4194 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4195 ref = build_outer_var_ref (var, ctx);
4196 gimplify_assign (ref, x, dlist);
4200 break;
4202 default:
4203 gcc_unreachable ();
4208 if (lane)
4210 tree uid = create_tmp_var (ptr_type_node, "simduid");
4211 /* Don't want uninit warnings on simduid, it is always uninitialized,
4212 but we use it not for the value, but for the DECL_UID only. */
4213 TREE_NO_WARNING (uid) = 1;
4214 gimple g
4215 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4216 gimple_call_set_lhs (g, lane);
4217 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4218 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4219 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4220 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4221 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4222 gimple_omp_for_set_clauses (ctx->stmt, c);
4223 g = gimple_build_assign (lane, INTEGER_CST,
4224 build_int_cst (unsigned_type_node, 0));
4225 gimple_seq_add_stmt (ilist, g);
4226 for (int i = 0; i < 2; i++)
4227 if (llist[i])
4229 tree vf = create_tmp_var (unsigned_type_node);
4230 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4231 gimple_call_set_lhs (g, vf);
4232 gimple_seq *seq = i == 0 ? ilist : dlist;
4233 gimple_seq_add_stmt (seq, g);
4234 tree t = build_int_cst (unsigned_type_node, 0);
4235 g = gimple_build_assign (idx, INTEGER_CST, t);
4236 gimple_seq_add_stmt (seq, g);
4237 tree body = create_artificial_label (UNKNOWN_LOCATION);
4238 tree header = create_artificial_label (UNKNOWN_LOCATION);
4239 tree end = create_artificial_label (UNKNOWN_LOCATION);
4240 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4241 gimple_seq_add_stmt (seq, gimple_build_label (body));
4242 gimple_seq_add_seq (seq, llist[i]);
4243 t = build_int_cst (unsigned_type_node, 1);
4244 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4245 gimple_seq_add_stmt (seq, g);
4246 gimple_seq_add_stmt (seq, gimple_build_label (header));
4247 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4248 gimple_seq_add_stmt (seq, g);
4249 gimple_seq_add_stmt (seq, gimple_build_label (end));
4253 /* The copyin sequence is not to be executed by the main thread, since
4254 that would result in self-copies. Perhaps not visible to scalars,
4255 but it certainly is to C++ operator=. */
4256 if (copyin_seq)
4258 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4260 x = build2 (NE_EXPR, boolean_type_node, x,
4261 build_int_cst (TREE_TYPE (x), 0));
4262 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4263 gimplify_and_add (x, ilist);
4266 /* If any copyin variable is passed by reference, we must ensure the
4267 master thread doesn't modify it before it is copied over in all
4268 threads. Similarly for variables in both firstprivate and
4269 lastprivate clauses we need to ensure the lastprivate copying
4270 happens after firstprivate copying in all threads. And similarly
4271 for UDRs if initializer expression refers to omp_orig. */
4272 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4274 /* Don't add any barrier for #pragma omp simd or
4275 #pragma omp distribute. */
4276 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4277 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4278 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4281 /* If max_vf is non-zero, then we can use only a vectorization factor
4282 up to the max_vf we chose. So stick it into the safelen clause. */
4283 if (max_vf)
4285 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4286 OMP_CLAUSE_SAFELEN);
4287 if (c == NULL_TREE
4288 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4289 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4290 max_vf) == 1))
4292 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4293 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4294 max_vf);
4295 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4296 gimple_omp_for_set_clauses (ctx->stmt, c);
4302 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4303 both parallel and workshare constructs. PREDICATE may be NULL if it's
4304 always true. */
4306 static void
4307 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4308 omp_context *ctx)
4310 tree x, c, label = NULL, orig_clauses = clauses;
4311 bool par_clauses = false;
4312 tree simduid = NULL, lastlane = NULL;
4314 /* Early exit if there are no lastprivate or linear clauses. */
4315 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4316 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4317 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4318 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4319 break;
4320 if (clauses == NULL)
4322 /* If this was a workshare clause, see if it had been combined
4323 with its parallel. In that case, look for the clauses on the
4324 parallel statement itself. */
4325 if (is_parallel_ctx (ctx))
4326 return;
4328 ctx = ctx->outer;
4329 if (ctx == NULL || !is_parallel_ctx (ctx))
4330 return;
4332 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4333 OMP_CLAUSE_LASTPRIVATE);
4334 if (clauses == NULL)
4335 return;
4336 par_clauses = true;
4339 if (predicate)
4341 gcond *stmt;
4342 tree label_true, arm1, arm2;
4344 label = create_artificial_label (UNKNOWN_LOCATION);
4345 label_true = create_artificial_label (UNKNOWN_LOCATION);
4346 arm1 = TREE_OPERAND (predicate, 0);
4347 arm2 = TREE_OPERAND (predicate, 1);
4348 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4349 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4350 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4351 label_true, label);
4352 gimple_seq_add_stmt (stmt_list, stmt);
4353 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4356 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4357 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4359 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4360 if (simduid)
4361 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4364 for (c = clauses; c ;)
4366 tree var, new_var;
4367 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4369 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4370 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4371 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4373 var = OMP_CLAUSE_DECL (c);
4374 new_var = lookup_decl (var, ctx);
4376 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4378 tree val = DECL_VALUE_EXPR (new_var);
4379 if (TREE_CODE (val) == ARRAY_REF
4380 && VAR_P (TREE_OPERAND (val, 0))
4381 && lookup_attribute ("omp simd array",
4382 DECL_ATTRIBUTES (TREE_OPERAND (val,
4383 0))))
4385 if (lastlane == NULL)
4387 lastlane = create_tmp_var (unsigned_type_node);
4388 gcall *g
4389 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4390 2, simduid,
4391 TREE_OPERAND (val, 1));
4392 gimple_call_set_lhs (g, lastlane);
4393 gimple_seq_add_stmt (stmt_list, g);
4395 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4396 TREE_OPERAND (val, 0), lastlane,
4397 NULL_TREE, NULL_TREE);
4401 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4402 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4404 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4405 gimple_seq_add_seq (stmt_list,
4406 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4407 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4409 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4410 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4412 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4413 gimple_seq_add_seq (stmt_list,
4414 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4415 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4418 x = build_outer_var_ref (var, ctx);
4419 if (is_reference (var))
4420 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4421 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4422 gimplify_and_add (x, stmt_list);
4424 c = OMP_CLAUSE_CHAIN (c);
4425 if (c == NULL && !par_clauses)
4427 /* If this was a workshare clause, see if it had been combined
4428 with its parallel. In that case, continue looking for the
4429 clauses also on the parallel statement itself. */
4430 if (is_parallel_ctx (ctx))
4431 break;
4433 ctx = ctx->outer;
4434 if (ctx == NULL || !is_parallel_ctx (ctx))
4435 break;
4437 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4438 OMP_CLAUSE_LASTPRIVATE);
4439 par_clauses = true;
4443 if (label)
4444 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4447 static void
4448 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4449 tree tid, tree var, tree new_var)
4451 /* The atomic add at the end of the sum creates unnecessary
4452 write contention on accelerators. To work around this,
4453 create an array to store the partial reductions. Later, in
4454 lower_omp_for (for openacc), the values of array will be
4455 combined. */
4457 tree t = NULL_TREE, array, x;
4458 tree type = get_base_type (var);
4459 gimple stmt;
4461 /* Now insert the partial reductions into the array. */
4463 /* Find the reduction array. */
4465 tree ptype = build_pointer_type (type);
4467 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4468 t = build_receiver_ref (t, false, ctx->outer);
4470 array = create_tmp_var (ptype);
4471 gimplify_assign (array, t, stmt_seqp);
4473 tree ptr = create_tmp_var (TREE_TYPE (array));
4475 /* Find the reduction array. */
4477 /* testing a unary conversion. */
4478 tree offset = create_tmp_var (sizetype);
4479 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4480 stmt_seqp);
4481 t = create_tmp_var (sizetype);
4482 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4483 stmt_seqp);
4484 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4485 gimple_seq_add_stmt (stmt_seqp, stmt);
4487 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4488 of adding sizeof(var) to the array? */
4489 ptr = create_tmp_var (ptype);
4490 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4491 offset);
4492 gimple_seq_add_stmt (stmt_seqp, stmt);
4494 /* Move the local sum to gfc$sum[i]. */
4495 x = unshare_expr (build_simple_mem_ref (ptr));
4496 stmt = gimplify_assign (x, new_var, stmt_seqp);
4499 /* Generate code to implement the REDUCTION clauses. */
4501 static void
4502 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4504 gimple_seq sub_seq = NULL;
4505 gimple stmt;
4506 tree x, c, tid = NULL_TREE;
4507 int count = 0;
4509 /* SIMD reductions are handled in lower_rec_input_clauses. */
4510 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4511 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4512 return;
4514 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4515 update in that case, otherwise use a lock. */
4516 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4517 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4519 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4521 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4522 count = -1;
4523 break;
4525 count++;
4528 if (count == 0)
4529 return;
4531 /* Initialize thread info for OpenACC. */
4532 if (is_gimple_omp_oacc (ctx->stmt))
4534 /* Get the current thread id. */
4535 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4536 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4537 gimple stmt = gimple_build_call (call, 0);
4538 gimple_call_set_lhs (stmt, tid);
4539 gimple_seq_add_stmt (stmt_seqp, stmt);
4542 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4544 tree var, ref, new_var;
4545 enum tree_code code;
4546 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4548 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4549 continue;
4551 var = OMP_CLAUSE_DECL (c);
4552 new_var = lookup_decl (var, ctx);
4553 if (is_reference (var))
4554 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4555 ref = build_outer_var_ref (var, ctx);
4556 code = OMP_CLAUSE_REDUCTION_CODE (c);
4558 /* reduction(-:var) sums up the partial results, so it acts
4559 identically to reduction(+:var). */
4560 if (code == MINUS_EXPR)
4561 code = PLUS_EXPR;
4563 if (is_gimple_omp_oacc (ctx->stmt))
4565 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4567 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4569 else if (count == 1)
4571 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4573 addr = save_expr (addr);
4574 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4575 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4576 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4577 gimplify_and_add (x, stmt_seqp);
4578 return;
4580 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4582 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4584 if (is_reference (var)
4585 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4586 TREE_TYPE (ref)))
4587 ref = build_fold_addr_expr_loc (clause_loc, ref);
4588 SET_DECL_VALUE_EXPR (placeholder, ref);
4589 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4590 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4591 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4592 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4593 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4595 else
4597 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4598 ref = build_outer_var_ref (var, ctx);
4599 gimplify_assign (ref, x, &sub_seq);
4603 if (is_gimple_omp_oacc (ctx->stmt))
4604 return;
4606 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4608 gimple_seq_add_stmt (stmt_seqp, stmt);
4610 gimple_seq_add_seq (stmt_seqp, sub_seq);
4612 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4614 gimple_seq_add_stmt (stmt_seqp, stmt);
4618 /* Generate code to implement the COPYPRIVATE clauses. */
4620 static void
4621 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4622 omp_context *ctx)
4624 tree c;
4626 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4628 tree var, new_var, ref, x;
4629 bool by_ref;
4630 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4632 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4633 continue;
4635 var = OMP_CLAUSE_DECL (c);
4636 by_ref = use_pointer_for_field (var, NULL);
4638 ref = build_sender_ref (var, ctx);
4639 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4640 if (by_ref)
4642 x = build_fold_addr_expr_loc (clause_loc, new_var);
4643 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4645 gimplify_assign (ref, x, slist);
4647 ref = build_receiver_ref (var, false, ctx);
4648 if (by_ref)
4650 ref = fold_convert_loc (clause_loc,
4651 build_pointer_type (TREE_TYPE (new_var)),
4652 ref);
4653 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4655 if (is_reference (var))
4657 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4658 ref = build_simple_mem_ref_loc (clause_loc, ref);
4659 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4661 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4662 gimplify_and_add (x, rlist);
4667 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4668 and REDUCTION from the sender (aka parent) side. */
4670 static void
4671 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4672 omp_context *ctx)
4674 tree c;
4676 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4678 tree val, ref, x, var;
4679 bool by_ref, do_in = false, do_out = false;
4680 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4682 switch (OMP_CLAUSE_CODE (c))
4684 case OMP_CLAUSE_PRIVATE:
4685 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4686 break;
4687 continue;
4688 case OMP_CLAUSE_FIRSTPRIVATE:
4689 case OMP_CLAUSE_COPYIN:
4690 case OMP_CLAUSE_LASTPRIVATE:
4691 case OMP_CLAUSE_REDUCTION:
4692 case OMP_CLAUSE__LOOPTEMP_:
4693 break;
4694 default:
4695 continue;
4698 val = OMP_CLAUSE_DECL (c);
4699 var = lookup_decl_in_outer_ctx (val, ctx);
4701 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4702 && is_global_var (var))
4703 continue;
4704 if (is_variable_sized (val))
4705 continue;
4706 by_ref = use_pointer_for_field (val, NULL);
4708 switch (OMP_CLAUSE_CODE (c))
4710 case OMP_CLAUSE_PRIVATE:
4711 case OMP_CLAUSE_FIRSTPRIVATE:
4712 case OMP_CLAUSE_COPYIN:
4713 case OMP_CLAUSE__LOOPTEMP_:
4714 do_in = true;
4715 break;
4717 case OMP_CLAUSE_LASTPRIVATE:
4718 if (by_ref || is_reference (val))
4720 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4721 continue;
4722 do_in = true;
4724 else
4726 do_out = true;
4727 if (lang_hooks.decls.omp_private_outer_ref (val))
4728 do_in = true;
4730 break;
4732 case OMP_CLAUSE_REDUCTION:
4733 do_in = true;
4734 do_out = !(by_ref || is_reference (val));
4735 break;
4737 default:
4738 gcc_unreachable ();
4741 if (do_in)
4743 ref = build_sender_ref (val, ctx);
4744 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4745 gimplify_assign (ref, x, ilist);
4746 if (is_task_ctx (ctx))
4747 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4750 if (do_out)
4752 ref = build_sender_ref (val, ctx);
4753 gimplify_assign (var, ref, olist);
4758 /* Generate code to implement SHARED from the sender (aka parent)
4759 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4760 list things that got automatically shared. */
4762 static void
4763 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4765 tree var, ovar, nvar, f, x, record_type;
4767 if (ctx->record_type == NULL)
4768 return;
4770 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4771 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4773 ovar = DECL_ABSTRACT_ORIGIN (f);
4774 nvar = maybe_lookup_decl (ovar, ctx);
4775 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4776 continue;
4778 /* If CTX is a nested parallel directive. Find the immediately
4779 enclosing parallel or workshare construct that contains a
4780 mapping for OVAR. */
4781 var = lookup_decl_in_outer_ctx (ovar, ctx);
4783 if (use_pointer_for_field (ovar, ctx))
4785 x = build_sender_ref (ovar, ctx);
4786 var = build_fold_addr_expr (var);
4787 gimplify_assign (x, var, ilist);
4789 else
4791 x = build_sender_ref (ovar, ctx);
4792 gimplify_assign (x, var, ilist);
4794 if (!TREE_READONLY (var)
4795 /* We don't need to receive a new reference to a result
4796 or parm decl. In fact we may not store to it as we will
4797 invalidate any pending RSO and generate wrong gimple
4798 during inlining. */
4799 && !((TREE_CODE (var) == RESULT_DECL
4800 || TREE_CODE (var) == PARM_DECL)
4801 && DECL_BY_REFERENCE (var)))
4803 x = build_sender_ref (ovar, ctx);
4804 gimplify_assign (var, x, olist);
4811 /* A convenience function to build an empty GIMPLE_COND with just the
4812 condition. */
4814 static gcond *
4815 gimple_build_cond_empty (tree cond)
4817 enum tree_code pred_code;
4818 tree lhs, rhs;
4820 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4821 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4825 /* Build the function calls to GOMP_parallel_start etc to actually
4826 generate the parallel operation. REGION is the parallel region
4827 being expanded. BB is the block where to insert the code. WS_ARGS
4828 will be set if this is a call to a combined parallel+workshare
4829 construct, it contains the list of additional arguments needed by
4830 the workshare construct. */
4832 static void
4833 expand_parallel_call (struct omp_region *region, basic_block bb,
4834 gomp_parallel *entry_stmt,
4835 vec<tree, va_gc> *ws_args)
4837 tree t, t1, t2, val, cond, c, clauses, flags;
4838 gimple_stmt_iterator gsi;
4839 gimple stmt;
4840 enum built_in_function start_ix;
4841 int start_ix2;
4842 location_t clause_loc;
4843 vec<tree, va_gc> *args;
4845 clauses = gimple_omp_parallel_clauses (entry_stmt);
4847 /* Determine what flavor of GOMP_parallel we will be
4848 emitting. */
4849 start_ix = BUILT_IN_GOMP_PARALLEL;
4850 if (is_combined_parallel (region))
4852 switch (region->inner->type)
4854 case GIMPLE_OMP_FOR:
4855 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4856 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4857 + (region->inner->sched_kind
4858 == OMP_CLAUSE_SCHEDULE_RUNTIME
4859 ? 3 : region->inner->sched_kind));
4860 start_ix = (enum built_in_function)start_ix2;
4861 break;
4862 case GIMPLE_OMP_SECTIONS:
4863 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4864 break;
4865 default:
4866 gcc_unreachable ();
4870 /* By default, the value of NUM_THREADS is zero (selected at run time)
4871 and there is no conditional. */
4872 cond = NULL_TREE;
4873 val = build_int_cst (unsigned_type_node, 0);
4874 flags = build_int_cst (unsigned_type_node, 0);
4876 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4877 if (c)
4878 cond = OMP_CLAUSE_IF_EXPR (c);
4880 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4881 if (c)
4883 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4884 clause_loc = OMP_CLAUSE_LOCATION (c);
4886 else
4887 clause_loc = gimple_location (entry_stmt);
4889 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4890 if (c)
4891 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4893 /* Ensure 'val' is of the correct type. */
4894 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4896 /* If we found the clause 'if (cond)', build either
4897 (cond != 0) or (cond ? val : 1u). */
4898 if (cond)
4900 cond = gimple_boolify (cond);
4902 if (integer_zerop (val))
4903 val = fold_build2_loc (clause_loc,
4904 EQ_EXPR, unsigned_type_node, cond,
4905 build_int_cst (TREE_TYPE (cond), 0));
4906 else
4908 basic_block cond_bb, then_bb, else_bb;
4909 edge e, e_then, e_else;
4910 tree tmp_then, tmp_else, tmp_join, tmp_var;
4912 tmp_var = create_tmp_var (TREE_TYPE (val));
4913 if (gimple_in_ssa_p (cfun))
4915 tmp_then = make_ssa_name (tmp_var);
4916 tmp_else = make_ssa_name (tmp_var);
4917 tmp_join = make_ssa_name (tmp_var);
4919 else
4921 tmp_then = tmp_var;
4922 tmp_else = tmp_var;
4923 tmp_join = tmp_var;
4926 e = split_block (bb, NULL);
4927 cond_bb = e->src;
4928 bb = e->dest;
4929 remove_edge (e);
4931 then_bb = create_empty_bb (cond_bb);
4932 else_bb = create_empty_bb (then_bb);
4933 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4934 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4936 stmt = gimple_build_cond_empty (cond);
4937 gsi = gsi_start_bb (cond_bb);
4938 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4940 gsi = gsi_start_bb (then_bb);
4941 stmt = gimple_build_assign (tmp_then, val);
4942 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4944 gsi = gsi_start_bb (else_bb);
4945 stmt = gimple_build_assign
4946 (tmp_else, build_int_cst (unsigned_type_node, 1));
4947 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4949 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4950 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4951 add_bb_to_loop (then_bb, cond_bb->loop_father);
4952 add_bb_to_loop (else_bb, cond_bb->loop_father);
4953 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4954 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4956 if (gimple_in_ssa_p (cfun))
4958 gphi *phi = create_phi_node (tmp_join, bb);
4959 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4960 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4963 val = tmp_join;
4966 gsi = gsi_start_bb (bb);
4967 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4968 false, GSI_CONTINUE_LINKING);
4971 gsi = gsi_last_bb (bb);
4972 t = gimple_omp_parallel_data_arg (entry_stmt);
4973 if (t == NULL)
4974 t1 = null_pointer_node;
4975 else
4976 t1 = build_fold_addr_expr (t);
4977 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4979 vec_alloc (args, 4 + vec_safe_length (ws_args));
4980 args->quick_push (t2);
4981 args->quick_push (t1);
4982 args->quick_push (val);
4983 if (ws_args)
4984 args->splice (*ws_args);
4985 args->quick_push (flags);
4987 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4988 builtin_decl_explicit (start_ix), args);
4990 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4991 false, GSI_CONTINUE_LINKING);
4994 /* Insert a function call whose name is FUNC_NAME with the information from
4995 ENTRY_STMT into the basic_block BB. */
4997 static void
4998 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
4999 vec <tree, va_gc> *ws_args)
5001 tree t, t1, t2;
5002 gimple_stmt_iterator gsi;
5003 vec <tree, va_gc> *args;
5005 gcc_assert (vec_safe_length (ws_args) == 2);
5006 tree func_name = (*ws_args)[0];
5007 tree grain = (*ws_args)[1];
5009 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5010 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5011 gcc_assert (count != NULL_TREE);
5012 count = OMP_CLAUSE_OPERAND (count, 0);
5014 gsi = gsi_last_bb (bb);
5015 t = gimple_omp_parallel_data_arg (entry_stmt);
5016 if (t == NULL)
5017 t1 = null_pointer_node;
5018 else
5019 t1 = build_fold_addr_expr (t);
5020 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5022 vec_alloc (args, 4);
5023 args->quick_push (t2);
5024 args->quick_push (t1);
5025 args->quick_push (count);
5026 args->quick_push (grain);
5027 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5029 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5030 GSI_CONTINUE_LINKING);
5033 /* Build the function call to GOMP_task to actually
5034 generate the task operation. BB is the block where to insert the code. */
5036 static void
5037 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5039 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5040 gimple_stmt_iterator gsi;
5041 location_t loc = gimple_location (entry_stmt);
5043 clauses = gimple_omp_task_clauses (entry_stmt);
5045 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5046 if (c)
5047 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5048 else
5049 cond = boolean_true_node;
5051 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5052 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5053 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5054 flags = build_int_cst (unsigned_type_node,
5055 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5057 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5058 if (c)
5060 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5061 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5062 build_int_cst (unsigned_type_node, 2),
5063 build_int_cst (unsigned_type_node, 0));
5064 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5066 if (depend)
5067 depend = OMP_CLAUSE_DECL (depend);
5068 else
5069 depend = build_int_cst (ptr_type_node, 0);
5071 gsi = gsi_last_bb (bb);
5072 t = gimple_omp_task_data_arg (entry_stmt);
5073 if (t == NULL)
5074 t2 = null_pointer_node;
5075 else
5076 t2 = build_fold_addr_expr_loc (loc, t);
5077 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5078 t = gimple_omp_task_copy_fn (entry_stmt);
5079 if (t == NULL)
5080 t3 = null_pointer_node;
5081 else
5082 t3 = build_fold_addr_expr_loc (loc, t);
5084 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5085 8, t1, t2, t3,
5086 gimple_omp_task_arg_size (entry_stmt),
5087 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5088 depend);
5090 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5091 false, GSI_CONTINUE_LINKING);
5095 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5096 catch handler and return it. This prevents programs from violating the
5097 structured block semantics with throws. */
5099 static gimple_seq
5100 maybe_catch_exception (gimple_seq body)
5102 gimple g;
5103 tree decl;
5105 if (!flag_exceptions)
5106 return body;
5108 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5109 decl = lang_hooks.eh_protect_cleanup_actions ();
5110 else
5111 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5113 g = gimple_build_eh_must_not_throw (decl);
5114 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5115 GIMPLE_TRY_CATCH);
5117 return gimple_seq_alloc_with_stmt (g);
5120 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5122 static tree
5123 vec2chain (vec<tree, va_gc> *v)
5125 tree chain = NULL_TREE, t;
5126 unsigned ix;
5128 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5130 DECL_CHAIN (t) = chain;
5131 chain = t;
5134 return chain;
5138 /* Remove barriers in REGION->EXIT's block. Note that this is only
5139 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5140 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5141 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5142 removed. */
5144 static void
5145 remove_exit_barrier (struct omp_region *region)
5147 gimple_stmt_iterator gsi;
5148 basic_block exit_bb;
5149 edge_iterator ei;
5150 edge e;
5151 gimple stmt;
5152 int any_addressable_vars = -1;
5154 exit_bb = region->exit;
5156 /* If the parallel region doesn't return, we don't have REGION->EXIT
5157 block at all. */
5158 if (! exit_bb)
5159 return;
5161 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5162 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5163 statements that can appear in between are extremely limited -- no
5164 memory operations at all. Here, we allow nothing at all, so the
5165 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5166 gsi = gsi_last_bb (exit_bb);
5167 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5168 gsi_prev (&gsi);
5169 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5170 return;
5172 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5174 gsi = gsi_last_bb (e->src);
5175 if (gsi_end_p (gsi))
5176 continue;
5177 stmt = gsi_stmt (gsi);
5178 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5179 && !gimple_omp_return_nowait_p (stmt))
5181 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5182 in many cases. If there could be tasks queued, the barrier
5183 might be needed to let the tasks run before some local
5184 variable of the parallel that the task uses as shared
5185 runs out of scope. The task can be spawned either
5186 from within current function (this would be easy to check)
5187 or from some function it calls and gets passed an address
5188 of such a variable. */
5189 if (any_addressable_vars < 0)
5191 gomp_parallel *parallel_stmt
5192 = as_a <gomp_parallel *> (last_stmt (region->entry));
5193 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5194 tree local_decls, block, decl;
5195 unsigned ix;
5197 any_addressable_vars = 0;
5198 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5199 if (TREE_ADDRESSABLE (decl))
5201 any_addressable_vars = 1;
5202 break;
5204 for (block = gimple_block (stmt);
5205 !any_addressable_vars
5206 && block
5207 && TREE_CODE (block) == BLOCK;
5208 block = BLOCK_SUPERCONTEXT (block))
5210 for (local_decls = BLOCK_VARS (block);
5211 local_decls;
5212 local_decls = DECL_CHAIN (local_decls))
5213 if (TREE_ADDRESSABLE (local_decls))
5215 any_addressable_vars = 1;
5216 break;
5218 if (block == gimple_block (parallel_stmt))
5219 break;
5222 if (!any_addressable_vars)
5223 gimple_omp_return_set_nowait (stmt);
5228 static void
5229 remove_exit_barriers (struct omp_region *region)
5231 if (region->type == GIMPLE_OMP_PARALLEL)
5232 remove_exit_barrier (region);
5234 if (region->inner)
5236 region = region->inner;
5237 remove_exit_barriers (region);
5238 while (region->next)
5240 region = region->next;
5241 remove_exit_barriers (region);
5246 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5247 calls. These can't be declared as const functions, but
5248 within one parallel body they are constant, so they can be
5249 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5250 which are declared const. Similarly for task body, except
5251 that in untied task omp_get_thread_num () can change at any task
5252 scheduling point. */
5254 static void
5255 optimize_omp_library_calls (gimple entry_stmt)
5257 basic_block bb;
5258 gimple_stmt_iterator gsi;
5259 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5260 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5261 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5262 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5263 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5264 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5265 OMP_CLAUSE_UNTIED) != NULL);
5267 FOR_EACH_BB_FN (bb, cfun)
5268 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5270 gimple call = gsi_stmt (gsi);
5271 tree decl;
5273 if (is_gimple_call (call)
5274 && (decl = gimple_call_fndecl (call))
5275 && DECL_EXTERNAL (decl)
5276 && TREE_PUBLIC (decl)
5277 && DECL_INITIAL (decl) == NULL)
5279 tree built_in;
5281 if (DECL_NAME (decl) == thr_num_id)
5283 /* In #pragma omp task untied omp_get_thread_num () can change
5284 during the execution of the task region. */
5285 if (untied_task)
5286 continue;
5287 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5289 else if (DECL_NAME (decl) == num_thr_id)
5290 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5291 else
5292 continue;
5294 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5295 || gimple_call_num_args (call) != 0)
5296 continue;
5298 if (flag_exceptions && !TREE_NOTHROW (decl))
5299 continue;
5301 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5302 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5303 TREE_TYPE (TREE_TYPE (built_in))))
5304 continue;
5306 gimple_call_set_fndecl (call, built_in);
5311 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5312 regimplified. */
5314 static tree
5315 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5317 tree t = *tp;
5319 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5320 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5321 return t;
5323 if (TREE_CODE (t) == ADDR_EXPR)
5324 recompute_tree_invariant_for_addr_expr (t);
5326 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5327 return NULL_TREE;
5330 /* Prepend TO = FROM assignment before *GSI_P. */
5332 static void
5333 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5335 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5336 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5337 true, GSI_SAME_STMT);
5338 gimple stmt = gimple_build_assign (to, from);
5339 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5340 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5341 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5343 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5344 gimple_regimplify_operands (stmt, &gsi);
5348 /* Expand the OpenMP parallel or task directive starting at REGION. */
5350 static void
5351 expand_omp_taskreg (struct omp_region *region)
5353 basic_block entry_bb, exit_bb, new_bb;
5354 struct function *child_cfun;
5355 tree child_fn, block, t;
5356 gimple_stmt_iterator gsi;
5357 gimple entry_stmt, stmt;
5358 edge e;
5359 vec<tree, va_gc> *ws_args;
5361 entry_stmt = last_stmt (region->entry);
5362 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5363 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5365 entry_bb = region->entry;
5366 exit_bb = region->exit;
5368 bool is_cilk_for
5369 = (flag_cilkplus
5370 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5371 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5372 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5374 if (is_cilk_for)
5375 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5376 and the inner statement contains the name of the built-in function
5377 and grain. */
5378 ws_args = region->inner->ws_args;
5379 else if (is_combined_parallel (region))
5380 ws_args = region->ws_args;
5381 else
5382 ws_args = NULL;
5384 if (child_cfun->cfg)
5386 /* Due to inlining, it may happen that we have already outlined
5387 the region, in which case all we need to do is make the
5388 sub-graph unreachable and emit the parallel call. */
5389 edge entry_succ_e, exit_succ_e;
5391 entry_succ_e = single_succ_edge (entry_bb);
5393 gsi = gsi_last_bb (entry_bb);
5394 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5395 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5396 gsi_remove (&gsi, true);
5398 new_bb = entry_bb;
5399 if (exit_bb)
5401 exit_succ_e = single_succ_edge (exit_bb);
5402 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5404 remove_edge_and_dominated_blocks (entry_succ_e);
5406 else
5408 unsigned srcidx, dstidx, num;
5410 /* If the parallel region needs data sent from the parent
5411 function, then the very first statement (except possible
5412 tree profile counter updates) of the parallel body
5413 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5414 &.OMP_DATA_O is passed as an argument to the child function,
5415 we need to replace it with the argument as seen by the child
5416 function.
5418 In most cases, this will end up being the identity assignment
5419 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5420 a function call that has been inlined, the original PARM_DECL
5421 .OMP_DATA_I may have been converted into a different local
5422 variable. In which case, we need to keep the assignment. */
5423 if (gimple_omp_taskreg_data_arg (entry_stmt))
5425 basic_block entry_succ_bb = single_succ (entry_bb);
5426 tree arg, narg;
5427 gimple parcopy_stmt = NULL;
5429 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5431 gimple stmt;
5433 gcc_assert (!gsi_end_p (gsi));
5434 stmt = gsi_stmt (gsi);
5435 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5436 continue;
5438 if (gimple_num_ops (stmt) == 2)
5440 tree arg = gimple_assign_rhs1 (stmt);
5442 /* We're ignore the subcode because we're
5443 effectively doing a STRIP_NOPS. */
5445 if (TREE_CODE (arg) == ADDR_EXPR
5446 && TREE_OPERAND (arg, 0)
5447 == gimple_omp_taskreg_data_arg (entry_stmt))
5449 parcopy_stmt = stmt;
5450 break;
5455 gcc_assert (parcopy_stmt != NULL);
5456 arg = DECL_ARGUMENTS (child_fn);
5458 if (!gimple_in_ssa_p (cfun))
5460 if (gimple_assign_lhs (parcopy_stmt) == arg)
5461 gsi_remove (&gsi, true);
5462 else
5464 /* ?? Is setting the subcode really necessary ?? */
5465 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5466 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5469 else
5471 /* If we are in ssa form, we must load the value from the default
5472 definition of the argument. That should not be defined now,
5473 since the argument is not used uninitialized. */
5474 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5475 narg = make_ssa_name (arg, gimple_build_nop ());
5476 set_ssa_default_def (cfun, arg, narg);
5477 /* ?? Is setting the subcode really necessary ?? */
5478 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5479 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5480 update_stmt (parcopy_stmt);
5484 /* Declare local variables needed in CHILD_CFUN. */
5485 block = DECL_INITIAL (child_fn);
5486 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5487 /* The gimplifier could record temporaries in parallel/task block
5488 rather than in containing function's local_decls chain,
5489 which would mean cgraph missed finalizing them. Do it now. */
5490 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5491 if (TREE_CODE (t) == VAR_DECL
5492 && TREE_STATIC (t)
5493 && !DECL_EXTERNAL (t))
5494 varpool_node::finalize_decl (t);
5495 DECL_SAVED_TREE (child_fn) = NULL;
5496 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5497 gimple_set_body (child_fn, NULL);
5498 TREE_USED (block) = 1;
5500 /* Reset DECL_CONTEXT on function arguments. */
5501 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5502 DECL_CONTEXT (t) = child_fn;
5504 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5505 so that it can be moved to the child function. */
5506 gsi = gsi_last_bb (entry_bb);
5507 stmt = gsi_stmt (gsi);
5508 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5509 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5510 gsi_remove (&gsi, true);
5511 e = split_block (entry_bb, stmt);
5512 entry_bb = e->dest;
5513 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5515 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5516 if (exit_bb)
5518 gsi = gsi_last_bb (exit_bb);
5519 gcc_assert (!gsi_end_p (gsi)
5520 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5521 stmt = gimple_build_return (NULL);
5522 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5523 gsi_remove (&gsi, true);
5526 /* Move the parallel region into CHILD_CFUN. */
5528 if (gimple_in_ssa_p (cfun))
5530 init_tree_ssa (child_cfun);
5531 init_ssa_operands (child_cfun);
5532 child_cfun->gimple_df->in_ssa_p = true;
5533 block = NULL_TREE;
5535 else
5536 block = gimple_block (entry_stmt);
5538 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5539 if (exit_bb)
5540 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5541 /* When the OMP expansion process cannot guarantee an up-to-date
5542 loop tree arrange for the child function to fixup loops. */
5543 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5544 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5546 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5547 num = vec_safe_length (child_cfun->local_decls);
5548 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5550 t = (*child_cfun->local_decls)[srcidx];
5551 if (DECL_CONTEXT (t) == cfun->decl)
5552 continue;
5553 if (srcidx != dstidx)
5554 (*child_cfun->local_decls)[dstidx] = t;
5555 dstidx++;
5557 if (dstidx != num)
5558 vec_safe_truncate (child_cfun->local_decls, dstidx);
5560 /* Inform the callgraph about the new function. */
5561 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5562 cgraph_node::add_new_function (child_fn, true);
5564 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5565 fixed in a following pass. */
5566 push_cfun (child_cfun);
5567 if (optimize)
5568 optimize_omp_library_calls (entry_stmt);
5569 cgraph_edge::rebuild_edges ();
5571 /* Some EH regions might become dead, see PR34608. If
5572 pass_cleanup_cfg isn't the first pass to happen with the
5573 new child, these dead EH edges might cause problems.
5574 Clean them up now. */
5575 if (flag_exceptions)
5577 basic_block bb;
5578 bool changed = false;
5580 FOR_EACH_BB_FN (bb, cfun)
5581 changed |= gimple_purge_dead_eh_edges (bb);
5582 if (changed)
5583 cleanup_tree_cfg ();
5585 if (gimple_in_ssa_p (cfun))
5586 update_ssa (TODO_update_ssa);
5587 pop_cfun ();
5590 /* Emit a library call to launch the children threads. */
5591 if (is_cilk_for)
5592 expand_cilk_for_call (new_bb,
5593 as_a <gomp_parallel *> (entry_stmt), ws_args);
5594 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5595 expand_parallel_call (region, new_bb,
5596 as_a <gomp_parallel *> (entry_stmt), ws_args);
5597 else
5598 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5599 if (gimple_in_ssa_p (cfun))
5600 update_ssa (TODO_update_ssa_only_virtuals);
5604 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5605 of the combined collapse > 1 loop constructs, generate code like:
5606 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5607 if (cond3 is <)
5608 adj = STEP3 - 1;
5609 else
5610 adj = STEP3 + 1;
5611 count3 = (adj + N32 - N31) / STEP3;
5612 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5613 if (cond2 is <)
5614 adj = STEP2 - 1;
5615 else
5616 adj = STEP2 + 1;
5617 count2 = (adj + N22 - N21) / STEP2;
5618 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5619 if (cond1 is <)
5620 adj = STEP1 - 1;
5621 else
5622 adj = STEP1 + 1;
5623 count1 = (adj + N12 - N11) / STEP1;
5624 count = count1 * count2 * count3;
5625 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5626 count = 0;
5627 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5628 of the combined loop constructs, just initialize COUNTS array
5629 from the _looptemp_ clauses. */
5631 /* NOTE: It *could* be better to moosh all of the BBs together,
5632 creating one larger BB with all the computation and the unexpected
5633 jump at the end. I.e.
5635 bool zero3, zero2, zero1, zero;
5637 zero3 = N32 c3 N31;
5638 count3 = (N32 - N31) /[cl] STEP3;
5639 zero2 = N22 c2 N21;
5640 count2 = (N22 - N21) /[cl] STEP2;
5641 zero1 = N12 c1 N11;
5642 count1 = (N12 - N11) /[cl] STEP1;
5643 zero = zero3 || zero2 || zero1;
5644 count = count1 * count2 * count3;
5645 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5647 After all, we expect the zero=false, and thus we expect to have to
5648 evaluate all of the comparison expressions, so short-circuiting
5649 oughtn't be a win. Since the condition isn't protecting a
5650 denominator, we're not concerned about divide-by-zero, so we can
5651 fully evaluate count even if a numerator turned out to be wrong.
5653 It seems like putting this all together would create much better
5654 scheduling opportunities, and less pressure on the chip's branch
5655 predictor. */
5657 static void
5658 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5659 basic_block &entry_bb, tree *counts,
5660 basic_block &zero_iter_bb, int &first_zero_iter,
5661 basic_block &l2_dom_bb)
5663 tree t, type = TREE_TYPE (fd->loop.v);
5664 edge e, ne;
5665 int i;
5667 /* Collapsed loops need work for expansion into SSA form. */
5668 gcc_assert (!gimple_in_ssa_p (cfun));
5670 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5671 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5673 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5674 isn't supposed to be handled, as the inner loop doesn't
5675 use it. */
5676 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5677 OMP_CLAUSE__LOOPTEMP_);
5678 gcc_assert (innerc);
5679 for (i = 0; i < fd->collapse; i++)
5681 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5682 OMP_CLAUSE__LOOPTEMP_);
5683 gcc_assert (innerc);
5684 if (i)
5685 counts[i] = OMP_CLAUSE_DECL (innerc);
5686 else
5687 counts[0] = NULL_TREE;
5689 return;
5692 for (i = 0; i < fd->collapse; i++)
5694 tree itype = TREE_TYPE (fd->loops[i].v);
5696 if (SSA_VAR_P (fd->loop.n2)
5697 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5698 fold_convert (itype, fd->loops[i].n1),
5699 fold_convert (itype, fd->loops[i].n2)))
5700 == NULL_TREE || !integer_onep (t)))
5702 gcond *cond_stmt;
5703 tree n1, n2;
5704 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5705 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5706 true, GSI_SAME_STMT);
5707 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5708 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5709 true, GSI_SAME_STMT);
5710 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5711 NULL_TREE, NULL_TREE);
5712 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5713 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5714 expand_omp_regimplify_p, NULL, NULL)
5715 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5716 expand_omp_regimplify_p, NULL, NULL))
5718 *gsi = gsi_for_stmt (cond_stmt);
5719 gimple_regimplify_operands (cond_stmt, gsi);
5721 e = split_block (entry_bb, cond_stmt);
5722 if (zero_iter_bb == NULL)
5724 gassign *assign_stmt;
5725 first_zero_iter = i;
5726 zero_iter_bb = create_empty_bb (entry_bb);
5727 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5728 *gsi = gsi_after_labels (zero_iter_bb);
5729 assign_stmt = gimple_build_assign (fd->loop.n2,
5730 build_zero_cst (type));
5731 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5732 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5733 entry_bb);
5735 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5736 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5737 e->flags = EDGE_TRUE_VALUE;
5738 e->probability = REG_BR_PROB_BASE - ne->probability;
5739 if (l2_dom_bb == NULL)
5740 l2_dom_bb = entry_bb;
5741 entry_bb = e->dest;
5742 *gsi = gsi_last_bb (entry_bb);
5745 if (POINTER_TYPE_P (itype))
5746 itype = signed_type_for (itype);
5747 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5748 ? -1 : 1));
5749 t = fold_build2 (PLUS_EXPR, itype,
5750 fold_convert (itype, fd->loops[i].step), t);
5751 t = fold_build2 (PLUS_EXPR, itype, t,
5752 fold_convert (itype, fd->loops[i].n2));
5753 t = fold_build2 (MINUS_EXPR, itype, t,
5754 fold_convert (itype, fd->loops[i].n1));
5755 /* ?? We could probably use CEIL_DIV_EXPR instead of
5756 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5757 generate the same code in the end because generically we
5758 don't know that the values involved must be negative for
5759 GT?? */
5760 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5761 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5762 fold_build1 (NEGATE_EXPR, itype, t),
5763 fold_build1 (NEGATE_EXPR, itype,
5764 fold_convert (itype,
5765 fd->loops[i].step)));
5766 else
5767 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5768 fold_convert (itype, fd->loops[i].step));
5769 t = fold_convert (type, t);
5770 if (TREE_CODE (t) == INTEGER_CST)
5771 counts[i] = t;
5772 else
5774 counts[i] = create_tmp_reg (type, ".count");
5775 expand_omp_build_assign (gsi, counts[i], t);
5777 if (SSA_VAR_P (fd->loop.n2))
5779 if (i == 0)
5780 t = counts[0];
5781 else
5782 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5783 expand_omp_build_assign (gsi, fd->loop.n2, t);
5789 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5790 T = V;
5791 V3 = N31 + (T % count3) * STEP3;
5792 T = T / count3;
5793 V2 = N21 + (T % count2) * STEP2;
5794 T = T / count2;
5795 V1 = N11 + T * STEP1;
5796 if this loop doesn't have an inner loop construct combined with it.
5797 If it does have an inner loop construct combined with it and the
5798 iteration count isn't known constant, store values from counts array
5799 into its _looptemp_ temporaries instead. */
5801 static void
5802 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5803 tree *counts, gimple inner_stmt, tree startvar)
5805 int i;
5806 if (gimple_omp_for_combined_p (fd->for_stmt))
5808 /* If fd->loop.n2 is constant, then no propagation of the counts
5809 is needed, they are constant. */
5810 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5811 return;
5813 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5814 ? gimple_omp_parallel_clauses (inner_stmt)
5815 : gimple_omp_for_clauses (inner_stmt);
5816 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5817 isn't supposed to be handled, as the inner loop doesn't
5818 use it. */
5819 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5820 gcc_assert (innerc);
5821 for (i = 0; i < fd->collapse; i++)
5823 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5824 OMP_CLAUSE__LOOPTEMP_);
5825 gcc_assert (innerc);
5826 if (i)
5828 tree tem = OMP_CLAUSE_DECL (innerc);
5829 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5830 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5831 false, GSI_CONTINUE_LINKING);
5832 gassign *stmt = gimple_build_assign (tem, t);
5833 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5836 return;
5839 tree type = TREE_TYPE (fd->loop.v);
5840 tree tem = create_tmp_reg (type, ".tem");
5841 gassign *stmt = gimple_build_assign (tem, startvar);
5842 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5844 for (i = fd->collapse - 1; i >= 0; i--)
5846 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5847 itype = vtype;
5848 if (POINTER_TYPE_P (vtype))
5849 itype = signed_type_for (vtype);
5850 if (i != 0)
5851 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5852 else
5853 t = tem;
5854 t = fold_convert (itype, t);
5855 t = fold_build2 (MULT_EXPR, itype, t,
5856 fold_convert (itype, fd->loops[i].step));
5857 if (POINTER_TYPE_P (vtype))
5858 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5859 else
5860 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5861 t = force_gimple_operand_gsi (gsi, t,
5862 DECL_P (fd->loops[i].v)
5863 && TREE_ADDRESSABLE (fd->loops[i].v),
5864 NULL_TREE, false,
5865 GSI_CONTINUE_LINKING);
5866 stmt = gimple_build_assign (fd->loops[i].v, t);
5867 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5868 if (i != 0)
5870 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5871 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5872 false, GSI_CONTINUE_LINKING);
5873 stmt = gimple_build_assign (tem, t);
5874 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5880 /* Helper function for expand_omp_for_*. Generate code like:
5881 L10:
5882 V3 += STEP3;
5883 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5884 L11:
5885 V3 = N31;
5886 V2 += STEP2;
5887 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5888 L12:
5889 V2 = N21;
5890 V1 += STEP1;
5891 goto BODY_BB; */
5893 static basic_block
5894 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5895 basic_block body_bb)
5897 basic_block last_bb, bb, collapse_bb = NULL;
5898 int i;
5899 gimple_stmt_iterator gsi;
5900 edge e;
5901 tree t;
5902 gimple stmt;
5904 last_bb = cont_bb;
5905 for (i = fd->collapse - 1; i >= 0; i--)
5907 tree vtype = TREE_TYPE (fd->loops[i].v);
5909 bb = create_empty_bb (last_bb);
5910 add_bb_to_loop (bb, last_bb->loop_father);
5911 gsi = gsi_start_bb (bb);
5913 if (i < fd->collapse - 1)
5915 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5916 e->probability = REG_BR_PROB_BASE / 8;
5918 t = fd->loops[i + 1].n1;
5919 t = force_gimple_operand_gsi (&gsi, t,
5920 DECL_P (fd->loops[i + 1].v)
5921 && TREE_ADDRESSABLE (fd->loops[i
5922 + 1].v),
5923 NULL_TREE, false,
5924 GSI_CONTINUE_LINKING);
5925 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5926 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5928 else
5929 collapse_bb = bb;
5931 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5933 if (POINTER_TYPE_P (vtype))
5934 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5935 else
5936 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5937 t = force_gimple_operand_gsi (&gsi, t,
5938 DECL_P (fd->loops[i].v)
5939 && TREE_ADDRESSABLE (fd->loops[i].v),
5940 NULL_TREE, false, GSI_CONTINUE_LINKING);
5941 stmt = gimple_build_assign (fd->loops[i].v, t);
5942 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5944 if (i > 0)
5946 t = fd->loops[i].n2;
5947 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5948 false, GSI_CONTINUE_LINKING);
5949 tree v = fd->loops[i].v;
5950 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5951 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5952 false, GSI_CONTINUE_LINKING);
5953 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5954 stmt = gimple_build_cond_empty (t);
5955 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5956 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5957 e->probability = REG_BR_PROB_BASE * 7 / 8;
5959 else
5960 make_edge (bb, body_bb, EDGE_FALLTHRU);
5961 last_bb = bb;
5964 return collapse_bb;
5968 /* A subroutine of expand_omp_for. Generate code for a parallel
5969 loop with any schedule. Given parameters:
5971 for (V = N1; V cond N2; V += STEP) BODY;
5973 where COND is "<" or ">", we generate pseudocode
5975 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5976 if (more) goto L0; else goto L3;
5978 V = istart0;
5979 iend = iend0;
5981 BODY;
5982 V += STEP;
5983 if (V cond iend) goto L1; else goto L2;
5985 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5988 If this is a combined omp parallel loop, instead of the call to
5989 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5990 If this is gimple_omp_for_combined_p loop, then instead of assigning
5991 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5992 inner GIMPLE_OMP_FOR and V += STEP; and
5993 if (V cond iend) goto L1; else goto L2; are removed.
5995 For collapsed loops, given parameters:
5996 collapse(3)
5997 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5998 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5999 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6000 BODY;
6002 we generate pseudocode
6004 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6005 if (cond3 is <)
6006 adj = STEP3 - 1;
6007 else
6008 adj = STEP3 + 1;
6009 count3 = (adj + N32 - N31) / STEP3;
6010 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6011 if (cond2 is <)
6012 adj = STEP2 - 1;
6013 else
6014 adj = STEP2 + 1;
6015 count2 = (adj + N22 - N21) / STEP2;
6016 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6017 if (cond1 is <)
6018 adj = STEP1 - 1;
6019 else
6020 adj = STEP1 + 1;
6021 count1 = (adj + N12 - N11) / STEP1;
6022 count = count1 * count2 * count3;
6023 goto Z1;
6025 count = 0;
6027 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6028 if (more) goto L0; else goto L3;
6030 V = istart0;
6031 T = V;
6032 V3 = N31 + (T % count3) * STEP3;
6033 T = T / count3;
6034 V2 = N21 + (T % count2) * STEP2;
6035 T = T / count2;
6036 V1 = N11 + T * STEP1;
6037 iend = iend0;
6039 BODY;
6040 V += 1;
6041 if (V < iend) goto L10; else goto L2;
6042 L10:
6043 V3 += STEP3;
6044 if (V3 cond3 N32) goto L1; else goto L11;
6045 L11:
6046 V3 = N31;
6047 V2 += STEP2;
6048 if (V2 cond2 N22) goto L1; else goto L12;
6049 L12:
6050 V2 = N21;
6051 V1 += STEP1;
6052 goto L1;
6054 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6059 static void
6060 expand_omp_for_generic (struct omp_region *region,
6061 struct omp_for_data *fd,
6062 enum built_in_function start_fn,
6063 enum built_in_function next_fn,
6064 gimple inner_stmt)
6066 tree type, istart0, iend0, iend;
6067 tree t, vmain, vback, bias = NULL_TREE;
6068 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6069 basic_block l2_bb = NULL, l3_bb = NULL;
6070 gimple_stmt_iterator gsi;
6071 gassign *assign_stmt;
6072 bool in_combined_parallel = is_combined_parallel (region);
6073 bool broken_loop = region->cont == NULL;
6074 edge e, ne;
6075 tree *counts = NULL;
6076 int i;
6078 gcc_assert (!broken_loop || !in_combined_parallel);
6079 gcc_assert (fd->iter_type == long_integer_type_node
6080 || !in_combined_parallel);
6082 type = TREE_TYPE (fd->loop.v);
6083 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6084 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6085 TREE_ADDRESSABLE (istart0) = 1;
6086 TREE_ADDRESSABLE (iend0) = 1;
6088 /* See if we need to bias by LLONG_MIN. */
6089 if (fd->iter_type == long_long_unsigned_type_node
6090 && TREE_CODE (type) == INTEGER_TYPE
6091 && !TYPE_UNSIGNED (type))
6093 tree n1, n2;
6095 if (fd->loop.cond_code == LT_EXPR)
6097 n1 = fd->loop.n1;
6098 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6100 else
6102 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6103 n2 = fd->loop.n1;
6105 if (TREE_CODE (n1) != INTEGER_CST
6106 || TREE_CODE (n2) != INTEGER_CST
6107 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6108 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6111 entry_bb = region->entry;
6112 cont_bb = region->cont;
6113 collapse_bb = NULL;
6114 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6115 gcc_assert (broken_loop
6116 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6117 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6118 l1_bb = single_succ (l0_bb);
6119 if (!broken_loop)
6121 l2_bb = create_empty_bb (cont_bb);
6122 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6123 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6125 else
6126 l2_bb = NULL;
6127 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6128 exit_bb = region->exit;
6130 gsi = gsi_last_bb (entry_bb);
6132 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6133 if (fd->collapse > 1)
6135 int first_zero_iter = -1;
6136 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6138 counts = XALLOCAVEC (tree, fd->collapse);
6139 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6140 zero_iter_bb, first_zero_iter,
6141 l2_dom_bb);
6143 if (zero_iter_bb)
6145 /* Some counts[i] vars might be uninitialized if
6146 some loop has zero iterations. But the body shouldn't
6147 be executed in that case, so just avoid uninit warnings. */
6148 for (i = first_zero_iter; i < fd->collapse; i++)
6149 if (SSA_VAR_P (counts[i]))
6150 TREE_NO_WARNING (counts[i]) = 1;
6151 gsi_prev (&gsi);
6152 e = split_block (entry_bb, gsi_stmt (gsi));
6153 entry_bb = e->dest;
6154 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6155 gsi = gsi_last_bb (entry_bb);
6156 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6157 get_immediate_dominator (CDI_DOMINATORS,
6158 zero_iter_bb));
6161 if (in_combined_parallel)
6163 /* In a combined parallel loop, emit a call to
6164 GOMP_loop_foo_next. */
6165 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6166 build_fold_addr_expr (istart0),
6167 build_fold_addr_expr (iend0));
6169 else
6171 tree t0, t1, t2, t3, t4;
6172 /* If this is not a combined parallel loop, emit a call to
6173 GOMP_loop_foo_start in ENTRY_BB. */
6174 t4 = build_fold_addr_expr (iend0);
6175 t3 = build_fold_addr_expr (istart0);
6176 t2 = fold_convert (fd->iter_type, fd->loop.step);
6177 t1 = fd->loop.n2;
6178 t0 = fd->loop.n1;
6179 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6181 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6182 OMP_CLAUSE__LOOPTEMP_);
6183 gcc_assert (innerc);
6184 t0 = OMP_CLAUSE_DECL (innerc);
6185 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6186 OMP_CLAUSE__LOOPTEMP_);
6187 gcc_assert (innerc);
6188 t1 = OMP_CLAUSE_DECL (innerc);
6190 if (POINTER_TYPE_P (TREE_TYPE (t0))
6191 && TYPE_PRECISION (TREE_TYPE (t0))
6192 != TYPE_PRECISION (fd->iter_type))
6194 /* Avoid casting pointers to integer of a different size. */
6195 tree itype = signed_type_for (type);
6196 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6197 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6199 else
6201 t1 = fold_convert (fd->iter_type, t1);
6202 t0 = fold_convert (fd->iter_type, t0);
6204 if (bias)
6206 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6207 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6209 if (fd->iter_type == long_integer_type_node)
6211 if (fd->chunk_size)
6213 t = fold_convert (fd->iter_type, fd->chunk_size);
6214 t = build_call_expr (builtin_decl_explicit (start_fn),
6215 6, t0, t1, t2, t, t3, t4);
6217 else
6218 t = build_call_expr (builtin_decl_explicit (start_fn),
6219 5, t0, t1, t2, t3, t4);
6221 else
6223 tree t5;
6224 tree c_bool_type;
6225 tree bfn_decl;
6227 /* The GOMP_loop_ull_*start functions have additional boolean
6228 argument, true for < loops and false for > loops.
6229 In Fortran, the C bool type can be different from
6230 boolean_type_node. */
6231 bfn_decl = builtin_decl_explicit (start_fn);
6232 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6233 t5 = build_int_cst (c_bool_type,
6234 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6235 if (fd->chunk_size)
6237 tree bfn_decl = builtin_decl_explicit (start_fn);
6238 t = fold_convert (fd->iter_type, fd->chunk_size);
6239 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6241 else
6242 t = build_call_expr (builtin_decl_explicit (start_fn),
6243 6, t5, t0, t1, t2, t3, t4);
6246 if (TREE_TYPE (t) != boolean_type_node)
6247 t = fold_build2 (NE_EXPR, boolean_type_node,
6248 t, build_int_cst (TREE_TYPE (t), 0));
6249 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6250 true, GSI_SAME_STMT);
6251 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6253 /* Remove the GIMPLE_OMP_FOR statement. */
6254 gsi_remove (&gsi, true);
6256 /* Iteration setup for sequential loop goes in L0_BB. */
6257 tree startvar = fd->loop.v;
6258 tree endvar = NULL_TREE;
6260 if (gimple_omp_for_combined_p (fd->for_stmt))
6262 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6263 && gimple_omp_for_kind (inner_stmt)
6264 == GF_OMP_FOR_KIND_SIMD);
6265 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6266 OMP_CLAUSE__LOOPTEMP_);
6267 gcc_assert (innerc);
6268 startvar = OMP_CLAUSE_DECL (innerc);
6269 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6270 OMP_CLAUSE__LOOPTEMP_);
6271 gcc_assert (innerc);
6272 endvar = OMP_CLAUSE_DECL (innerc);
6275 gsi = gsi_start_bb (l0_bb);
6276 t = istart0;
6277 if (bias)
6278 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6279 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6280 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6281 t = fold_convert (TREE_TYPE (startvar), t);
6282 t = force_gimple_operand_gsi (&gsi, t,
6283 DECL_P (startvar)
6284 && TREE_ADDRESSABLE (startvar),
6285 NULL_TREE, false, GSI_CONTINUE_LINKING);
6286 assign_stmt = gimple_build_assign (startvar, t);
6287 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6289 t = iend0;
6290 if (bias)
6291 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6292 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6293 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6294 t = fold_convert (TREE_TYPE (startvar), t);
6295 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6296 false, GSI_CONTINUE_LINKING);
6297 if (endvar)
6299 assign_stmt = gimple_build_assign (endvar, iend);
6300 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6301 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6302 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6303 else
6304 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6305 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6307 if (fd->collapse > 1)
6308 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6310 if (!broken_loop)
6312 /* Code to control the increment and predicate for the sequential
6313 loop goes in the CONT_BB. */
6314 gsi = gsi_last_bb (cont_bb);
6315 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6316 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6317 vmain = gimple_omp_continue_control_use (cont_stmt);
6318 vback = gimple_omp_continue_control_def (cont_stmt);
6320 if (!gimple_omp_for_combined_p (fd->for_stmt))
6322 if (POINTER_TYPE_P (type))
6323 t = fold_build_pointer_plus (vmain, fd->loop.step);
6324 else
6325 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6326 t = force_gimple_operand_gsi (&gsi, t,
6327 DECL_P (vback)
6328 && TREE_ADDRESSABLE (vback),
6329 NULL_TREE, true, GSI_SAME_STMT);
6330 assign_stmt = gimple_build_assign (vback, t);
6331 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6333 t = build2 (fd->loop.cond_code, boolean_type_node,
6334 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6335 iend);
6336 gcond *cond_stmt = gimple_build_cond_empty (t);
6337 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6340 /* Remove GIMPLE_OMP_CONTINUE. */
6341 gsi_remove (&gsi, true);
6343 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6344 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6346 /* Emit code to get the next parallel iteration in L2_BB. */
6347 gsi = gsi_start_bb (l2_bb);
6349 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6350 build_fold_addr_expr (istart0),
6351 build_fold_addr_expr (iend0));
6352 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6353 false, GSI_CONTINUE_LINKING);
6354 if (TREE_TYPE (t) != boolean_type_node)
6355 t = fold_build2 (NE_EXPR, boolean_type_node,
6356 t, build_int_cst (TREE_TYPE (t), 0));
6357 gcond *cond_stmt = gimple_build_cond_empty (t);
6358 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6361 /* Add the loop cleanup function. */
6362 gsi = gsi_last_bb (exit_bb);
6363 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6364 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6365 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6366 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6367 else
6368 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6369 gcall *call_stmt = gimple_build_call (t, 0);
6370 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6371 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6372 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6373 gsi_remove (&gsi, true);
6375 /* Connect the new blocks. */
6376 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6377 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6379 if (!broken_loop)
6381 gimple_seq phis;
6383 e = find_edge (cont_bb, l3_bb);
6384 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6386 phis = phi_nodes (l3_bb);
6387 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6389 gimple phi = gsi_stmt (gsi);
6390 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6391 PHI_ARG_DEF_FROM_EDGE (phi, e));
6393 remove_edge (e);
6395 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6396 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6397 e = find_edge (cont_bb, l1_bb);
6398 if (gimple_omp_for_combined_p (fd->for_stmt))
6400 remove_edge (e);
6401 e = NULL;
6403 else if (fd->collapse > 1)
6405 remove_edge (e);
6406 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6408 else
6409 e->flags = EDGE_TRUE_VALUE;
6410 if (e)
6412 e->probability = REG_BR_PROB_BASE * 7 / 8;
6413 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6415 else
6417 e = find_edge (cont_bb, l2_bb);
6418 e->flags = EDGE_FALLTHRU;
6420 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6422 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6423 recompute_dominator (CDI_DOMINATORS, l2_bb));
6424 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6425 recompute_dominator (CDI_DOMINATORS, l3_bb));
6426 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6427 recompute_dominator (CDI_DOMINATORS, l0_bb));
6428 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6429 recompute_dominator (CDI_DOMINATORS, l1_bb));
6431 struct loop *outer_loop = alloc_loop ();
6432 outer_loop->header = l0_bb;
6433 outer_loop->latch = l2_bb;
6434 add_loop (outer_loop, l0_bb->loop_father);
6436 if (!gimple_omp_for_combined_p (fd->for_stmt))
6438 struct loop *loop = alloc_loop ();
6439 loop->header = l1_bb;
6440 /* The loop may have multiple latches. */
6441 add_loop (loop, outer_loop);
6447 /* A subroutine of expand_omp_for. Generate code for a parallel
6448 loop with static schedule and no specified chunk size. Given
6449 parameters:
6451 for (V = N1; V cond N2; V += STEP) BODY;
6453 where COND is "<" or ">", we generate pseudocode
6455 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6456 if (cond is <)
6457 adj = STEP - 1;
6458 else
6459 adj = STEP + 1;
6460 if ((__typeof (V)) -1 > 0 && cond is >)
6461 n = -(adj + N2 - N1) / -STEP;
6462 else
6463 n = (adj + N2 - N1) / STEP;
6464 q = n / nthreads;
6465 tt = n % nthreads;
6466 if (threadid < tt) goto L3; else goto L4;
6468 tt = 0;
6469 q = q + 1;
6471 s0 = q * threadid + tt;
6472 e0 = s0 + q;
6473 V = s0 * STEP + N1;
6474 if (s0 >= e0) goto L2; else goto L0;
6476 e = e0 * STEP + N1;
6478 BODY;
6479 V += STEP;
6480 if (V cond e) goto L1;
6484 static void
6485 expand_omp_for_static_nochunk (struct omp_region *region,
6486 struct omp_for_data *fd,
6487 gimple inner_stmt)
6489 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6490 tree type, itype, vmain, vback;
6491 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6492 basic_block body_bb, cont_bb, collapse_bb = NULL;
6493 basic_block fin_bb;
6494 gimple_stmt_iterator gsi;
6495 edge ep;
6496 bool broken_loop = region->cont == NULL;
6497 tree *counts = NULL;
6498 tree n1, n2, step;
6500 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6501 != GF_OMP_FOR_KIND_OACC_LOOP)
6502 || !inner_stmt);
6504 itype = type = TREE_TYPE (fd->loop.v);
6505 if (POINTER_TYPE_P (type))
6506 itype = signed_type_for (type);
6508 entry_bb = region->entry;
6509 cont_bb = region->cont;
6510 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6511 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6512 gcc_assert (broken_loop
6513 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6514 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6515 body_bb = single_succ (seq_start_bb);
6516 if (!broken_loop)
6518 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6519 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6521 exit_bb = region->exit;
6523 /* Iteration space partitioning goes in ENTRY_BB. */
6524 gsi = gsi_last_bb (entry_bb);
6525 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6527 if (fd->collapse > 1)
6529 int first_zero_iter = -1;
6530 basic_block l2_dom_bb = NULL;
6532 counts = XALLOCAVEC (tree, fd->collapse);
6533 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6534 fin_bb, first_zero_iter,
6535 l2_dom_bb);
6536 t = NULL_TREE;
6538 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6539 t = integer_one_node;
6540 else
6541 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6542 fold_convert (type, fd->loop.n1),
6543 fold_convert (type, fd->loop.n2));
6544 if (fd->collapse == 1
6545 && TYPE_UNSIGNED (type)
6546 && (t == NULL_TREE || !integer_onep (t)))
6548 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6549 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6550 true, GSI_SAME_STMT);
6551 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6552 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6553 true, GSI_SAME_STMT);
6554 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6555 NULL_TREE, NULL_TREE);
6556 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6557 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6558 expand_omp_regimplify_p, NULL, NULL)
6559 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6560 expand_omp_regimplify_p, NULL, NULL))
6562 gsi = gsi_for_stmt (cond_stmt);
6563 gimple_regimplify_operands (cond_stmt, &gsi);
6565 ep = split_block (entry_bb, cond_stmt);
6566 ep->flags = EDGE_TRUE_VALUE;
6567 entry_bb = ep->dest;
6568 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6569 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6570 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6571 if (gimple_in_ssa_p (cfun))
6573 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6574 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6575 !gsi_end_p (gpi); gsi_next (&gpi))
6577 gphi *phi = gpi.phi ();
6578 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6579 ep, UNKNOWN_LOCATION);
6582 gsi = gsi_last_bb (entry_bb);
6585 switch (gimple_omp_for_kind (fd->for_stmt))
6587 case GF_OMP_FOR_KIND_FOR:
6588 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6589 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6590 break;
6591 case GF_OMP_FOR_KIND_DISTRIBUTE:
6592 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6593 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6594 break;
6595 case GF_OMP_FOR_KIND_OACC_LOOP:
6596 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6597 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6598 break;
6599 default:
6600 gcc_unreachable ();
6602 nthreads = build_call_expr (nthreads, 0);
6603 nthreads = fold_convert (itype, nthreads);
6604 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6605 true, GSI_SAME_STMT);
6606 threadid = build_call_expr (threadid, 0);
6607 threadid = fold_convert (itype, threadid);
6608 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6609 true, GSI_SAME_STMT);
6611 n1 = fd->loop.n1;
6612 n2 = fd->loop.n2;
6613 step = fd->loop.step;
6614 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6616 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6617 OMP_CLAUSE__LOOPTEMP_);
6618 gcc_assert (innerc);
6619 n1 = OMP_CLAUSE_DECL (innerc);
6620 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6621 OMP_CLAUSE__LOOPTEMP_);
6622 gcc_assert (innerc);
6623 n2 = OMP_CLAUSE_DECL (innerc);
6625 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6626 true, NULL_TREE, true, GSI_SAME_STMT);
6627 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6628 true, NULL_TREE, true, GSI_SAME_STMT);
6629 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6630 true, NULL_TREE, true, GSI_SAME_STMT);
6632 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6633 t = fold_build2 (PLUS_EXPR, itype, step, t);
6634 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6635 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6636 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6637 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6638 fold_build1 (NEGATE_EXPR, itype, t),
6639 fold_build1 (NEGATE_EXPR, itype, step));
6640 else
6641 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6642 t = fold_convert (itype, t);
6643 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6645 q = create_tmp_reg (itype, "q");
6646 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6647 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6648 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6650 tt = create_tmp_reg (itype, "tt");
6651 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6652 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6653 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6655 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6656 gcond *cond_stmt = gimple_build_cond_empty (t);
6657 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6659 second_bb = split_block (entry_bb, cond_stmt)->dest;
6660 gsi = gsi_last_bb (second_bb);
6661 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6663 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6664 GSI_SAME_STMT);
6665 gassign *assign_stmt
6666 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6667 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6669 third_bb = split_block (second_bb, assign_stmt)->dest;
6670 gsi = gsi_last_bb (third_bb);
6671 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6673 t = build2 (MULT_EXPR, itype, q, threadid);
6674 t = build2 (PLUS_EXPR, itype, t, tt);
6675 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6677 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6678 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6680 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6681 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6683 /* Remove the GIMPLE_OMP_FOR statement. */
6684 gsi_remove (&gsi, true);
6686 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6687 gsi = gsi_start_bb (seq_start_bb);
6689 tree startvar = fd->loop.v;
6690 tree endvar = NULL_TREE;
6692 if (gimple_omp_for_combined_p (fd->for_stmt))
6694 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6695 ? gimple_omp_parallel_clauses (inner_stmt)
6696 : gimple_omp_for_clauses (inner_stmt);
6697 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6698 gcc_assert (innerc);
6699 startvar = OMP_CLAUSE_DECL (innerc);
6700 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6701 OMP_CLAUSE__LOOPTEMP_);
6702 gcc_assert (innerc);
6703 endvar = OMP_CLAUSE_DECL (innerc);
6705 t = fold_convert (itype, s0);
6706 t = fold_build2 (MULT_EXPR, itype, t, step);
6707 if (POINTER_TYPE_P (type))
6708 t = fold_build_pointer_plus (n1, t);
6709 else
6710 t = fold_build2 (PLUS_EXPR, type, t, n1);
6711 t = fold_convert (TREE_TYPE (startvar), t);
6712 t = force_gimple_operand_gsi (&gsi, t,
6713 DECL_P (startvar)
6714 && TREE_ADDRESSABLE (startvar),
6715 NULL_TREE, false, GSI_CONTINUE_LINKING);
6716 assign_stmt = gimple_build_assign (startvar, t);
6717 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6719 t = fold_convert (itype, e0);
6720 t = fold_build2 (MULT_EXPR, itype, t, step);
6721 if (POINTER_TYPE_P (type))
6722 t = fold_build_pointer_plus (n1, t);
6723 else
6724 t = fold_build2 (PLUS_EXPR, type, t, n1);
6725 t = fold_convert (TREE_TYPE (startvar), t);
6726 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6727 false, GSI_CONTINUE_LINKING);
6728 if (endvar)
6730 assign_stmt = gimple_build_assign (endvar, e);
6731 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6732 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6733 assign_stmt = gimple_build_assign (fd->loop.v, e);
6734 else
6735 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6736 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6738 if (fd->collapse > 1)
6739 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6741 if (!broken_loop)
6743 /* The code controlling the sequential loop replaces the
6744 GIMPLE_OMP_CONTINUE. */
6745 gsi = gsi_last_bb (cont_bb);
6746 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6747 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6748 vmain = gimple_omp_continue_control_use (cont_stmt);
6749 vback = gimple_omp_continue_control_def (cont_stmt);
6751 if (!gimple_omp_for_combined_p (fd->for_stmt))
6753 if (POINTER_TYPE_P (type))
6754 t = fold_build_pointer_plus (vmain, step);
6755 else
6756 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6757 t = force_gimple_operand_gsi (&gsi, t,
6758 DECL_P (vback)
6759 && TREE_ADDRESSABLE (vback),
6760 NULL_TREE, true, GSI_SAME_STMT);
6761 assign_stmt = gimple_build_assign (vback, t);
6762 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6764 t = build2 (fd->loop.cond_code, boolean_type_node,
6765 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6766 ? t : vback, e);
6767 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6770 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6771 gsi_remove (&gsi, true);
6773 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6774 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6777 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6778 gsi = gsi_last_bb (exit_bb);
6779 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6781 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6782 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6783 gcc_checking_assert (t == NULL_TREE);
6784 else
6785 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6787 gsi_remove (&gsi, true);
6789 /* Connect all the blocks. */
6790 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6791 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6792 ep = find_edge (entry_bb, second_bb);
6793 ep->flags = EDGE_TRUE_VALUE;
6794 ep->probability = REG_BR_PROB_BASE / 4;
6795 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6796 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6798 if (!broken_loop)
6800 ep = find_edge (cont_bb, body_bb);
6801 if (gimple_omp_for_combined_p (fd->for_stmt))
6803 remove_edge (ep);
6804 ep = NULL;
6806 else if (fd->collapse > 1)
6808 remove_edge (ep);
6809 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6811 else
6812 ep->flags = EDGE_TRUE_VALUE;
6813 find_edge (cont_bb, fin_bb)->flags
6814 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6817 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6818 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6819 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6821 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6822 recompute_dominator (CDI_DOMINATORS, body_bb));
6823 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6824 recompute_dominator (CDI_DOMINATORS, fin_bb));
6826 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6828 struct loop *loop = alloc_loop ();
6829 loop->header = body_bb;
6830 if (collapse_bb == NULL)
6831 loop->latch = cont_bb;
6832 add_loop (loop, body_bb->loop_father);
6837 /* A subroutine of expand_omp_for. Generate code for a parallel
6838 loop with static schedule and a specified chunk size. Given
6839 parameters:
6841 for (V = N1; V cond N2; V += STEP) BODY;
6843 where COND is "<" or ">", we generate pseudocode
6845 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6846 if (cond is <)
6847 adj = STEP - 1;
6848 else
6849 adj = STEP + 1;
6850 if ((__typeof (V)) -1 > 0 && cond is >)
6851 n = -(adj + N2 - N1) / -STEP;
6852 else
6853 n = (adj + N2 - N1) / STEP;
6854 trip = 0;
6855 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6856 here so that V is defined
6857 if the loop is not entered
6859 s0 = (trip * nthreads + threadid) * CHUNK;
6860 e0 = min(s0 + CHUNK, n);
6861 if (s0 < n) goto L1; else goto L4;
6863 V = s0 * STEP + N1;
6864 e = e0 * STEP + N1;
6866 BODY;
6867 V += STEP;
6868 if (V cond e) goto L2; else goto L3;
6870 trip += 1;
6871 goto L0;
6875 static void
6876 expand_omp_for_static_chunk (struct omp_region *region,
6877 struct omp_for_data *fd, gimple inner_stmt)
6879 tree n, s0, e0, e, t;
6880 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6881 tree type, itype, vmain, vback, vextra;
6882 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6883 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6884 gimple_stmt_iterator gsi;
6885 edge se;
6886 bool broken_loop = region->cont == NULL;
6887 tree *counts = NULL;
6888 tree n1, n2, step;
6890 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6891 != GF_OMP_FOR_KIND_OACC_LOOP)
6892 || !inner_stmt);
6894 itype = type = TREE_TYPE (fd->loop.v);
6895 if (POINTER_TYPE_P (type))
6896 itype = signed_type_for (type);
6898 entry_bb = region->entry;
6899 se = split_block (entry_bb, last_stmt (entry_bb));
6900 entry_bb = se->src;
6901 iter_part_bb = se->dest;
6902 cont_bb = region->cont;
6903 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6904 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6905 gcc_assert (broken_loop
6906 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6907 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6908 body_bb = single_succ (seq_start_bb);
6909 if (!broken_loop)
6911 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6912 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6913 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6915 exit_bb = region->exit;
6917 /* Trip and adjustment setup goes in ENTRY_BB. */
6918 gsi = gsi_last_bb (entry_bb);
6919 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6921 if (fd->collapse > 1)
6923 int first_zero_iter = -1;
6924 basic_block l2_dom_bb = NULL;
6926 counts = XALLOCAVEC (tree, fd->collapse);
6927 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6928 fin_bb, first_zero_iter,
6929 l2_dom_bb);
6930 t = NULL_TREE;
6932 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6933 t = integer_one_node;
6934 else
6935 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6936 fold_convert (type, fd->loop.n1),
6937 fold_convert (type, fd->loop.n2));
6938 if (fd->collapse == 1
6939 && TYPE_UNSIGNED (type)
6940 && (t == NULL_TREE || !integer_onep (t)))
6942 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6943 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6944 true, GSI_SAME_STMT);
6945 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6946 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6947 true, GSI_SAME_STMT);
6948 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6949 NULL_TREE, NULL_TREE);
6950 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6951 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6952 expand_omp_regimplify_p, NULL, NULL)
6953 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6954 expand_omp_regimplify_p, NULL, NULL))
6956 gsi = gsi_for_stmt (cond_stmt);
6957 gimple_regimplify_operands (cond_stmt, &gsi);
6959 se = split_block (entry_bb, cond_stmt);
6960 se->flags = EDGE_TRUE_VALUE;
6961 entry_bb = se->dest;
6962 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6963 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6964 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6965 if (gimple_in_ssa_p (cfun))
6967 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6968 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6969 !gsi_end_p (gpi); gsi_next (&gpi))
6971 gphi *phi = gpi.phi ();
6972 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6973 se, UNKNOWN_LOCATION);
6976 gsi = gsi_last_bb (entry_bb);
6979 switch (gimple_omp_for_kind (fd->for_stmt))
6981 case GF_OMP_FOR_KIND_FOR:
6982 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6983 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6984 break;
6985 case GF_OMP_FOR_KIND_DISTRIBUTE:
6986 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6987 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6988 break;
6989 case GF_OMP_FOR_KIND_OACC_LOOP:
6990 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6991 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6992 break;
6993 default:
6994 gcc_unreachable ();
6996 nthreads = build_call_expr (nthreads, 0);
6997 nthreads = fold_convert (itype, nthreads);
6998 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6999 true, GSI_SAME_STMT);
7000 threadid = build_call_expr (threadid, 0);
7001 threadid = fold_convert (itype, threadid);
7002 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7003 true, GSI_SAME_STMT);
7005 n1 = fd->loop.n1;
7006 n2 = fd->loop.n2;
7007 step = fd->loop.step;
7008 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7010 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7011 OMP_CLAUSE__LOOPTEMP_);
7012 gcc_assert (innerc);
7013 n1 = OMP_CLAUSE_DECL (innerc);
7014 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7015 OMP_CLAUSE__LOOPTEMP_);
7016 gcc_assert (innerc);
7017 n2 = OMP_CLAUSE_DECL (innerc);
7019 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7020 true, NULL_TREE, true, GSI_SAME_STMT);
7021 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7022 true, NULL_TREE, true, GSI_SAME_STMT);
7023 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7024 true, NULL_TREE, true, GSI_SAME_STMT);
7025 fd->chunk_size
7026 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7027 true, NULL_TREE, true, GSI_SAME_STMT);
7029 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7030 t = fold_build2 (PLUS_EXPR, itype, step, t);
7031 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7032 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7033 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7034 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7035 fold_build1 (NEGATE_EXPR, itype, t),
7036 fold_build1 (NEGATE_EXPR, itype, step));
7037 else
7038 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7039 t = fold_convert (itype, t);
7040 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7041 true, GSI_SAME_STMT);
7043 trip_var = create_tmp_reg (itype, ".trip");
7044 if (gimple_in_ssa_p (cfun))
7046 trip_init = make_ssa_name (trip_var);
7047 trip_main = make_ssa_name (trip_var);
7048 trip_back = make_ssa_name (trip_var);
7050 else
7052 trip_init = trip_var;
7053 trip_main = trip_var;
7054 trip_back = trip_var;
7057 gassign *assign_stmt
7058 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7059 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7061 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7062 t = fold_build2 (MULT_EXPR, itype, t, step);
7063 if (POINTER_TYPE_P (type))
7064 t = fold_build_pointer_plus (n1, t);
7065 else
7066 t = fold_build2 (PLUS_EXPR, type, t, n1);
7067 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7068 true, GSI_SAME_STMT);
7070 /* Remove the GIMPLE_OMP_FOR. */
7071 gsi_remove (&gsi, true);
7073 /* Iteration space partitioning goes in ITER_PART_BB. */
7074 gsi = gsi_last_bb (iter_part_bb);
7076 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7077 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7078 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7079 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7080 false, GSI_CONTINUE_LINKING);
7082 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7083 t = fold_build2 (MIN_EXPR, itype, t, n);
7084 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7085 false, GSI_CONTINUE_LINKING);
7087 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7088 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7090 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7091 gsi = gsi_start_bb (seq_start_bb);
7093 tree startvar = fd->loop.v;
7094 tree endvar = NULL_TREE;
7096 if (gimple_omp_for_combined_p (fd->for_stmt))
7098 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7099 ? gimple_omp_parallel_clauses (inner_stmt)
7100 : gimple_omp_for_clauses (inner_stmt);
7101 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7102 gcc_assert (innerc);
7103 startvar = OMP_CLAUSE_DECL (innerc);
7104 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7105 OMP_CLAUSE__LOOPTEMP_);
7106 gcc_assert (innerc);
7107 endvar = OMP_CLAUSE_DECL (innerc);
7110 t = fold_convert (itype, s0);
7111 t = fold_build2 (MULT_EXPR, itype, t, step);
7112 if (POINTER_TYPE_P (type))
7113 t = fold_build_pointer_plus (n1, t);
7114 else
7115 t = fold_build2 (PLUS_EXPR, type, t, n1);
7116 t = fold_convert (TREE_TYPE (startvar), t);
7117 t = force_gimple_operand_gsi (&gsi, t,
7118 DECL_P (startvar)
7119 && TREE_ADDRESSABLE (startvar),
7120 NULL_TREE, false, GSI_CONTINUE_LINKING);
7121 assign_stmt = gimple_build_assign (startvar, t);
7122 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7124 t = fold_convert (itype, e0);
7125 t = fold_build2 (MULT_EXPR, itype, t, step);
7126 if (POINTER_TYPE_P (type))
7127 t = fold_build_pointer_plus (n1, t);
7128 else
7129 t = fold_build2 (PLUS_EXPR, type, t, n1);
7130 t = fold_convert (TREE_TYPE (startvar), t);
7131 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7132 false, GSI_CONTINUE_LINKING);
7133 if (endvar)
7135 assign_stmt = gimple_build_assign (endvar, e);
7136 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7137 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7138 assign_stmt = gimple_build_assign (fd->loop.v, e);
7139 else
7140 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7141 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7143 if (fd->collapse > 1)
7144 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7146 if (!broken_loop)
7148 /* The code controlling the sequential loop goes in CONT_BB,
7149 replacing the GIMPLE_OMP_CONTINUE. */
7150 gsi = gsi_last_bb (cont_bb);
7151 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7152 vmain = gimple_omp_continue_control_use (cont_stmt);
7153 vback = gimple_omp_continue_control_def (cont_stmt);
7155 if (!gimple_omp_for_combined_p (fd->for_stmt))
7157 if (POINTER_TYPE_P (type))
7158 t = fold_build_pointer_plus (vmain, step);
7159 else
7160 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7161 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7162 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7163 true, GSI_SAME_STMT);
7164 assign_stmt = gimple_build_assign (vback, t);
7165 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7167 t = build2 (fd->loop.cond_code, boolean_type_node,
7168 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7169 ? t : vback, e);
7170 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7173 /* Remove GIMPLE_OMP_CONTINUE. */
7174 gsi_remove (&gsi, true);
7176 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7177 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7179 /* Trip update code goes into TRIP_UPDATE_BB. */
7180 gsi = gsi_start_bb (trip_update_bb);
7182 t = build_int_cst (itype, 1);
7183 t = build2 (PLUS_EXPR, itype, trip_main, t);
7184 assign_stmt = gimple_build_assign (trip_back, t);
7185 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7188 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7189 gsi = gsi_last_bb (exit_bb);
7190 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7192 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7193 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7194 gcc_checking_assert (t == NULL_TREE);
7195 else
7196 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7198 gsi_remove (&gsi, true);
7200 /* Connect the new blocks. */
7201 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7202 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7204 if (!broken_loop)
7206 se = find_edge (cont_bb, body_bb);
7207 if (gimple_omp_for_combined_p (fd->for_stmt))
7209 remove_edge (se);
7210 se = NULL;
7212 else if (fd->collapse > 1)
7214 remove_edge (se);
7215 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7217 else
7218 se->flags = EDGE_TRUE_VALUE;
7219 find_edge (cont_bb, trip_update_bb)->flags
7220 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7222 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7225 if (gimple_in_ssa_p (cfun))
7227 gphi_iterator psi;
7228 gphi *phi;
7229 edge re, ene;
7230 edge_var_map *vm;
7231 size_t i;
7233 gcc_assert (fd->collapse == 1 && !broken_loop);
7235 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7236 remove arguments of the phi nodes in fin_bb. We need to create
7237 appropriate phi nodes in iter_part_bb instead. */
7238 se = single_pred_edge (fin_bb);
7239 re = single_succ_edge (trip_update_bb);
7240 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7241 ene = single_succ_edge (entry_bb);
7243 psi = gsi_start_phis (fin_bb);
7244 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7245 gsi_next (&psi), ++i)
7247 gphi *nphi;
7248 source_location locus;
7250 phi = psi.phi ();
7251 t = gimple_phi_result (phi);
7252 gcc_assert (t == redirect_edge_var_map_result (vm));
7253 nphi = create_phi_node (t, iter_part_bb);
7255 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7256 locus = gimple_phi_arg_location_from_edge (phi, se);
7258 /* A special case -- fd->loop.v is not yet computed in
7259 iter_part_bb, we need to use vextra instead. */
7260 if (t == fd->loop.v)
7261 t = vextra;
7262 add_phi_arg (nphi, t, ene, locus);
7263 locus = redirect_edge_var_map_location (vm);
7264 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7266 gcc_assert (gsi_end_p (psi) && i == head->length ());
7267 redirect_edge_var_map_clear (re);
7268 while (1)
7270 psi = gsi_start_phis (fin_bb);
7271 if (gsi_end_p (psi))
7272 break;
7273 remove_phi_node (&psi, false);
7276 /* Make phi node for trip. */
7277 phi = create_phi_node (trip_main, iter_part_bb);
7278 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7279 UNKNOWN_LOCATION);
7280 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7281 UNKNOWN_LOCATION);
7284 if (!broken_loop)
7285 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7286 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7287 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7288 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7289 recompute_dominator (CDI_DOMINATORS, fin_bb));
7290 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7291 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7292 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7293 recompute_dominator (CDI_DOMINATORS, body_bb));
7295 if (!broken_loop)
7297 struct loop *trip_loop = alloc_loop ();
7298 trip_loop->header = iter_part_bb;
7299 trip_loop->latch = trip_update_bb;
7300 add_loop (trip_loop, iter_part_bb->loop_father);
7302 if (!gimple_omp_for_combined_p (fd->for_stmt))
7304 struct loop *loop = alloc_loop ();
7305 loop->header = body_bb;
7306 if (collapse_bb == NULL)
7307 loop->latch = cont_bb;
7308 add_loop (loop, trip_loop);
7313 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7314 Given parameters:
7315 for (V = N1; V cond N2; V += STEP) BODY;
7317 where COND is "<" or ">" or "!=", we generate pseudocode
7319 for (ind_var = low; ind_var < high; ind_var++)
7321 V = n1 + (ind_var * STEP)
7323 <BODY>
7326 In the above pseudocode, low and high are function parameters of the
7327 child function. In the function below, we are inserting a temp.
7328 variable that will be making a call to two OMP functions that will not be
7329 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7330 with _Cilk_for). These functions are replaced with low and high
7331 by the function that handles taskreg. */
7334 static void
7335 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7337 bool broken_loop = region->cont == NULL;
7338 basic_block entry_bb = region->entry;
7339 basic_block cont_bb = region->cont;
7341 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7342 gcc_assert (broken_loop
7343 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7344 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7345 basic_block l1_bb, l2_bb;
7347 if (!broken_loop)
7349 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7350 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7351 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7352 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7354 else
7356 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7357 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7358 l2_bb = single_succ (l1_bb);
7360 basic_block exit_bb = region->exit;
7361 basic_block l2_dom_bb = NULL;
7363 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7365 /* Below statements until the "tree high_val = ..." are pseudo statements
7366 used to pass information to be used by expand_omp_taskreg.
7367 low_val and high_val will be replaced by the __low and __high
7368 parameter from the child function.
7370 The call_exprs part is a place-holder, it is mainly used
7371 to distinctly identify to the top-level part that this is
7372 where we should put low and high (reasoning given in header
7373 comment). */
7375 tree child_fndecl
7376 = gimple_omp_parallel_child_fn (
7377 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7378 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7379 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7381 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7382 high_val = t;
7383 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7384 low_val = t;
7386 gcc_assert (low_val && high_val);
7388 tree type = TREE_TYPE (low_val);
7389 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7390 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7392 /* Not needed in SSA form right now. */
7393 gcc_assert (!gimple_in_ssa_p (cfun));
7394 if (l2_dom_bb == NULL)
7395 l2_dom_bb = l1_bb;
7397 tree n1 = low_val;
7398 tree n2 = high_val;
7400 gimple stmt = gimple_build_assign (ind_var, n1);
7402 /* Replace the GIMPLE_OMP_FOR statement. */
7403 gsi_replace (&gsi, stmt, true);
7405 if (!broken_loop)
7407 /* Code to control the increment goes in the CONT_BB. */
7408 gsi = gsi_last_bb (cont_bb);
7409 stmt = gsi_stmt (gsi);
7410 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7411 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7412 build_one_cst (type));
7414 /* Replace GIMPLE_OMP_CONTINUE. */
7415 gsi_replace (&gsi, stmt, true);
7418 /* Emit the condition in L1_BB. */
7419 gsi = gsi_after_labels (l1_bb);
7420 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7421 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7422 fd->loop.step);
7423 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7424 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7425 fd->loop.n1, fold_convert (sizetype, t));
7426 else
7427 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7428 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7429 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7430 expand_omp_build_assign (&gsi, fd->loop.v, t);
7432 /* The condition is always '<' since the runtime will fill in the low
7433 and high values. */
7434 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7435 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7437 /* Remove GIMPLE_OMP_RETURN. */
7438 gsi = gsi_last_bb (exit_bb);
7439 gsi_remove (&gsi, true);
7441 /* Connect the new blocks. */
7442 remove_edge (FALLTHRU_EDGE (entry_bb));
7444 edge e, ne;
7445 if (!broken_loop)
7447 remove_edge (BRANCH_EDGE (entry_bb));
7448 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7450 e = BRANCH_EDGE (l1_bb);
7451 ne = FALLTHRU_EDGE (l1_bb);
7452 e->flags = EDGE_TRUE_VALUE;
7454 else
7456 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7458 ne = single_succ_edge (l1_bb);
7459 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7462 ne->flags = EDGE_FALSE_VALUE;
7463 e->probability = REG_BR_PROB_BASE * 7 / 8;
7464 ne->probability = REG_BR_PROB_BASE / 8;
7466 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7467 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7468 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7470 if (!broken_loop)
7472 struct loop *loop = alloc_loop ();
7473 loop->header = l1_bb;
7474 loop->latch = cont_bb;
7475 add_loop (loop, l1_bb->loop_father);
7476 loop->safelen = INT_MAX;
7479 /* Pick the correct library function based on the precision of the
7480 induction variable type. */
7481 tree lib_fun = NULL_TREE;
7482 if (TYPE_PRECISION (type) == 32)
7483 lib_fun = cilk_for_32_fndecl;
7484 else if (TYPE_PRECISION (type) == 64)
7485 lib_fun = cilk_for_64_fndecl;
7486 else
7487 gcc_unreachable ();
7489 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7491 /* WS_ARGS contains the library function flavor to call:
7492 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7493 user-defined grain value. If the user does not define one, then zero
7494 is passed in by the parser. */
7495 vec_alloc (region->ws_args, 2);
7496 region->ws_args->quick_push (lib_fun);
7497 region->ws_args->quick_push (fd->chunk_size);
7500 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7501 loop. Given parameters:
7503 for (V = N1; V cond N2; V += STEP) BODY;
7505 where COND is "<" or ">", we generate pseudocode
7507 V = N1;
7508 goto L1;
7510 BODY;
7511 V += STEP;
7513 if (V cond N2) goto L0; else goto L2;
7516 For collapsed loops, given parameters:
7517 collapse(3)
7518 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7519 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7520 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7521 BODY;
7523 we generate pseudocode
7525 if (cond3 is <)
7526 adj = STEP3 - 1;
7527 else
7528 adj = STEP3 + 1;
7529 count3 = (adj + N32 - N31) / STEP3;
7530 if (cond2 is <)
7531 adj = STEP2 - 1;
7532 else
7533 adj = STEP2 + 1;
7534 count2 = (adj + N22 - N21) / STEP2;
7535 if (cond1 is <)
7536 adj = STEP1 - 1;
7537 else
7538 adj = STEP1 + 1;
7539 count1 = (adj + N12 - N11) / STEP1;
7540 count = count1 * count2 * count3;
7541 V = 0;
7542 V1 = N11;
7543 V2 = N21;
7544 V3 = N31;
7545 goto L1;
7547 BODY;
7548 V += 1;
7549 V3 += STEP3;
7550 V2 += (V3 cond3 N32) ? 0 : STEP2;
7551 V3 = (V3 cond3 N32) ? V3 : N31;
7552 V1 += (V2 cond2 N22) ? 0 : STEP1;
7553 V2 = (V2 cond2 N22) ? V2 : N21;
7555 if (V < count) goto L0; else goto L2;
7560 static void
7561 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7563 tree type, t;
7564 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7565 gimple_stmt_iterator gsi;
7566 gimple stmt;
7567 gcond *cond_stmt;
7568 bool broken_loop = region->cont == NULL;
7569 edge e, ne;
7570 tree *counts = NULL;
7571 int i;
7572 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7573 OMP_CLAUSE_SAFELEN);
7574 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7575 OMP_CLAUSE__SIMDUID_);
7576 tree n1, n2;
7578 type = TREE_TYPE (fd->loop.v);
7579 entry_bb = region->entry;
7580 cont_bb = region->cont;
7581 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7582 gcc_assert (broken_loop
7583 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7584 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7585 if (!broken_loop)
7587 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7588 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7589 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7590 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7592 else
7594 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7595 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7596 l2_bb = single_succ (l1_bb);
7598 exit_bb = region->exit;
7599 l2_dom_bb = NULL;
7601 gsi = gsi_last_bb (entry_bb);
7603 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7604 /* Not needed in SSA form right now. */
7605 gcc_assert (!gimple_in_ssa_p (cfun));
7606 if (fd->collapse > 1)
7608 int first_zero_iter = -1;
7609 basic_block zero_iter_bb = l2_bb;
7611 counts = XALLOCAVEC (tree, fd->collapse);
7612 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7613 zero_iter_bb, first_zero_iter,
7614 l2_dom_bb);
7616 if (l2_dom_bb == NULL)
7617 l2_dom_bb = l1_bb;
7619 n1 = fd->loop.n1;
7620 n2 = fd->loop.n2;
7621 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7623 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7624 OMP_CLAUSE__LOOPTEMP_);
7625 gcc_assert (innerc);
7626 n1 = OMP_CLAUSE_DECL (innerc);
7627 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7628 OMP_CLAUSE__LOOPTEMP_);
7629 gcc_assert (innerc);
7630 n2 = OMP_CLAUSE_DECL (innerc);
7631 expand_omp_build_assign (&gsi, fd->loop.v,
7632 fold_convert (type, n1));
7633 if (fd->collapse > 1)
7635 gsi_prev (&gsi);
7636 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7637 gsi_next (&gsi);
7640 else
7642 expand_omp_build_assign (&gsi, fd->loop.v,
7643 fold_convert (type, fd->loop.n1));
7644 if (fd->collapse > 1)
7645 for (i = 0; i < fd->collapse; i++)
7647 tree itype = TREE_TYPE (fd->loops[i].v);
7648 if (POINTER_TYPE_P (itype))
7649 itype = signed_type_for (itype);
7650 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7651 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7655 /* Remove the GIMPLE_OMP_FOR statement. */
7656 gsi_remove (&gsi, true);
7658 if (!broken_loop)
7660 /* Code to control the increment goes in the CONT_BB. */
7661 gsi = gsi_last_bb (cont_bb);
7662 stmt = gsi_stmt (gsi);
7663 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7665 if (POINTER_TYPE_P (type))
7666 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7667 else
7668 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7669 expand_omp_build_assign (&gsi, fd->loop.v, t);
7671 if (fd->collapse > 1)
7673 i = fd->collapse - 1;
7674 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7676 t = fold_convert (sizetype, fd->loops[i].step);
7677 t = fold_build_pointer_plus (fd->loops[i].v, t);
7679 else
7681 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7682 fd->loops[i].step);
7683 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7684 fd->loops[i].v, t);
7686 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7688 for (i = fd->collapse - 1; i > 0; i--)
7690 tree itype = TREE_TYPE (fd->loops[i].v);
7691 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7692 if (POINTER_TYPE_P (itype2))
7693 itype2 = signed_type_for (itype2);
7694 t = build3 (COND_EXPR, itype2,
7695 build2 (fd->loops[i].cond_code, boolean_type_node,
7696 fd->loops[i].v,
7697 fold_convert (itype, fd->loops[i].n2)),
7698 build_int_cst (itype2, 0),
7699 fold_convert (itype2, fd->loops[i - 1].step));
7700 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7701 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7702 else
7703 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7704 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7706 t = build3 (COND_EXPR, itype,
7707 build2 (fd->loops[i].cond_code, boolean_type_node,
7708 fd->loops[i].v,
7709 fold_convert (itype, fd->loops[i].n2)),
7710 fd->loops[i].v,
7711 fold_convert (itype, fd->loops[i].n1));
7712 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7716 /* Remove GIMPLE_OMP_CONTINUE. */
7717 gsi_remove (&gsi, true);
7720 /* Emit the condition in L1_BB. */
7721 gsi = gsi_start_bb (l1_bb);
7723 t = fold_convert (type, n2);
7724 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7725 false, GSI_CONTINUE_LINKING);
7726 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7727 cond_stmt = gimple_build_cond_empty (t);
7728 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7729 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7730 NULL, NULL)
7731 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7732 NULL, NULL))
7734 gsi = gsi_for_stmt (cond_stmt);
7735 gimple_regimplify_operands (cond_stmt, &gsi);
7738 /* Remove GIMPLE_OMP_RETURN. */
7739 gsi = gsi_last_bb (exit_bb);
7740 gsi_remove (&gsi, true);
7742 /* Connect the new blocks. */
7743 remove_edge (FALLTHRU_EDGE (entry_bb));
7745 if (!broken_loop)
7747 remove_edge (BRANCH_EDGE (entry_bb));
7748 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7750 e = BRANCH_EDGE (l1_bb);
7751 ne = FALLTHRU_EDGE (l1_bb);
7752 e->flags = EDGE_TRUE_VALUE;
7754 else
7756 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7758 ne = single_succ_edge (l1_bb);
7759 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7762 ne->flags = EDGE_FALSE_VALUE;
7763 e->probability = REG_BR_PROB_BASE * 7 / 8;
7764 ne->probability = REG_BR_PROB_BASE / 8;
7766 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7767 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7768 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7770 if (!broken_loop)
7772 struct loop *loop = alloc_loop ();
7773 loop->header = l1_bb;
7774 loop->latch = cont_bb;
7775 add_loop (loop, l1_bb->loop_father);
7776 if (safelen == NULL_TREE)
7777 loop->safelen = INT_MAX;
7778 else
7780 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7781 if (TREE_CODE (safelen) != INTEGER_CST)
7782 loop->safelen = 0;
7783 else if (!tree_fits_uhwi_p (safelen)
7784 || tree_to_uhwi (safelen) > INT_MAX)
7785 loop->safelen = INT_MAX;
7786 else
7787 loop->safelen = tree_to_uhwi (safelen);
7788 if (loop->safelen == 1)
7789 loop->safelen = 0;
7791 if (simduid)
7793 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7794 cfun->has_simduid_loops = true;
7796 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7797 the loop. */
7798 if ((flag_tree_loop_vectorize
7799 || (!global_options_set.x_flag_tree_loop_vectorize
7800 && !global_options_set.x_flag_tree_vectorize))
7801 && flag_tree_loop_optimize
7802 && loop->safelen > 1)
7804 loop->force_vectorize = true;
7805 cfun->has_force_vectorize_loops = true;
7811 /* Expand the OMP loop defined by REGION. */
7813 static void
7814 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7816 struct omp_for_data fd;
7817 struct omp_for_data_loop *loops;
7819 loops
7820 = (struct omp_for_data_loop *)
7821 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7822 * sizeof (struct omp_for_data_loop));
7823 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7824 &fd, loops);
7825 region->sched_kind = fd.sched_kind;
7827 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7828 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7829 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7830 if (region->cont)
7832 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7833 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7834 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7836 else
7837 /* If there isn't a continue then this is a degerate case where
7838 the introduction of abnormal edges during lowering will prevent
7839 original loops from being detected. Fix that up. */
7840 loops_state_set (LOOPS_NEED_FIXUP);
7842 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7843 expand_omp_simd (region, &fd);
7844 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7845 expand_cilk_for (region, &fd);
7846 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7847 && !fd.have_ordered)
7849 if (fd.chunk_size == NULL)
7850 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7851 else
7852 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7854 else
7856 int fn_index, start_ix, next_ix;
7858 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7859 == GF_OMP_FOR_KIND_FOR);
7860 if (fd.chunk_size == NULL
7861 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7862 fd.chunk_size = integer_zero_node;
7863 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7864 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7865 ? 3 : fd.sched_kind;
7866 fn_index += fd.have_ordered * 4;
7867 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7868 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7869 if (fd.iter_type == long_long_unsigned_type_node)
7871 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7872 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7873 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7874 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7876 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7877 (enum built_in_function) next_ix, inner_stmt);
7880 if (gimple_in_ssa_p (cfun))
7881 update_ssa (TODO_update_ssa_only_virtuals);
7885 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7887 v = GOMP_sections_start (n);
7889 switch (v)
7891 case 0:
7892 goto L2;
7893 case 1:
7894 section 1;
7895 goto L1;
7896 case 2:
7898 case n:
7900 default:
7901 abort ();
7904 v = GOMP_sections_next ();
7905 goto L0;
7907 reduction;
7909 If this is a combined parallel sections, replace the call to
7910 GOMP_sections_start with call to GOMP_sections_next. */
7912 static void
7913 expand_omp_sections (struct omp_region *region)
7915 tree t, u, vin = NULL, vmain, vnext, l2;
7916 unsigned len;
7917 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7918 gimple_stmt_iterator si, switch_si;
7919 gomp_sections *sections_stmt;
7920 gimple stmt;
7921 gomp_continue *cont;
7922 edge_iterator ei;
7923 edge e;
7924 struct omp_region *inner;
7925 unsigned i, casei;
7926 bool exit_reachable = region->cont != NULL;
7928 gcc_assert (region->exit != NULL);
7929 entry_bb = region->entry;
7930 l0_bb = single_succ (entry_bb);
7931 l1_bb = region->cont;
7932 l2_bb = region->exit;
7933 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7934 l2 = gimple_block_label (l2_bb);
7935 else
7937 /* This can happen if there are reductions. */
7938 len = EDGE_COUNT (l0_bb->succs);
7939 gcc_assert (len > 0);
7940 e = EDGE_SUCC (l0_bb, len - 1);
7941 si = gsi_last_bb (e->dest);
7942 l2 = NULL_TREE;
7943 if (gsi_end_p (si)
7944 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7945 l2 = gimple_block_label (e->dest);
7946 else
7947 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7949 si = gsi_last_bb (e->dest);
7950 if (gsi_end_p (si)
7951 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7953 l2 = gimple_block_label (e->dest);
7954 break;
7958 if (exit_reachable)
7959 default_bb = create_empty_bb (l1_bb->prev_bb);
7960 else
7961 default_bb = create_empty_bb (l0_bb);
7963 /* We will build a switch() with enough cases for all the
7964 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7965 and a default case to abort if something goes wrong. */
7966 len = EDGE_COUNT (l0_bb->succs);
7968 /* Use vec::quick_push on label_vec throughout, since we know the size
7969 in advance. */
7970 auto_vec<tree> label_vec (len);
7972 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7973 GIMPLE_OMP_SECTIONS statement. */
7974 si = gsi_last_bb (entry_bb);
7975 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
7976 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7977 vin = gimple_omp_sections_control (sections_stmt);
7978 if (!is_combined_parallel (region))
7980 /* If we are not inside a combined parallel+sections region,
7981 call GOMP_sections_start. */
7982 t = build_int_cst (unsigned_type_node, len - 1);
7983 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7984 stmt = gimple_build_call (u, 1, t);
7986 else
7988 /* Otherwise, call GOMP_sections_next. */
7989 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7990 stmt = gimple_build_call (u, 0);
7992 gimple_call_set_lhs (stmt, vin);
7993 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7994 gsi_remove (&si, true);
7996 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7997 L0_BB. */
7998 switch_si = gsi_last_bb (l0_bb);
7999 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8000 if (exit_reachable)
8002 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8003 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8004 vmain = gimple_omp_continue_control_use (cont);
8005 vnext = gimple_omp_continue_control_def (cont);
8007 else
8009 vmain = vin;
8010 vnext = NULL_TREE;
8013 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8014 label_vec.quick_push (t);
8015 i = 1;
8017 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8018 for (inner = region->inner, casei = 1;
8019 inner;
8020 inner = inner->next, i++, casei++)
8022 basic_block s_entry_bb, s_exit_bb;
8024 /* Skip optional reduction region. */
8025 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8027 --i;
8028 --casei;
8029 continue;
8032 s_entry_bb = inner->entry;
8033 s_exit_bb = inner->exit;
8035 t = gimple_block_label (s_entry_bb);
8036 u = build_int_cst (unsigned_type_node, casei);
8037 u = build_case_label (u, NULL, t);
8038 label_vec.quick_push (u);
8040 si = gsi_last_bb (s_entry_bb);
8041 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8042 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8043 gsi_remove (&si, true);
8044 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8046 if (s_exit_bb == NULL)
8047 continue;
8049 si = gsi_last_bb (s_exit_bb);
8050 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8051 gsi_remove (&si, true);
8053 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8056 /* Error handling code goes in DEFAULT_BB. */
8057 t = gimple_block_label (default_bb);
8058 u = build_case_label (NULL, NULL, t);
8059 make_edge (l0_bb, default_bb, 0);
8060 add_bb_to_loop (default_bb, current_loops->tree_root);
8062 stmt = gimple_build_switch (vmain, u, label_vec);
8063 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8064 gsi_remove (&switch_si, true);
8066 si = gsi_start_bb (default_bb);
8067 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8068 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8070 if (exit_reachable)
8072 tree bfn_decl;
8074 /* Code to get the next section goes in L1_BB. */
8075 si = gsi_last_bb (l1_bb);
8076 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8078 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8079 stmt = gimple_build_call (bfn_decl, 0);
8080 gimple_call_set_lhs (stmt, vnext);
8081 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8082 gsi_remove (&si, true);
8084 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8087 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8088 si = gsi_last_bb (l2_bb);
8089 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8090 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8091 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8092 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8093 else
8094 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8095 stmt = gimple_build_call (t, 0);
8096 if (gimple_omp_return_lhs (gsi_stmt (si)))
8097 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8098 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8099 gsi_remove (&si, true);
8101 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8105 /* Expand code for an OpenMP single directive. We've already expanded
8106 much of the code, here we simply place the GOMP_barrier call. */
8108 static void
8109 expand_omp_single (struct omp_region *region)
8111 basic_block entry_bb, exit_bb;
8112 gimple_stmt_iterator si;
8114 entry_bb = region->entry;
8115 exit_bb = region->exit;
8117 si = gsi_last_bb (entry_bb);
8118 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8119 gsi_remove (&si, true);
8120 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8122 si = gsi_last_bb (exit_bb);
8123 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8125 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8126 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8128 gsi_remove (&si, true);
8129 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8133 /* Generic expansion for OpenMP synchronization directives: master,
8134 ordered and critical. All we need to do here is remove the entry
8135 and exit markers for REGION. */
8137 static void
8138 expand_omp_synch (struct omp_region *region)
8140 basic_block entry_bb, exit_bb;
8141 gimple_stmt_iterator si;
8143 entry_bb = region->entry;
8144 exit_bb = region->exit;
8146 si = gsi_last_bb (entry_bb);
8147 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8148 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8149 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8150 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8151 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8152 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8153 gsi_remove (&si, true);
8154 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8156 if (exit_bb)
8158 si = gsi_last_bb (exit_bb);
8159 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8160 gsi_remove (&si, true);
8161 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8165 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8166 operation as a normal volatile load. */
8168 static bool
8169 expand_omp_atomic_load (basic_block load_bb, tree addr,
8170 tree loaded_val, int index)
8172 enum built_in_function tmpbase;
8173 gimple_stmt_iterator gsi;
8174 basic_block store_bb;
8175 location_t loc;
8176 gimple stmt;
8177 tree decl, call, type, itype;
8179 gsi = gsi_last_bb (load_bb);
8180 stmt = gsi_stmt (gsi);
8181 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8182 loc = gimple_location (stmt);
8184 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8185 is smaller than word size, then expand_atomic_load assumes that the load
8186 is atomic. We could avoid the builtin entirely in this case. */
8188 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8189 decl = builtin_decl_explicit (tmpbase);
8190 if (decl == NULL_TREE)
8191 return false;
8193 type = TREE_TYPE (loaded_val);
8194 itype = TREE_TYPE (TREE_TYPE (decl));
8196 call = build_call_expr_loc (loc, decl, 2, addr,
8197 build_int_cst (NULL,
8198 gimple_omp_atomic_seq_cst_p (stmt)
8199 ? MEMMODEL_SEQ_CST
8200 : MEMMODEL_RELAXED));
8201 if (!useless_type_conversion_p (type, itype))
8202 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8203 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8205 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8206 gsi_remove (&gsi, true);
8208 store_bb = single_succ (load_bb);
8209 gsi = gsi_last_bb (store_bb);
8210 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8211 gsi_remove (&gsi, true);
8213 if (gimple_in_ssa_p (cfun))
8214 update_ssa (TODO_update_ssa_no_phi);
8216 return true;
8219 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8220 operation as a normal volatile store. */
8222 static bool
8223 expand_omp_atomic_store (basic_block load_bb, tree addr,
8224 tree loaded_val, tree stored_val, int index)
8226 enum built_in_function tmpbase;
8227 gimple_stmt_iterator gsi;
8228 basic_block store_bb = single_succ (load_bb);
8229 location_t loc;
8230 gimple stmt;
8231 tree decl, call, type, itype;
8232 machine_mode imode;
8233 bool exchange;
8235 gsi = gsi_last_bb (load_bb);
8236 stmt = gsi_stmt (gsi);
8237 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8239 /* If the load value is needed, then this isn't a store but an exchange. */
8240 exchange = gimple_omp_atomic_need_value_p (stmt);
8242 gsi = gsi_last_bb (store_bb);
8243 stmt = gsi_stmt (gsi);
8244 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8245 loc = gimple_location (stmt);
8247 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8248 is smaller than word size, then expand_atomic_store assumes that the store
8249 is atomic. We could avoid the builtin entirely in this case. */
8251 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8252 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8253 decl = builtin_decl_explicit (tmpbase);
8254 if (decl == NULL_TREE)
8255 return false;
8257 type = TREE_TYPE (stored_val);
8259 /* Dig out the type of the function's second argument. */
8260 itype = TREE_TYPE (decl);
8261 itype = TYPE_ARG_TYPES (itype);
8262 itype = TREE_CHAIN (itype);
8263 itype = TREE_VALUE (itype);
8264 imode = TYPE_MODE (itype);
8266 if (exchange && !can_atomic_exchange_p (imode, true))
8267 return false;
8269 if (!useless_type_conversion_p (itype, type))
8270 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8271 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8272 build_int_cst (NULL,
8273 gimple_omp_atomic_seq_cst_p (stmt)
8274 ? MEMMODEL_SEQ_CST
8275 : MEMMODEL_RELAXED));
8276 if (exchange)
8278 if (!useless_type_conversion_p (type, itype))
8279 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8280 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8283 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8284 gsi_remove (&gsi, true);
8286 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8287 gsi = gsi_last_bb (load_bb);
8288 gsi_remove (&gsi, true);
8290 if (gimple_in_ssa_p (cfun))
8291 update_ssa (TODO_update_ssa_no_phi);
8293 return true;
8296 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8297 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8298 size of the data type, and thus usable to find the index of the builtin
8299 decl. Returns false if the expression is not of the proper form. */
8301 static bool
8302 expand_omp_atomic_fetch_op (basic_block load_bb,
8303 tree addr, tree loaded_val,
8304 tree stored_val, int index)
8306 enum built_in_function oldbase, newbase, tmpbase;
8307 tree decl, itype, call;
8308 tree lhs, rhs;
8309 basic_block store_bb = single_succ (load_bb);
8310 gimple_stmt_iterator gsi;
8311 gimple stmt;
8312 location_t loc;
8313 enum tree_code code;
8314 bool need_old, need_new;
8315 machine_mode imode;
8316 bool seq_cst;
8318 /* We expect to find the following sequences:
8320 load_bb:
8321 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8323 store_bb:
8324 val = tmp OP something; (or: something OP tmp)
8325 GIMPLE_OMP_STORE (val)
8327 ???FIXME: Allow a more flexible sequence.
8328 Perhaps use data flow to pick the statements.
8332 gsi = gsi_after_labels (store_bb);
8333 stmt = gsi_stmt (gsi);
8334 loc = gimple_location (stmt);
8335 if (!is_gimple_assign (stmt))
8336 return false;
8337 gsi_next (&gsi);
8338 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8339 return false;
8340 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8341 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8342 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8343 gcc_checking_assert (!need_old || !need_new);
8345 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8346 return false;
8348 /* Check for one of the supported fetch-op operations. */
8349 code = gimple_assign_rhs_code (stmt);
8350 switch (code)
8352 case PLUS_EXPR:
8353 case POINTER_PLUS_EXPR:
8354 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8355 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8356 break;
8357 case MINUS_EXPR:
8358 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8359 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8360 break;
8361 case BIT_AND_EXPR:
8362 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8363 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8364 break;
8365 case BIT_IOR_EXPR:
8366 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8367 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8368 break;
8369 case BIT_XOR_EXPR:
8370 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8371 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8372 break;
8373 default:
8374 return false;
8377 /* Make sure the expression is of the proper form. */
8378 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8379 rhs = gimple_assign_rhs2 (stmt);
8380 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8381 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8382 rhs = gimple_assign_rhs1 (stmt);
8383 else
8384 return false;
8386 tmpbase = ((enum built_in_function)
8387 ((need_new ? newbase : oldbase) + index + 1));
8388 decl = builtin_decl_explicit (tmpbase);
8389 if (decl == NULL_TREE)
8390 return false;
8391 itype = TREE_TYPE (TREE_TYPE (decl));
8392 imode = TYPE_MODE (itype);
8394 /* We could test all of the various optabs involved, but the fact of the
8395 matter is that (with the exception of i486 vs i586 and xadd) all targets
8396 that support any atomic operaton optab also implements compare-and-swap.
8397 Let optabs.c take care of expanding any compare-and-swap loop. */
8398 if (!can_compare_and_swap_p (imode, true))
8399 return false;
8401 gsi = gsi_last_bb (load_bb);
8402 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8404 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8405 It only requires that the operation happen atomically. Thus we can
8406 use the RELAXED memory model. */
8407 call = build_call_expr_loc (loc, decl, 3, addr,
8408 fold_convert_loc (loc, itype, rhs),
8409 build_int_cst (NULL,
8410 seq_cst ? MEMMODEL_SEQ_CST
8411 : MEMMODEL_RELAXED));
8413 if (need_old || need_new)
8415 lhs = need_old ? loaded_val : stored_val;
8416 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8417 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8419 else
8420 call = fold_convert_loc (loc, void_type_node, call);
8421 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8422 gsi_remove (&gsi, true);
8424 gsi = gsi_last_bb (store_bb);
8425 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8426 gsi_remove (&gsi, true);
8427 gsi = gsi_last_bb (store_bb);
8428 gsi_remove (&gsi, true);
8430 if (gimple_in_ssa_p (cfun))
8431 update_ssa (TODO_update_ssa_no_phi);
8433 return true;
8436 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8438 oldval = *addr;
8439 repeat:
8440 newval = rhs; // with oldval replacing *addr in rhs
8441 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8442 if (oldval != newval)
8443 goto repeat;
8445 INDEX is log2 of the size of the data type, and thus usable to find the
8446 index of the builtin decl. */
8448 static bool
8449 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8450 tree addr, tree loaded_val, tree stored_val,
8451 int index)
8453 tree loadedi, storedi, initial, new_storedi, old_vali;
8454 tree type, itype, cmpxchg, iaddr;
8455 gimple_stmt_iterator si;
8456 basic_block loop_header = single_succ (load_bb);
8457 gimple phi, stmt;
8458 edge e;
8459 enum built_in_function fncode;
8461 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8462 order to use the RELAXED memory model effectively. */
8463 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8464 + index + 1);
8465 cmpxchg = builtin_decl_explicit (fncode);
8466 if (cmpxchg == NULL_TREE)
8467 return false;
8468 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8469 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8471 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8472 return false;
8474 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8475 si = gsi_last_bb (load_bb);
8476 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8478 /* For floating-point values, we'll need to view-convert them to integers
8479 so that we can perform the atomic compare and swap. Simplify the
8480 following code by always setting up the "i"ntegral variables. */
8481 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8483 tree iaddr_val;
8485 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8486 true));
8487 iaddr_val
8488 = force_gimple_operand_gsi (&si,
8489 fold_convert (TREE_TYPE (iaddr), addr),
8490 false, NULL_TREE, true, GSI_SAME_STMT);
8491 stmt = gimple_build_assign (iaddr, iaddr_val);
8492 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8493 loadedi = create_tmp_var (itype);
8494 if (gimple_in_ssa_p (cfun))
8495 loadedi = make_ssa_name (loadedi);
8497 else
8499 iaddr = addr;
8500 loadedi = loaded_val;
8503 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8504 tree loaddecl = builtin_decl_explicit (fncode);
8505 if (loaddecl)
8506 initial
8507 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8508 build_call_expr (loaddecl, 2, iaddr,
8509 build_int_cst (NULL_TREE,
8510 MEMMODEL_RELAXED)));
8511 else
8512 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8513 build_int_cst (TREE_TYPE (iaddr), 0));
8515 initial
8516 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8517 GSI_SAME_STMT);
8519 /* Move the value to the LOADEDI temporary. */
8520 if (gimple_in_ssa_p (cfun))
8522 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8523 phi = create_phi_node (loadedi, loop_header);
8524 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8525 initial);
8527 else
8528 gsi_insert_before (&si,
8529 gimple_build_assign (loadedi, initial),
8530 GSI_SAME_STMT);
8531 if (loadedi != loaded_val)
8533 gimple_stmt_iterator gsi2;
8534 tree x;
8536 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8537 gsi2 = gsi_start_bb (loop_header);
8538 if (gimple_in_ssa_p (cfun))
8540 gassign *stmt;
8541 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8542 true, GSI_SAME_STMT);
8543 stmt = gimple_build_assign (loaded_val, x);
8544 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8546 else
8548 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8549 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8550 true, GSI_SAME_STMT);
8553 gsi_remove (&si, true);
8555 si = gsi_last_bb (store_bb);
8556 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8558 if (iaddr == addr)
8559 storedi = stored_val;
8560 else
8561 storedi =
8562 force_gimple_operand_gsi (&si,
8563 build1 (VIEW_CONVERT_EXPR, itype,
8564 stored_val), true, NULL_TREE, true,
8565 GSI_SAME_STMT);
8567 /* Build the compare&swap statement. */
8568 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8569 new_storedi = force_gimple_operand_gsi (&si,
8570 fold_convert (TREE_TYPE (loadedi),
8571 new_storedi),
8572 true, NULL_TREE,
8573 true, GSI_SAME_STMT);
8575 if (gimple_in_ssa_p (cfun))
8576 old_vali = loadedi;
8577 else
8579 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8580 stmt = gimple_build_assign (old_vali, loadedi);
8581 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8583 stmt = gimple_build_assign (loadedi, new_storedi);
8584 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8587 /* Note that we always perform the comparison as an integer, even for
8588 floating point. This allows the atomic operation to properly
8589 succeed even with NaNs and -0.0. */
8590 stmt = gimple_build_cond_empty
8591 (build2 (NE_EXPR, boolean_type_node,
8592 new_storedi, old_vali));
8593 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8595 /* Update cfg. */
8596 e = single_succ_edge (store_bb);
8597 e->flags &= ~EDGE_FALLTHRU;
8598 e->flags |= EDGE_FALSE_VALUE;
8600 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8602 /* Copy the new value to loadedi (we already did that before the condition
8603 if we are not in SSA). */
8604 if (gimple_in_ssa_p (cfun))
8606 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8607 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8610 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8611 gsi_remove (&si, true);
8613 struct loop *loop = alloc_loop ();
8614 loop->header = loop_header;
8615 loop->latch = store_bb;
8616 add_loop (loop, loop_header->loop_father);
8618 if (gimple_in_ssa_p (cfun))
8619 update_ssa (TODO_update_ssa_no_phi);
8621 return true;
8624 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8626 GOMP_atomic_start ();
8627 *addr = rhs;
8628 GOMP_atomic_end ();
8630 The result is not globally atomic, but works so long as all parallel
8631 references are within #pragma omp atomic directives. According to
8632 responses received from omp@openmp.org, appears to be within spec.
8633 Which makes sense, since that's how several other compilers handle
8634 this situation as well.
8635 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8636 expanding. STORED_VAL is the operand of the matching
8637 GIMPLE_OMP_ATOMIC_STORE.
8639 We replace
8640 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8641 loaded_val = *addr;
8643 and replace
8644 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8645 *addr = stored_val;
8648 static bool
8649 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8650 tree addr, tree loaded_val, tree stored_val)
8652 gimple_stmt_iterator si;
8653 gassign *stmt;
8654 tree t;
8656 si = gsi_last_bb (load_bb);
8657 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8659 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8660 t = build_call_expr (t, 0);
8661 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8663 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8664 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8665 gsi_remove (&si, true);
8667 si = gsi_last_bb (store_bb);
8668 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8670 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8671 stored_val);
8672 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8674 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8675 t = build_call_expr (t, 0);
8676 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8677 gsi_remove (&si, true);
8679 if (gimple_in_ssa_p (cfun))
8680 update_ssa (TODO_update_ssa_no_phi);
8681 return true;
8684 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8685 using expand_omp_atomic_fetch_op. If it failed, we try to
8686 call expand_omp_atomic_pipeline, and if it fails too, the
8687 ultimate fallback is wrapping the operation in a mutex
8688 (expand_omp_atomic_mutex). REGION is the atomic region built
8689 by build_omp_regions_1(). */
8691 static void
8692 expand_omp_atomic (struct omp_region *region)
8694 basic_block load_bb = region->entry, store_bb = region->exit;
8695 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8696 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8697 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8698 tree addr = gimple_omp_atomic_load_rhs (load);
8699 tree stored_val = gimple_omp_atomic_store_val (store);
8700 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8701 HOST_WIDE_INT index;
8703 /* Make sure the type is one of the supported sizes. */
8704 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8705 index = exact_log2 (index);
8706 if (index >= 0 && index <= 4)
8708 unsigned int align = TYPE_ALIGN_UNIT (type);
8710 /* __sync builtins require strict data alignment. */
8711 if (exact_log2 (align) >= index)
8713 /* Atomic load. */
8714 if (loaded_val == stored_val
8715 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8716 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8717 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8718 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8719 return;
8721 /* Atomic store. */
8722 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8723 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8724 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8725 && store_bb == single_succ (load_bb)
8726 && first_stmt (store_bb) == store
8727 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8728 stored_val, index))
8729 return;
8731 /* When possible, use specialized atomic update functions. */
8732 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8733 && store_bb == single_succ (load_bb)
8734 && expand_omp_atomic_fetch_op (load_bb, addr,
8735 loaded_val, stored_val, index))
8736 return;
8738 /* If we don't have specialized __sync builtins, try and implement
8739 as a compare and swap loop. */
8740 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8741 loaded_val, stored_val, index))
8742 return;
8746 /* The ultimate fallback is wrapping the operation in a mutex. */
8747 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8751 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8753 static void
8754 expand_omp_target (struct omp_region *region)
8756 basic_block entry_bb, exit_bb, new_bb;
8757 struct function *child_cfun;
8758 tree child_fn, block, t;
8759 gimple_stmt_iterator gsi;
8760 gomp_target *entry_stmt;
8761 gimple stmt;
8762 edge e;
8763 bool offloaded, data_region;
8765 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8766 new_bb = region->entry;
8768 offloaded = is_gimple_omp_offloaded (entry_stmt);
8769 switch (gimple_omp_target_kind (entry_stmt))
8771 case GF_OMP_TARGET_KIND_REGION:
8772 case GF_OMP_TARGET_KIND_UPDATE:
8773 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8774 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8775 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8776 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8777 data_region = false;
8778 break;
8779 case GF_OMP_TARGET_KIND_DATA:
8780 case GF_OMP_TARGET_KIND_OACC_DATA:
8781 data_region = true;
8782 break;
8783 default:
8784 gcc_unreachable ();
8787 child_fn = NULL_TREE;
8788 child_cfun = NULL;
8789 if (offloaded)
8791 child_fn = gimple_omp_target_child_fn (entry_stmt);
8792 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8795 /* Supported by expand_omp_taskreg, but not here. */
8796 if (child_cfun != NULL)
8797 gcc_checking_assert (!child_cfun->cfg);
8798 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8800 entry_bb = region->entry;
8801 exit_bb = region->exit;
8803 if (offloaded)
8805 unsigned srcidx, dstidx, num;
8807 /* If the offloading region needs data sent from the parent
8808 function, then the very first statement (except possible
8809 tree profile counter updates) of the offloading body
8810 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8811 &.OMP_DATA_O is passed as an argument to the child function,
8812 we need to replace it with the argument as seen by the child
8813 function.
8815 In most cases, this will end up being the identity assignment
8816 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8817 a function call that has been inlined, the original PARM_DECL
8818 .OMP_DATA_I may have been converted into a different local
8819 variable. In which case, we need to keep the assignment. */
8820 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8821 if (data_arg)
8823 basic_block entry_succ_bb = single_succ (entry_bb);
8824 gimple_stmt_iterator gsi;
8825 tree arg;
8826 gimple tgtcopy_stmt = NULL;
8827 tree sender = TREE_VEC_ELT (data_arg, 0);
8829 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8831 gcc_assert (!gsi_end_p (gsi));
8832 stmt = gsi_stmt (gsi);
8833 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8834 continue;
8836 if (gimple_num_ops (stmt) == 2)
8838 tree arg = gimple_assign_rhs1 (stmt);
8840 /* We're ignoring the subcode because we're
8841 effectively doing a STRIP_NOPS. */
8843 if (TREE_CODE (arg) == ADDR_EXPR
8844 && TREE_OPERAND (arg, 0) == sender)
8846 tgtcopy_stmt = stmt;
8847 break;
8852 gcc_assert (tgtcopy_stmt != NULL);
8853 arg = DECL_ARGUMENTS (child_fn);
8855 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8856 gsi_remove (&gsi, true);
8859 /* Declare local variables needed in CHILD_CFUN. */
8860 block = DECL_INITIAL (child_fn);
8861 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8862 /* The gimplifier could record temporaries in the offloading block
8863 rather than in containing function's local_decls chain,
8864 which would mean cgraph missed finalizing them. Do it now. */
8865 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8866 if (TREE_CODE (t) == VAR_DECL
8867 && TREE_STATIC (t)
8868 && !DECL_EXTERNAL (t))
8869 varpool_node::finalize_decl (t);
8870 DECL_SAVED_TREE (child_fn) = NULL;
8871 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8872 gimple_set_body (child_fn, NULL);
8873 TREE_USED (block) = 1;
8875 /* Reset DECL_CONTEXT on function arguments. */
8876 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8877 DECL_CONTEXT (t) = child_fn;
8879 /* Split ENTRY_BB at GIMPLE_*,
8880 so that it can be moved to the child function. */
8881 gsi = gsi_last_bb (entry_bb);
8882 stmt = gsi_stmt (gsi);
8883 gcc_assert (stmt
8884 && gimple_code (stmt) == gimple_code (entry_stmt));
8885 gsi_remove (&gsi, true);
8886 e = split_block (entry_bb, stmt);
8887 entry_bb = e->dest;
8888 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8890 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8891 if (exit_bb)
8893 gsi = gsi_last_bb (exit_bb);
8894 gcc_assert (!gsi_end_p (gsi)
8895 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8896 stmt = gimple_build_return (NULL);
8897 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8898 gsi_remove (&gsi, true);
8901 /* Move the offloading region into CHILD_CFUN. */
8903 block = gimple_block (entry_stmt);
8905 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8906 if (exit_bb)
8907 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8908 /* When the OMP expansion process cannot guarantee an up-to-date
8909 loop tree arrange for the child function to fixup loops. */
8910 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8911 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8913 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8914 num = vec_safe_length (child_cfun->local_decls);
8915 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8917 t = (*child_cfun->local_decls)[srcidx];
8918 if (DECL_CONTEXT (t) == cfun->decl)
8919 continue;
8920 if (srcidx != dstidx)
8921 (*child_cfun->local_decls)[dstidx] = t;
8922 dstidx++;
8924 if (dstidx != num)
8925 vec_safe_truncate (child_cfun->local_decls, dstidx);
8927 /* Inform the callgraph about the new function. */
8928 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8929 cgraph_node::add_new_function (child_fn, true);
8931 #ifdef ENABLE_OFFLOADING
8932 /* Add the new function to the offload table. */
8933 vec_safe_push (offload_funcs, child_fn);
8934 #endif
8936 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8937 fixed in a following pass. */
8938 push_cfun (child_cfun);
8939 cgraph_edge::rebuild_edges ();
8941 #ifdef ENABLE_OFFLOADING
8942 /* Prevent IPA from removing child_fn as unreachable, since there are no
8943 refs from the parent function to child_fn in offload LTO mode. */
8944 struct cgraph_node *node = cgraph_node::get (child_fn);
8945 node->mark_force_output ();
8946 #endif
8948 /* Some EH regions might become dead, see PR34608. If
8949 pass_cleanup_cfg isn't the first pass to happen with the
8950 new child, these dead EH edges might cause problems.
8951 Clean them up now. */
8952 if (flag_exceptions)
8954 basic_block bb;
8955 bool changed = false;
8957 FOR_EACH_BB_FN (bb, cfun)
8958 changed |= gimple_purge_dead_eh_edges (bb);
8959 if (changed)
8960 cleanup_tree_cfg ();
8962 pop_cfun ();
8965 /* Emit a library call to launch the offloading region, or do data
8966 transfers. */
8967 tree t1, t2, t3, t4, device, cond, c, clauses;
8968 enum built_in_function start_ix;
8969 location_t clause_loc;
8971 switch (gimple_omp_target_kind (entry_stmt))
8973 case GF_OMP_TARGET_KIND_REGION:
8974 start_ix = BUILT_IN_GOMP_TARGET;
8975 break;
8976 case GF_OMP_TARGET_KIND_DATA:
8977 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8978 break;
8979 case GF_OMP_TARGET_KIND_UPDATE:
8980 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8981 break;
8982 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8983 start_ix = BUILT_IN_GOACC_PARALLEL;
8984 break;
8985 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8986 start_ix = BUILT_IN_GOACC_KERNELS;
8987 break;
8988 case GF_OMP_TARGET_KIND_OACC_DATA:
8989 start_ix = BUILT_IN_GOACC_DATA_START;
8990 break;
8991 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8992 start_ix = BUILT_IN_GOACC_UPDATE;
8993 break;
8994 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8995 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
8996 break;
8997 default:
8998 gcc_unreachable ();
9001 clauses = gimple_omp_target_clauses (entry_stmt);
9003 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9004 library choose) and there is no conditional. */
9005 cond = NULL_TREE;
9006 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9008 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9009 if (c)
9010 cond = OMP_CLAUSE_IF_EXPR (c);
9012 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9013 if (c)
9015 /* Even if we pass it to all library function calls, it is currently only
9016 defined/used for the OpenMP target ones. */
9017 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9018 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9019 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9021 device = OMP_CLAUSE_DEVICE_ID (c);
9022 clause_loc = OMP_CLAUSE_LOCATION (c);
9024 else
9025 clause_loc = gimple_location (entry_stmt);
9027 /* Ensure 'device' is of the correct type. */
9028 device = fold_convert_loc (clause_loc, integer_type_node, device);
9030 /* If we found the clause 'if (cond)', build
9031 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9032 if (cond)
9034 cond = gimple_boolify (cond);
9036 basic_block cond_bb, then_bb, else_bb;
9037 edge e;
9038 tree tmp_var;
9040 tmp_var = create_tmp_var (TREE_TYPE (device));
9041 if (offloaded)
9042 e = split_block (new_bb, NULL);
9043 else
9045 gsi = gsi_last_bb (new_bb);
9046 gsi_prev (&gsi);
9047 e = split_block (new_bb, gsi_stmt (gsi));
9049 cond_bb = e->src;
9050 new_bb = e->dest;
9051 remove_edge (e);
9053 then_bb = create_empty_bb (cond_bb);
9054 else_bb = create_empty_bb (then_bb);
9055 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9056 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9058 stmt = gimple_build_cond_empty (cond);
9059 gsi = gsi_last_bb (cond_bb);
9060 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9062 gsi = gsi_start_bb (then_bb);
9063 stmt = gimple_build_assign (tmp_var, device);
9064 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9066 gsi = gsi_start_bb (else_bb);
9067 stmt = gimple_build_assign (tmp_var,
9068 build_int_cst (integer_type_node,
9069 GOMP_DEVICE_HOST_FALLBACK));
9070 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9072 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9073 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9074 add_bb_to_loop (then_bb, cond_bb->loop_father);
9075 add_bb_to_loop (else_bb, cond_bb->loop_father);
9076 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9077 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9079 device = tmp_var;
9082 gsi = gsi_last_bb (new_bb);
9083 t = gimple_omp_target_data_arg (entry_stmt);
9084 if (t == NULL)
9086 t1 = size_zero_node;
9087 t2 = build_zero_cst (ptr_type_node);
9088 t3 = t2;
9089 t4 = t2;
9091 else
9093 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9094 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9095 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9096 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9097 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9100 gimple g;
9101 vec<tree> *args;
9102 /* The maximum number used by any start_ix, without varargs. */
9103 unsigned int argcnt = 11;
9105 vec_alloc (args, argcnt);
9106 args->quick_push (device);
9107 if (offloaded)
9108 args->quick_push (build_fold_addr_expr (child_fn));
9109 switch (start_ix)
9111 case BUILT_IN_GOMP_TARGET:
9112 case BUILT_IN_GOMP_TARGET_DATA:
9113 case BUILT_IN_GOMP_TARGET_UPDATE:
9114 /* This const void * is part of the current ABI, but we're not actually
9115 using it. */
9116 args->quick_push (build_zero_cst (ptr_type_node));
9117 break;
9118 case BUILT_IN_GOACC_DATA_START:
9119 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9120 case BUILT_IN_GOACC_KERNELS:
9121 case BUILT_IN_GOACC_PARALLEL:
9122 case BUILT_IN_GOACC_UPDATE:
9123 break;
9124 default:
9125 gcc_unreachable ();
9127 args->quick_push (t1);
9128 args->quick_push (t2);
9129 args->quick_push (t3);
9130 args->quick_push (t4);
9131 switch (start_ix)
9133 case BUILT_IN_GOACC_DATA_START:
9134 case BUILT_IN_GOMP_TARGET:
9135 case BUILT_IN_GOMP_TARGET_DATA:
9136 case BUILT_IN_GOMP_TARGET_UPDATE:
9137 break;
9138 case BUILT_IN_GOACC_KERNELS:
9139 case BUILT_IN_GOACC_PARALLEL:
9141 tree t_num_gangs, t_num_workers, t_vector_length;
9143 /* Default values for num_gangs, num_workers, and vector_length. */
9144 t_num_gangs = t_num_workers = t_vector_length
9145 = fold_convert_loc (gimple_location (entry_stmt),
9146 integer_type_node, integer_one_node);
9147 /* ..., but if present, use the value specified by the respective
9148 clause, making sure that are of the correct type. */
9149 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9150 if (c)
9151 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9152 integer_type_node,
9153 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9154 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9155 if (c)
9156 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9157 integer_type_node,
9158 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9159 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9160 if (c)
9161 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9162 integer_type_node,
9163 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9164 args->quick_push (t_num_gangs);
9165 args->quick_push (t_num_workers);
9166 args->quick_push (t_vector_length);
9168 /* FALLTHRU */
9169 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9170 case BUILT_IN_GOACC_UPDATE:
9172 tree t_async;
9173 int t_wait_idx;
9175 /* Default values for t_async. */
9176 t_async = fold_convert_loc (gimple_location (entry_stmt),
9177 integer_type_node,
9178 build_int_cst (integer_type_node,
9179 GOMP_ASYNC_SYNC));
9180 /* ..., but if present, use the value specified by the respective
9181 clause, making sure that is of the correct type. */
9182 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9183 if (c)
9184 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9185 integer_type_node,
9186 OMP_CLAUSE_ASYNC_EXPR (c));
9188 args->quick_push (t_async);
9189 /* Save the index, and... */
9190 t_wait_idx = args->length ();
9191 /* ... push a default value. */
9192 args->quick_push (fold_convert_loc (gimple_location (entry_stmt),
9193 integer_type_node,
9194 integer_zero_node));
9195 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9196 if (c)
9198 int n = 0;
9200 for (; c; c = OMP_CLAUSE_CHAIN (c))
9202 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9204 args->safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9205 integer_type_node,
9206 OMP_CLAUSE_WAIT_EXPR (c)));
9207 n++;
9211 /* Now that we know the number, replace the default value. */
9212 args->ordered_remove (t_wait_idx);
9213 args->quick_insert (t_wait_idx,
9214 fold_convert_loc (gimple_location (entry_stmt),
9215 integer_type_node,
9216 build_int_cst (integer_type_node, n)));
9219 break;
9220 default:
9221 gcc_unreachable ();
9224 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), *args);
9225 args->release ();
9226 gimple_set_location (g, gimple_location (entry_stmt));
9227 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9228 if (!offloaded)
9230 g = gsi_stmt (gsi);
9231 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9232 gsi_remove (&gsi, true);
9234 if (data_region
9235 && region->exit)
9237 gsi = gsi_last_bb (region->exit);
9238 g = gsi_stmt (gsi);
9239 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9240 gsi_remove (&gsi, true);
9245 /* Expand the parallel region tree rooted at REGION. Expansion
9246 proceeds in depth-first order. Innermost regions are expanded
9247 first. This way, parallel regions that require a new function to
9248 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9249 internal dependencies in their body. */
9251 static void
9252 expand_omp (struct omp_region *region)
9254 while (region)
9256 location_t saved_location;
9257 gimple inner_stmt = NULL;
9259 /* First, determine whether this is a combined parallel+workshare
9260 region. */
9261 if (region->type == GIMPLE_OMP_PARALLEL)
9262 determine_parallel_type (region);
9264 if (region->type == GIMPLE_OMP_FOR
9265 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9266 inner_stmt = last_stmt (region->inner->entry);
9268 if (region->inner)
9269 expand_omp (region->inner);
9271 saved_location = input_location;
9272 if (gimple_has_location (last_stmt (region->entry)))
9273 input_location = gimple_location (last_stmt (region->entry));
9275 switch (region->type)
9277 case GIMPLE_OMP_PARALLEL:
9278 case GIMPLE_OMP_TASK:
9279 expand_omp_taskreg (region);
9280 break;
9282 case GIMPLE_OMP_FOR:
9283 expand_omp_for (region, inner_stmt);
9284 break;
9286 case GIMPLE_OMP_SECTIONS:
9287 expand_omp_sections (region);
9288 break;
9290 case GIMPLE_OMP_SECTION:
9291 /* Individual omp sections are handled together with their
9292 parent GIMPLE_OMP_SECTIONS region. */
9293 break;
9295 case GIMPLE_OMP_SINGLE:
9296 expand_omp_single (region);
9297 break;
9299 case GIMPLE_OMP_MASTER:
9300 case GIMPLE_OMP_TASKGROUP:
9301 case GIMPLE_OMP_ORDERED:
9302 case GIMPLE_OMP_CRITICAL:
9303 case GIMPLE_OMP_TEAMS:
9304 expand_omp_synch (region);
9305 break;
9307 case GIMPLE_OMP_ATOMIC_LOAD:
9308 expand_omp_atomic (region);
9309 break;
9311 case GIMPLE_OMP_TARGET:
9312 expand_omp_target (region);
9313 break;
9315 default:
9316 gcc_unreachable ();
9319 input_location = saved_location;
9320 region = region->next;
9325 /* Helper for build_omp_regions. Scan the dominator tree starting at
9326 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9327 true, the function ends once a single tree is built (otherwise, whole
9328 forest of OMP constructs may be built). */
9330 static void
9331 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9332 bool single_tree)
9334 gimple_stmt_iterator gsi;
9335 gimple stmt;
9336 basic_block son;
9338 gsi = gsi_last_bb (bb);
9339 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9341 struct omp_region *region;
9342 enum gimple_code code;
9344 stmt = gsi_stmt (gsi);
9345 code = gimple_code (stmt);
9346 if (code == GIMPLE_OMP_RETURN)
9348 /* STMT is the return point out of region PARENT. Mark it
9349 as the exit point and make PARENT the immediately
9350 enclosing region. */
9351 gcc_assert (parent);
9352 region = parent;
9353 region->exit = bb;
9354 parent = parent->outer;
9356 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9358 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9359 GIMPLE_OMP_RETURN, but matches with
9360 GIMPLE_OMP_ATOMIC_LOAD. */
9361 gcc_assert (parent);
9362 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9363 region = parent;
9364 region->exit = bb;
9365 parent = parent->outer;
9367 else if (code == GIMPLE_OMP_CONTINUE)
9369 gcc_assert (parent);
9370 parent->cont = bb;
9372 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9374 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9375 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9377 else
9379 region = new_omp_region (bb, code, parent);
9380 /* Otherwise... */
9381 if (code == GIMPLE_OMP_TARGET)
9383 switch (gimple_omp_target_kind (stmt))
9385 case GF_OMP_TARGET_KIND_REGION:
9386 case GF_OMP_TARGET_KIND_DATA:
9387 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9388 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9389 case GF_OMP_TARGET_KIND_OACC_DATA:
9390 break;
9391 case GF_OMP_TARGET_KIND_UPDATE:
9392 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9393 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9394 /* ..., other than for those stand-alone directives... */
9395 region = NULL;
9396 break;
9397 default:
9398 gcc_unreachable ();
9401 /* ..., this directive becomes the parent for a new region. */
9402 if (region)
9403 parent = region;
9407 if (single_tree && !parent)
9408 return;
9410 for (son = first_dom_son (CDI_DOMINATORS, bb);
9411 son;
9412 son = next_dom_son (CDI_DOMINATORS, son))
9413 build_omp_regions_1 (son, parent, single_tree);
9416 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9417 root_omp_region. */
9419 static void
9420 build_omp_regions_root (basic_block root)
9422 gcc_assert (root_omp_region == NULL);
9423 build_omp_regions_1 (root, NULL, true);
9424 gcc_assert (root_omp_region != NULL);
9427 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9429 void
9430 omp_expand_local (basic_block head)
9432 build_omp_regions_root (head);
9433 if (dump_file && (dump_flags & TDF_DETAILS))
9435 fprintf (dump_file, "\nOMP region tree\n\n");
9436 dump_omp_region (dump_file, root_omp_region, 0);
9437 fprintf (dump_file, "\n");
9440 remove_exit_barriers (root_omp_region);
9441 expand_omp (root_omp_region);
9443 free_omp_regions ();
9446 /* Scan the CFG and build a tree of OMP regions. Return the root of
9447 the OMP region tree. */
9449 static void
9450 build_omp_regions (void)
9452 gcc_assert (root_omp_region == NULL);
9453 calculate_dominance_info (CDI_DOMINATORS);
9454 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9457 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9459 static unsigned int
9460 execute_expand_omp (void)
9462 build_omp_regions ();
9464 if (!root_omp_region)
9465 return 0;
9467 if (dump_file)
9469 fprintf (dump_file, "\nOMP region tree\n\n");
9470 dump_omp_region (dump_file, root_omp_region, 0);
9471 fprintf (dump_file, "\n");
9474 remove_exit_barriers (root_omp_region);
9476 expand_omp (root_omp_region);
9478 cleanup_tree_cfg ();
9480 free_omp_regions ();
9482 return 0;
9485 /* OMP expansion -- the default pass, run before creation of SSA form. */
9487 namespace {
9489 const pass_data pass_data_expand_omp =
9491 GIMPLE_PASS, /* type */
9492 "ompexp", /* name */
9493 OPTGROUP_NONE, /* optinfo_flags */
9494 TV_NONE, /* tv_id */
9495 PROP_gimple_any, /* properties_required */
9496 PROP_gimple_eomp, /* properties_provided */
9497 0, /* properties_destroyed */
9498 0, /* todo_flags_start */
9499 0, /* todo_flags_finish */
9502 class pass_expand_omp : public gimple_opt_pass
9504 public:
9505 pass_expand_omp (gcc::context *ctxt)
9506 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9509 /* opt_pass methods: */
9510 virtual unsigned int execute (function *)
9512 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9513 || flag_openmp_simd != 0)
9514 && !seen_error ());
9516 /* This pass always runs, to provide PROP_gimple_eomp.
9517 But often, there is nothing to do. */
9518 if (!gate)
9519 return 0;
9521 return execute_expand_omp ();
9524 }; // class pass_expand_omp
9526 } // anon namespace
9528 gimple_opt_pass *
9529 make_pass_expand_omp (gcc::context *ctxt)
9531 return new pass_expand_omp (ctxt);
9534 namespace {
9536 const pass_data pass_data_expand_omp_ssa =
9538 GIMPLE_PASS, /* type */
9539 "ompexpssa", /* name */
9540 OPTGROUP_NONE, /* optinfo_flags */
9541 TV_NONE, /* tv_id */
9542 PROP_cfg | PROP_ssa, /* properties_required */
9543 PROP_gimple_eomp, /* properties_provided */
9544 0, /* properties_destroyed */
9545 0, /* todo_flags_start */
9546 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9549 class pass_expand_omp_ssa : public gimple_opt_pass
9551 public:
9552 pass_expand_omp_ssa (gcc::context *ctxt)
9553 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9556 /* opt_pass methods: */
9557 virtual bool gate (function *fun)
9559 return !(fun->curr_properties & PROP_gimple_eomp);
9561 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9563 }; // class pass_expand_omp_ssa
9565 } // anon namespace
9567 gimple_opt_pass *
9568 make_pass_expand_omp_ssa (gcc::context *ctxt)
9570 return new pass_expand_omp_ssa (ctxt);
9573 /* Routines to lower OMP directives into OMP-GIMPLE. */
9575 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9576 convert it to gimple. */
9577 static void
9578 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9580 gimple stmt;
9582 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9584 stmt = gimple_build_assign (dest, op, dest, src);
9585 gimple_seq_add_stmt (seq, stmt);
9586 return;
9589 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9590 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9591 gimplify_assign (t, rdest, seq);
9592 rdest = t;
9594 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9595 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9596 gimplify_assign (t, idest, seq);
9597 idest = t;
9599 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9600 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9601 gimplify_assign (t, rsrc, seq);
9602 rsrc = t;
9604 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9605 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9606 gimplify_assign (t, isrc, seq);
9607 isrc = t;
9609 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9610 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9611 tree result;
9613 if (op == PLUS_EXPR)
9615 stmt = gimple_build_assign (r, op, rdest, rsrc);
9616 gimple_seq_add_stmt (seq, stmt);
9618 stmt = gimple_build_assign (i, op, idest, isrc);
9619 gimple_seq_add_stmt (seq, stmt);
9621 else if (op == MULT_EXPR)
9623 /* Let x = a + ib = dest, y = c + id = src.
9624 x * y = (ac - bd) + i(ad + bc) */
9625 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9626 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9627 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9628 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9630 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9631 gimple_seq_add_stmt (seq, stmt);
9633 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9634 gimple_seq_add_stmt (seq, stmt);
9636 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9637 gimple_seq_add_stmt (seq, stmt);
9639 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9640 gimple_seq_add_stmt (seq, stmt);
9642 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9643 gimple_seq_add_stmt (seq, stmt);
9645 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9646 gimple_seq_add_stmt (seq, stmt);
9648 else
9649 gcc_unreachable ();
9651 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9652 gimplify_assign (dest, result, seq);
9655 /* Helper function to initialize local data for the reduction arrays.
9656 The reduction arrays need to be placed inside the calling function
9657 for accelerators, or else the host won't be able to preform the final
9658 reduction. */
9660 static void
9661 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9662 gimple_seq *stmt_seqp, omp_context *ctx)
9664 tree c, t, oc;
9665 gimple stmt;
9666 omp_context *octx;
9668 /* Find the innermost OpenACC parallel context. */
9669 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9670 && (gimple_omp_target_kind (ctx->stmt)
9671 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9672 octx = ctx;
9673 else
9674 octx = ctx->outer;
9675 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9676 && (gimple_omp_target_kind (octx->stmt)
9677 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9679 /* Extract the clauses. */
9680 oc = gimple_omp_target_clauses (octx->stmt);
9682 /* Find the last outer clause. */
9683 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9686 /* Allocate arrays for each reduction variable. */
9687 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9689 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9690 continue;
9692 tree var = OMP_CLAUSE_DECL (c);
9693 tree type = get_base_type (var);
9694 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9695 ctx);
9696 tree size, call;
9698 /* Calculate size of the reduction array. */
9699 t = create_tmp_var (TREE_TYPE (nthreads));
9700 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9701 fold_convert (TREE_TYPE (nthreads),
9702 TYPE_SIZE_UNIT (type)));
9703 gimple_seq_add_stmt (stmt_seqp, stmt);
9705 size = create_tmp_var (sizetype);
9706 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9708 /* Now allocate memory for it. */
9709 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9710 stmt = gimple_build_call (call, 1, size);
9711 gimple_call_set_lhs (stmt, array);
9712 gimple_seq_add_stmt (stmt_seqp, stmt);
9714 /* Map this array into the accelerator. */
9716 /* Add the reduction array to the list of clauses. */
9717 tree x = array;
9718 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9719 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9720 OMP_CLAUSE_DECL (t) = x;
9721 OMP_CLAUSE_CHAIN (t) = NULL;
9722 if (oc)
9723 OMP_CLAUSE_CHAIN (oc) = t;
9724 else
9725 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9726 OMP_CLAUSE_SIZE (t) = size;
9727 oc = t;
9731 /* Helper function to process the array of partial reductions. Nthreads
9732 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9733 cannot be used here, because nthreads on the host may be different than
9734 on the accelerator. */
9736 static void
9737 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9738 gimple_seq *stmt_seqp, omp_context *ctx)
9740 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9741 gimple stmt;
9743 /* Create for loop.
9745 let var = the original reduction variable
9746 let array = reduction variable array
9748 for (i = 0; i < nthreads; i++)
9749 var op= array[i]
9752 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9753 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9754 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9756 /* Create and initialize an index variable. */
9757 tree ix = create_tmp_var (sizetype);
9758 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9759 stmt_seqp);
9761 /* Insert the loop header label here. */
9762 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9764 /* Exit loop if ix >= nthreads. */
9765 x = create_tmp_var (sizetype);
9766 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9767 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9768 gimple_seq_add_stmt (stmt_seqp, stmt);
9770 /* Insert the loop body label here. */
9771 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9773 /* Collapse each reduction array, one element at a time. */
9774 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9776 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9777 continue;
9779 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9781 /* reduction(-:var) sums up the partial results, so it acts
9782 identically to reduction(+:var). */
9783 if (reduction_code == MINUS_EXPR)
9784 reduction_code = PLUS_EXPR;
9786 /* Set up reduction variable var. */
9787 var = OMP_CLAUSE_DECL (c);
9788 type = get_base_type (var);
9789 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9790 (OMP_CLAUSE_DECL (c)), ctx);
9792 /* Calculate the array offset. */
9793 tree offset = create_tmp_var (sizetype);
9794 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9795 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9796 gimple_seq_add_stmt (stmt_seqp, stmt);
9798 tree ptr = create_tmp_var (TREE_TYPE (array));
9799 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9800 gimple_seq_add_stmt (stmt_seqp, stmt);
9802 /* Extract array[ix] into mem. */
9803 tree mem = create_tmp_var (type);
9804 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9806 /* Find the original reduction variable. */
9807 if (is_reference (var))
9808 var = build_simple_mem_ref (var);
9810 tree t = create_tmp_var (type);
9812 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9813 gimplify_and_add (unshare_expr(x), stmt_seqp);
9815 /* var = var op mem */
9816 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9818 case TRUTH_ANDIF_EXPR:
9819 case TRUTH_ORIF_EXPR:
9820 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9821 t, mem);
9822 gimplify_and_add (t, stmt_seqp);
9823 break;
9824 default:
9825 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9826 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9827 stmt_seqp);
9830 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9831 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9832 gimplify_and_add (unshare_expr(x), stmt_seqp);
9835 /* Increment the induction variable. */
9836 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9837 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9838 gimple_seq_add_stmt (stmt_seqp, stmt);
9840 /* Go back to the top of the loop. */
9841 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9843 /* Place the loop exit label here. */
9844 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9847 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9848 scan that for reductions. */
9850 static void
9851 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9852 gimple_seq *out_stmt_seqp, omp_context *ctx)
9854 gimple_stmt_iterator gsi;
9855 gimple_seq inner = NULL;
9857 /* A collapse clause may have inserted a new bind block. */
9858 gsi = gsi_start (*body);
9859 while (!gsi_end_p (gsi))
9861 gimple stmt = gsi_stmt (gsi);
9862 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9864 inner = gimple_bind_body (bind_stmt);
9865 body = &inner;
9866 gsi = gsi_start (*body);
9868 else if (dyn_cast <gomp_for *> (stmt))
9869 break;
9870 else
9871 gsi_next (&gsi);
9874 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9876 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9877 enter, exit;
9878 bool reduction_found = false;
9880 gimple stmt = gsi_stmt (gsi);
9882 switch (gimple_code (stmt))
9884 case GIMPLE_OMP_FOR:
9885 clauses = gimple_omp_for_clauses (stmt);
9887 /* Search for a reduction clause. */
9888 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9889 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9891 reduction_found = true;
9892 break;
9895 if (!reduction_found)
9896 break;
9898 ctx = maybe_lookup_ctx (stmt);
9899 t = NULL_TREE;
9901 /* Extract the number of threads. */
9902 nthreads = create_tmp_var (sizetype);
9903 t = oacc_max_threads (ctx);
9904 gimplify_assign (nthreads, t, in_stmt_seqp);
9906 /* Determine if this is kernel will be executed on the host. */
9907 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9908 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9909 stmt = gimple_build_call (call, 0);
9910 gimple_call_set_lhs (stmt, acc_device);
9911 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9913 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9914 acc_device_host = create_tmp_var (integer_type_node,
9915 ".acc_device_host");
9916 gimplify_assign (acc_device_host,
9917 build_int_cst (integer_type_node,
9918 GOMP_DEVICE_HOST),
9919 in_stmt_seqp);
9921 enter = create_artificial_label (UNKNOWN_LOCATION);
9922 exit = create_artificial_label (UNKNOWN_LOCATION);
9924 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9925 enter, exit);
9926 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9927 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9928 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9929 integer_one_node),
9930 in_stmt_seqp);
9931 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9933 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9934 gimplify_assign (acc_device_host,
9935 build_int_cst (integer_type_node,
9936 GOMP_DEVICE_HOST_NONSHM),
9937 in_stmt_seqp);
9939 enter = create_artificial_label (UNKNOWN_LOCATION);
9940 exit = create_artificial_label (UNKNOWN_LOCATION);
9942 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9943 enter, exit);
9944 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9945 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9946 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9947 integer_one_node),
9948 in_stmt_seqp);
9949 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9951 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9952 ctx);
9953 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9954 break;
9955 default:
9956 // Scan for other directives which support reduction here.
9957 break;
9962 /* If ctx is a worksharing context inside of a cancellable parallel
9963 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9964 and conditional branch to parallel's cancel_label to handle
9965 cancellation in the implicit barrier. */
9967 static void
9968 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9970 gimple omp_return = gimple_seq_last_stmt (*body);
9971 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
9972 if (gimple_omp_return_nowait_p (omp_return))
9973 return;
9974 if (ctx->outer
9975 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
9976 && ctx->outer->cancellable)
9978 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
9979 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
9980 tree lhs = create_tmp_var (c_bool_type);
9981 gimple_omp_return_set_lhs (omp_return, lhs);
9982 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
9983 gimple g = gimple_build_cond (NE_EXPR, lhs,
9984 fold_convert (c_bool_type,
9985 boolean_false_node),
9986 ctx->outer->cancel_label, fallthru_label);
9987 gimple_seq_add_stmt (body, g);
9988 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
9992 /* Lower the OpenMP sections directive in the current statement in GSI_P.
9993 CTX is the enclosing OMP context for the current statement. */
9995 static void
9996 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9998 tree block, control;
9999 gimple_stmt_iterator tgsi;
10000 gomp_sections *stmt;
10001 gimple t;
10002 gbind *new_stmt, *bind;
10003 gimple_seq ilist, dlist, olist, new_body;
10005 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10007 push_gimplify_context ();
10009 dlist = NULL;
10010 ilist = NULL;
10011 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10012 &ilist, &dlist, ctx, NULL);
10014 new_body = gimple_omp_body (stmt);
10015 gimple_omp_set_body (stmt, NULL);
10016 tgsi = gsi_start (new_body);
10017 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10019 omp_context *sctx;
10020 gimple sec_start;
10022 sec_start = gsi_stmt (tgsi);
10023 sctx = maybe_lookup_ctx (sec_start);
10024 gcc_assert (sctx);
10026 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10027 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10028 GSI_CONTINUE_LINKING);
10029 gimple_omp_set_body (sec_start, NULL);
10031 if (gsi_one_before_end_p (tgsi))
10033 gimple_seq l = NULL;
10034 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10035 &l, ctx);
10036 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10037 gimple_omp_section_set_last (sec_start);
10040 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10041 GSI_CONTINUE_LINKING);
10044 block = make_node (BLOCK);
10045 bind = gimple_build_bind (NULL, new_body, block);
10047 olist = NULL;
10048 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10050 block = make_node (BLOCK);
10051 new_stmt = gimple_build_bind (NULL, NULL, block);
10052 gsi_replace (gsi_p, new_stmt, true);
10054 pop_gimplify_context (new_stmt);
10055 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10056 BLOCK_VARS (block) = gimple_bind_vars (bind);
10057 if (BLOCK_VARS (block))
10058 TREE_USED (block) = 1;
10060 new_body = NULL;
10061 gimple_seq_add_seq (&new_body, ilist);
10062 gimple_seq_add_stmt (&new_body, stmt);
10063 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10064 gimple_seq_add_stmt (&new_body, bind);
10066 control = create_tmp_var (unsigned_type_node, ".section");
10067 t = gimple_build_omp_continue (control, control);
10068 gimple_omp_sections_set_control (stmt, control);
10069 gimple_seq_add_stmt (&new_body, t);
10071 gimple_seq_add_seq (&new_body, olist);
10072 if (ctx->cancellable)
10073 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10074 gimple_seq_add_seq (&new_body, dlist);
10076 new_body = maybe_catch_exception (new_body);
10078 t = gimple_build_omp_return
10079 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10080 OMP_CLAUSE_NOWAIT));
10081 gimple_seq_add_stmt (&new_body, t);
10082 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10084 gimple_bind_set_body (new_stmt, new_body);
10088 /* A subroutine of lower_omp_single. Expand the simple form of
10089 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10091 if (GOMP_single_start ())
10092 BODY;
10093 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10095 FIXME. It may be better to delay expanding the logic of this until
10096 pass_expand_omp. The expanded logic may make the job more difficult
10097 to a synchronization analysis pass. */
10099 static void
10100 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10102 location_t loc = gimple_location (single_stmt);
10103 tree tlabel = create_artificial_label (loc);
10104 tree flabel = create_artificial_label (loc);
10105 gimple call, cond;
10106 tree lhs, decl;
10108 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10109 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10110 call = gimple_build_call (decl, 0);
10111 gimple_call_set_lhs (call, lhs);
10112 gimple_seq_add_stmt (pre_p, call);
10114 cond = gimple_build_cond (EQ_EXPR, lhs,
10115 fold_convert_loc (loc, TREE_TYPE (lhs),
10116 boolean_true_node),
10117 tlabel, flabel);
10118 gimple_seq_add_stmt (pre_p, cond);
10119 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10120 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10121 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10125 /* A subroutine of lower_omp_single. Expand the simple form of
10126 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10128 #pragma omp single copyprivate (a, b, c)
10130 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10133 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10135 BODY;
10136 copyout.a = a;
10137 copyout.b = b;
10138 copyout.c = c;
10139 GOMP_single_copy_end (&copyout);
10141 else
10143 a = copyout_p->a;
10144 b = copyout_p->b;
10145 c = copyout_p->c;
10147 GOMP_barrier ();
10150 FIXME. It may be better to delay expanding the logic of this until
10151 pass_expand_omp. The expanded logic may make the job more difficult
10152 to a synchronization analysis pass. */
10154 static void
10155 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10156 omp_context *ctx)
10158 tree ptr_type, t, l0, l1, l2, bfn_decl;
10159 gimple_seq copyin_seq;
10160 location_t loc = gimple_location (single_stmt);
10162 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10164 ptr_type = build_pointer_type (ctx->record_type);
10165 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10167 l0 = create_artificial_label (loc);
10168 l1 = create_artificial_label (loc);
10169 l2 = create_artificial_label (loc);
10171 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10172 t = build_call_expr_loc (loc, bfn_decl, 0);
10173 t = fold_convert_loc (loc, ptr_type, t);
10174 gimplify_assign (ctx->receiver_decl, t, pre_p);
10176 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10177 build_int_cst (ptr_type, 0));
10178 t = build3 (COND_EXPR, void_type_node, t,
10179 build_and_jump (&l0), build_and_jump (&l1));
10180 gimplify_and_add (t, pre_p);
10182 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10184 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10186 copyin_seq = NULL;
10187 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10188 &copyin_seq, ctx);
10190 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10191 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10192 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10193 gimplify_and_add (t, pre_p);
10195 t = build_and_jump (&l2);
10196 gimplify_and_add (t, pre_p);
10198 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10200 gimple_seq_add_seq (pre_p, copyin_seq);
10202 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10206 /* Expand code for an OpenMP single directive. */
10208 static void
10209 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10211 tree block;
10212 gimple t;
10213 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10214 gbind *bind;
10215 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10217 push_gimplify_context ();
10219 block = make_node (BLOCK);
10220 bind = gimple_build_bind (NULL, NULL, block);
10221 gsi_replace (gsi_p, bind, true);
10222 bind_body = NULL;
10223 dlist = NULL;
10224 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10225 &bind_body, &dlist, ctx, NULL);
10226 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10228 gimple_seq_add_stmt (&bind_body, single_stmt);
10230 if (ctx->record_type)
10231 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10232 else
10233 lower_omp_single_simple (single_stmt, &bind_body);
10235 gimple_omp_set_body (single_stmt, NULL);
10237 gimple_seq_add_seq (&bind_body, dlist);
10239 bind_body = maybe_catch_exception (bind_body);
10241 t = gimple_build_omp_return
10242 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10243 OMP_CLAUSE_NOWAIT));
10244 gimple_seq_add_stmt (&bind_body_tail, t);
10245 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10246 if (ctx->record_type)
10248 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10249 tree clobber = build_constructor (ctx->record_type, NULL);
10250 TREE_THIS_VOLATILE (clobber) = 1;
10251 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10252 clobber), GSI_SAME_STMT);
10254 gimple_seq_add_seq (&bind_body, bind_body_tail);
10255 gimple_bind_set_body (bind, bind_body);
10257 pop_gimplify_context (bind);
10259 gimple_bind_append_vars (bind, ctx->block_vars);
10260 BLOCK_VARS (block) = ctx->block_vars;
10261 if (BLOCK_VARS (block))
10262 TREE_USED (block) = 1;
10266 /* Expand code for an OpenMP master directive. */
10268 static void
10269 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10271 tree block, lab = NULL, x, bfn_decl;
10272 gimple stmt = gsi_stmt (*gsi_p);
10273 gbind *bind;
10274 location_t loc = gimple_location (stmt);
10275 gimple_seq tseq;
10277 push_gimplify_context ();
10279 block = make_node (BLOCK);
10280 bind = gimple_build_bind (NULL, NULL, block);
10281 gsi_replace (gsi_p, bind, true);
10282 gimple_bind_add_stmt (bind, stmt);
10284 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10285 x = build_call_expr_loc (loc, bfn_decl, 0);
10286 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10287 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10288 tseq = NULL;
10289 gimplify_and_add (x, &tseq);
10290 gimple_bind_add_seq (bind, tseq);
10292 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10293 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10294 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10295 gimple_omp_set_body (stmt, NULL);
10297 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10299 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10301 pop_gimplify_context (bind);
10303 gimple_bind_append_vars (bind, ctx->block_vars);
10304 BLOCK_VARS (block) = ctx->block_vars;
10308 /* Expand code for an OpenMP taskgroup directive. */
10310 static void
10311 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10313 gimple stmt = gsi_stmt (*gsi_p);
10314 gcall *x;
10315 gbind *bind;
10316 tree block = make_node (BLOCK);
10318 bind = gimple_build_bind (NULL, NULL, block);
10319 gsi_replace (gsi_p, bind, true);
10320 gimple_bind_add_stmt (bind, stmt);
10322 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10324 gimple_bind_add_stmt (bind, x);
10326 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10327 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10328 gimple_omp_set_body (stmt, NULL);
10330 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10332 gimple_bind_append_vars (bind, ctx->block_vars);
10333 BLOCK_VARS (block) = ctx->block_vars;
10337 /* Expand code for an OpenMP ordered directive. */
10339 static void
10340 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10342 tree block;
10343 gimple stmt = gsi_stmt (*gsi_p);
10344 gcall *x;
10345 gbind *bind;
10347 push_gimplify_context ();
10349 block = make_node (BLOCK);
10350 bind = gimple_build_bind (NULL, NULL, block);
10351 gsi_replace (gsi_p, bind, true);
10352 gimple_bind_add_stmt (bind, stmt);
10354 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10356 gimple_bind_add_stmt (bind, x);
10358 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10359 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10360 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10361 gimple_omp_set_body (stmt, NULL);
10363 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10364 gimple_bind_add_stmt (bind, x);
10366 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10368 pop_gimplify_context (bind);
10370 gimple_bind_append_vars (bind, ctx->block_vars);
10371 BLOCK_VARS (block) = gimple_bind_vars (bind);
10375 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10376 substitution of a couple of function calls. But in the NAMED case,
10377 requires that languages coordinate a symbol name. It is therefore
10378 best put here in common code. */
10380 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10382 static void
10383 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10385 tree block;
10386 tree name, lock, unlock;
10387 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10388 gbind *bind;
10389 location_t loc = gimple_location (stmt);
10390 gimple_seq tbody;
10392 name = gimple_omp_critical_name (stmt);
10393 if (name)
10395 tree decl;
10397 if (!critical_name_mutexes)
10398 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10400 tree *n = critical_name_mutexes->get (name);
10401 if (n == NULL)
10403 char *new_str;
10405 decl = create_tmp_var_raw (ptr_type_node);
10407 new_str = ACONCAT ((".gomp_critical_user_",
10408 IDENTIFIER_POINTER (name), NULL));
10409 DECL_NAME (decl) = get_identifier (new_str);
10410 TREE_PUBLIC (decl) = 1;
10411 TREE_STATIC (decl) = 1;
10412 DECL_COMMON (decl) = 1;
10413 DECL_ARTIFICIAL (decl) = 1;
10414 DECL_IGNORED_P (decl) = 1;
10416 varpool_node::finalize_decl (decl);
10418 critical_name_mutexes->put (name, decl);
10420 else
10421 decl = *n;
10423 /* If '#pragma omp critical' is inside offloaded region or
10424 inside function marked as offloadable, the symbol must be
10425 marked as offloadable too. */
10426 omp_context *octx;
10427 if (cgraph_node::get (current_function_decl)->offloadable)
10428 varpool_node::get_create (decl)->offloadable = 1;
10429 else
10430 for (octx = ctx->outer; octx; octx = octx->outer)
10431 if (is_gimple_omp_offloaded (octx->stmt))
10433 varpool_node::get_create (decl)->offloadable = 1;
10434 break;
10437 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10438 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10440 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10441 unlock = build_call_expr_loc (loc, unlock, 1,
10442 build_fold_addr_expr_loc (loc, decl));
10444 else
10446 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10447 lock = build_call_expr_loc (loc, lock, 0);
10449 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10450 unlock = build_call_expr_loc (loc, unlock, 0);
10453 push_gimplify_context ();
10455 block = make_node (BLOCK);
10456 bind = gimple_build_bind (NULL, NULL, block);
10457 gsi_replace (gsi_p, bind, true);
10458 gimple_bind_add_stmt (bind, stmt);
10460 tbody = gimple_bind_body (bind);
10461 gimplify_and_add (lock, &tbody);
10462 gimple_bind_set_body (bind, tbody);
10464 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10465 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10466 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10467 gimple_omp_set_body (stmt, NULL);
10469 tbody = gimple_bind_body (bind);
10470 gimplify_and_add (unlock, &tbody);
10471 gimple_bind_set_body (bind, tbody);
10473 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10475 pop_gimplify_context (bind);
10476 gimple_bind_append_vars (bind, ctx->block_vars);
10477 BLOCK_VARS (block) = gimple_bind_vars (bind);
10481 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10482 for a lastprivate clause. Given a loop control predicate of (V
10483 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10484 is appended to *DLIST, iterator initialization is appended to
10485 *BODY_P. */
10487 static void
10488 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10489 gimple_seq *dlist, struct omp_context *ctx)
10491 tree clauses, cond, vinit;
10492 enum tree_code cond_code;
10493 gimple_seq stmts;
10495 cond_code = fd->loop.cond_code;
10496 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10498 /* When possible, use a strict equality expression. This can let VRP
10499 type optimizations deduce the value and remove a copy. */
10500 if (tree_fits_shwi_p (fd->loop.step))
10502 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10503 if (step == 1 || step == -1)
10504 cond_code = EQ_EXPR;
10507 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
10509 clauses = gimple_omp_for_clauses (fd->for_stmt);
10510 stmts = NULL;
10511 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10512 if (!gimple_seq_empty_p (stmts))
10514 gimple_seq_add_seq (&stmts, *dlist);
10515 *dlist = stmts;
10517 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10518 vinit = fd->loop.n1;
10519 if (cond_code == EQ_EXPR
10520 && tree_fits_shwi_p (fd->loop.n2)
10521 && ! integer_zerop (fd->loop.n2))
10522 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10523 else
10524 vinit = unshare_expr (vinit);
10526 /* Initialize the iterator variable, so that threads that don't execute
10527 any iterations don't execute the lastprivate clauses by accident. */
10528 gimplify_assign (fd->loop.v, vinit, body_p);
10533 /* Lower code for an OMP loop directive. */
10535 static void
10536 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10538 tree *rhs_p, block;
10539 struct omp_for_data fd, *fdp = NULL;
10540 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10541 gbind *new_stmt;
10542 gimple_seq omp_for_body, body, dlist;
10543 size_t i;
10545 push_gimplify_context ();
10547 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10549 block = make_node (BLOCK);
10550 new_stmt = gimple_build_bind (NULL, NULL, block);
10551 /* Replace at gsi right away, so that 'stmt' is no member
10552 of a sequence anymore as we're going to add to to a different
10553 one below. */
10554 gsi_replace (gsi_p, new_stmt, true);
10556 /* Move declaration of temporaries in the loop body before we make
10557 it go away. */
10558 omp_for_body = gimple_omp_body (stmt);
10559 if (!gimple_seq_empty_p (omp_for_body)
10560 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10562 gbind *inner_bind
10563 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10564 tree vars = gimple_bind_vars (inner_bind);
10565 gimple_bind_append_vars (new_stmt, vars);
10566 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10567 keep them on the inner_bind and it's block. */
10568 gimple_bind_set_vars (inner_bind, NULL_TREE);
10569 if (gimple_bind_block (inner_bind))
10570 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10573 if (gimple_omp_for_combined_into_p (stmt))
10575 extract_omp_for_data (stmt, &fd, NULL);
10576 fdp = &fd;
10578 /* We need two temporaries with fd.loop.v type (istart/iend)
10579 and then (fd.collapse - 1) temporaries with the same
10580 type for count2 ... countN-1 vars if not constant. */
10581 size_t count = 2;
10582 tree type = fd.iter_type;
10583 if (fd.collapse > 1
10584 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10585 count += fd.collapse - 1;
10586 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10587 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10588 tree clauses = *pc;
10589 if (parallel_for)
10590 outerc
10591 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10592 OMP_CLAUSE__LOOPTEMP_);
10593 for (i = 0; i < count; i++)
10595 tree temp;
10596 if (parallel_for)
10598 gcc_assert (outerc);
10599 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10600 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10601 OMP_CLAUSE__LOOPTEMP_);
10603 else
10605 temp = create_tmp_var (type);
10606 insert_decl_map (&ctx->outer->cb, temp, temp);
10608 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10609 OMP_CLAUSE_DECL (*pc) = temp;
10610 pc = &OMP_CLAUSE_CHAIN (*pc);
10612 *pc = clauses;
10615 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10616 dlist = NULL;
10617 body = NULL;
10618 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10619 fdp);
10620 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10622 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10624 /* Lower the header expressions. At this point, we can assume that
10625 the header is of the form:
10627 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10629 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10630 using the .omp_data_s mapping, if needed. */
10631 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10633 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10634 if (!is_gimple_min_invariant (*rhs_p))
10635 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10637 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10638 if (!is_gimple_min_invariant (*rhs_p))
10639 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10641 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10642 if (!is_gimple_min_invariant (*rhs_p))
10643 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10646 /* Once lowered, extract the bounds and clauses. */
10647 extract_omp_for_data (stmt, &fd, NULL);
10649 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10651 gimple_seq_add_stmt (&body, stmt);
10652 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10654 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10655 fd.loop.v));
10657 /* After the loop, add exit clauses. */
10658 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10660 if (ctx->cancellable)
10661 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10663 gimple_seq_add_seq (&body, dlist);
10665 body = maybe_catch_exception (body);
10667 /* Region exit marker goes at the end of the loop body. */
10668 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10669 maybe_add_implicit_barrier_cancel (ctx, &body);
10670 pop_gimplify_context (new_stmt);
10672 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10673 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10674 if (BLOCK_VARS (block))
10675 TREE_USED (block) = 1;
10677 gimple_bind_set_body (new_stmt, body);
10678 gimple_omp_set_body (stmt, NULL);
10679 gimple_omp_for_set_pre_body (stmt, NULL);
10682 /* Callback for walk_stmts. Check if the current statement only contains
10683 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10685 static tree
10686 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10687 bool *handled_ops_p,
10688 struct walk_stmt_info *wi)
10690 int *info = (int *) wi->info;
10691 gimple stmt = gsi_stmt (*gsi_p);
10693 *handled_ops_p = true;
10694 switch (gimple_code (stmt))
10696 WALK_SUBSTMTS;
10698 case GIMPLE_OMP_FOR:
10699 case GIMPLE_OMP_SECTIONS:
10700 *info = *info == 0 ? 1 : -1;
10701 break;
10702 default:
10703 *info = -1;
10704 break;
10706 return NULL;
10709 struct omp_taskcopy_context
10711 /* This field must be at the beginning, as we do "inheritance": Some
10712 callback functions for tree-inline.c (e.g., omp_copy_decl)
10713 receive a copy_body_data pointer that is up-casted to an
10714 omp_context pointer. */
10715 copy_body_data cb;
10716 omp_context *ctx;
10719 static tree
10720 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10722 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10724 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10725 return create_tmp_var (TREE_TYPE (var));
10727 return var;
10730 static tree
10731 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10733 tree name, new_fields = NULL, type, f;
10735 type = lang_hooks.types.make_type (RECORD_TYPE);
10736 name = DECL_NAME (TYPE_NAME (orig_type));
10737 name = build_decl (gimple_location (tcctx->ctx->stmt),
10738 TYPE_DECL, name, type);
10739 TYPE_NAME (type) = name;
10741 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10743 tree new_f = copy_node (f);
10744 DECL_CONTEXT (new_f) = type;
10745 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10746 TREE_CHAIN (new_f) = new_fields;
10747 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10748 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10749 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10750 &tcctx->cb, NULL);
10751 new_fields = new_f;
10752 tcctx->cb.decl_map->put (f, new_f);
10754 TYPE_FIELDS (type) = nreverse (new_fields);
10755 layout_type (type);
10756 return type;
10759 /* Create task copyfn. */
10761 static void
10762 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10764 struct function *child_cfun;
10765 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10766 tree record_type, srecord_type, bind, list;
10767 bool record_needs_remap = false, srecord_needs_remap = false;
10768 splay_tree_node n;
10769 struct omp_taskcopy_context tcctx;
10770 location_t loc = gimple_location (task_stmt);
10772 child_fn = gimple_omp_task_copy_fn (task_stmt);
10773 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10774 gcc_assert (child_cfun->cfg == NULL);
10775 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10777 /* Reset DECL_CONTEXT on function arguments. */
10778 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10779 DECL_CONTEXT (t) = child_fn;
10781 /* Populate the function. */
10782 push_gimplify_context ();
10783 push_cfun (child_cfun);
10785 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10786 TREE_SIDE_EFFECTS (bind) = 1;
10787 list = NULL;
10788 DECL_SAVED_TREE (child_fn) = bind;
10789 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10791 /* Remap src and dst argument types if needed. */
10792 record_type = ctx->record_type;
10793 srecord_type = ctx->srecord_type;
10794 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10795 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10797 record_needs_remap = true;
10798 break;
10800 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10801 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10803 srecord_needs_remap = true;
10804 break;
10807 if (record_needs_remap || srecord_needs_remap)
10809 memset (&tcctx, '\0', sizeof (tcctx));
10810 tcctx.cb.src_fn = ctx->cb.src_fn;
10811 tcctx.cb.dst_fn = child_fn;
10812 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
10813 gcc_checking_assert (tcctx.cb.src_node);
10814 tcctx.cb.dst_node = tcctx.cb.src_node;
10815 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10816 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10817 tcctx.cb.eh_lp_nr = 0;
10818 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10819 tcctx.cb.decl_map = new hash_map<tree, tree>;
10820 tcctx.ctx = ctx;
10822 if (record_needs_remap)
10823 record_type = task_copyfn_remap_type (&tcctx, record_type);
10824 if (srecord_needs_remap)
10825 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10827 else
10828 tcctx.cb.decl_map = NULL;
10830 arg = DECL_ARGUMENTS (child_fn);
10831 TREE_TYPE (arg) = build_pointer_type (record_type);
10832 sarg = DECL_CHAIN (arg);
10833 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10835 /* First pass: initialize temporaries used in record_type and srecord_type
10836 sizes and field offsets. */
10837 if (tcctx.cb.decl_map)
10838 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10839 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10841 tree *p;
10843 decl = OMP_CLAUSE_DECL (c);
10844 p = tcctx.cb.decl_map->get (decl);
10845 if (p == NULL)
10846 continue;
10847 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10848 sf = (tree) n->value;
10849 sf = *tcctx.cb.decl_map->get (sf);
10850 src = build_simple_mem_ref_loc (loc, sarg);
10851 src = omp_build_component_ref (src, sf);
10852 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10853 append_to_statement_list (t, &list);
10856 /* Second pass: copy shared var pointers and copy construct non-VLA
10857 firstprivate vars. */
10858 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10859 switch (OMP_CLAUSE_CODE (c))
10861 case OMP_CLAUSE_SHARED:
10862 decl = OMP_CLAUSE_DECL (c);
10863 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10864 if (n == NULL)
10865 break;
10866 f = (tree) n->value;
10867 if (tcctx.cb.decl_map)
10868 f = *tcctx.cb.decl_map->get (f);
10869 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10870 sf = (tree) n->value;
10871 if (tcctx.cb.decl_map)
10872 sf = *tcctx.cb.decl_map->get (sf);
10873 src = build_simple_mem_ref_loc (loc, sarg);
10874 src = omp_build_component_ref (src, sf);
10875 dst = build_simple_mem_ref_loc (loc, arg);
10876 dst = omp_build_component_ref (dst, f);
10877 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10878 append_to_statement_list (t, &list);
10879 break;
10880 case OMP_CLAUSE_FIRSTPRIVATE:
10881 decl = OMP_CLAUSE_DECL (c);
10882 if (is_variable_sized (decl))
10883 break;
10884 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10885 if (n == NULL)
10886 break;
10887 f = (tree) n->value;
10888 if (tcctx.cb.decl_map)
10889 f = *tcctx.cb.decl_map->get (f);
10890 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10891 if (n != NULL)
10893 sf = (tree) n->value;
10894 if (tcctx.cb.decl_map)
10895 sf = *tcctx.cb.decl_map->get (sf);
10896 src = build_simple_mem_ref_loc (loc, sarg);
10897 src = omp_build_component_ref (src, sf);
10898 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
10899 src = build_simple_mem_ref_loc (loc, src);
10901 else
10902 src = decl;
10903 dst = build_simple_mem_ref_loc (loc, arg);
10904 dst = omp_build_component_ref (dst, f);
10905 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10906 append_to_statement_list (t, &list);
10907 break;
10908 case OMP_CLAUSE_PRIVATE:
10909 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10910 break;
10911 decl = OMP_CLAUSE_DECL (c);
10912 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10913 f = (tree) n->value;
10914 if (tcctx.cb.decl_map)
10915 f = *tcctx.cb.decl_map->get (f);
10916 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10917 if (n != NULL)
10919 sf = (tree) n->value;
10920 if (tcctx.cb.decl_map)
10921 sf = *tcctx.cb.decl_map->get (sf);
10922 src = build_simple_mem_ref_loc (loc, sarg);
10923 src = omp_build_component_ref (src, sf);
10924 if (use_pointer_for_field (decl, NULL))
10925 src = build_simple_mem_ref_loc (loc, src);
10927 else
10928 src = decl;
10929 dst = build_simple_mem_ref_loc (loc, arg);
10930 dst = omp_build_component_ref (dst, f);
10931 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10932 append_to_statement_list (t, &list);
10933 break;
10934 default:
10935 break;
10938 /* Last pass: handle VLA firstprivates. */
10939 if (tcctx.cb.decl_map)
10940 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10941 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10943 tree ind, ptr, df;
10945 decl = OMP_CLAUSE_DECL (c);
10946 if (!is_variable_sized (decl))
10947 continue;
10948 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10949 if (n == NULL)
10950 continue;
10951 f = (tree) n->value;
10952 f = *tcctx.cb.decl_map->get (f);
10953 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10954 ind = DECL_VALUE_EXPR (decl);
10955 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10956 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10957 n = splay_tree_lookup (ctx->sfield_map,
10958 (splay_tree_key) TREE_OPERAND (ind, 0));
10959 sf = (tree) n->value;
10960 sf = *tcctx.cb.decl_map->get (sf);
10961 src = build_simple_mem_ref_loc (loc, sarg);
10962 src = omp_build_component_ref (src, sf);
10963 src = build_simple_mem_ref_loc (loc, src);
10964 dst = build_simple_mem_ref_loc (loc, arg);
10965 dst = omp_build_component_ref (dst, f);
10966 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10967 append_to_statement_list (t, &list);
10968 n = splay_tree_lookup (ctx->field_map,
10969 (splay_tree_key) TREE_OPERAND (ind, 0));
10970 df = (tree) n->value;
10971 df = *tcctx.cb.decl_map->get (df);
10972 ptr = build_simple_mem_ref_loc (loc, arg);
10973 ptr = omp_build_component_ref (ptr, df);
10974 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
10975 build_fold_addr_expr_loc (loc, dst));
10976 append_to_statement_list (t, &list);
10979 t = build1 (RETURN_EXPR, void_type_node, NULL);
10980 append_to_statement_list (t, &list);
10982 if (tcctx.cb.decl_map)
10983 delete tcctx.cb.decl_map;
10984 pop_gimplify_context (NULL);
10985 BIND_EXPR_BODY (bind) = list;
10986 pop_cfun ();
10989 static void
10990 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
10992 tree c, clauses;
10993 gimple g;
10994 size_t n_in = 0, n_out = 0, idx = 2, i;
10996 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
10997 OMP_CLAUSE_DEPEND);
10998 gcc_assert (clauses);
10999 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11000 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11001 switch (OMP_CLAUSE_DEPEND_KIND (c))
11003 case OMP_CLAUSE_DEPEND_IN:
11004 n_in++;
11005 break;
11006 case OMP_CLAUSE_DEPEND_OUT:
11007 case OMP_CLAUSE_DEPEND_INOUT:
11008 n_out++;
11009 break;
11010 default:
11011 gcc_unreachable ();
11013 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11014 tree array = create_tmp_var (type);
11015 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11016 NULL_TREE);
11017 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11018 gimple_seq_add_stmt (iseq, g);
11019 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11020 NULL_TREE);
11021 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11022 gimple_seq_add_stmt (iseq, g);
11023 for (i = 0; i < 2; i++)
11025 if ((i ? n_in : n_out) == 0)
11026 continue;
11027 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11028 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11029 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11031 tree t = OMP_CLAUSE_DECL (c);
11032 t = fold_convert (ptr_type_node, t);
11033 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11034 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11035 NULL_TREE, NULL_TREE);
11036 g = gimple_build_assign (r, t);
11037 gimple_seq_add_stmt (iseq, g);
11040 tree *p = gimple_omp_task_clauses_ptr (stmt);
11041 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11042 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11043 OMP_CLAUSE_CHAIN (c) = *p;
11044 *p = c;
11045 tree clobber = build_constructor (type, NULL);
11046 TREE_THIS_VOLATILE (clobber) = 1;
11047 g = gimple_build_assign (array, clobber);
11048 gimple_seq_add_stmt (oseq, g);
11051 /* Lower the OpenMP parallel or task directive in the current statement
11052 in GSI_P. CTX holds context information for the directive. */
11054 static void
11055 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11057 tree clauses;
11058 tree child_fn, t;
11059 gimple stmt = gsi_stmt (*gsi_p);
11060 gbind *par_bind, *bind, *dep_bind = NULL;
11061 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11062 location_t loc = gimple_location (stmt);
11064 clauses = gimple_omp_taskreg_clauses (stmt);
11065 par_bind
11066 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11067 par_body = gimple_bind_body (par_bind);
11068 child_fn = ctx->cb.dst_fn;
11069 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11070 && !gimple_omp_parallel_combined_p (stmt))
11072 struct walk_stmt_info wi;
11073 int ws_num = 0;
11075 memset (&wi, 0, sizeof (wi));
11076 wi.info = &ws_num;
11077 wi.val_only = true;
11078 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11079 if (ws_num == 1)
11080 gimple_omp_parallel_set_combined_p (stmt, true);
11082 gimple_seq dep_ilist = NULL;
11083 gimple_seq dep_olist = NULL;
11084 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11085 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11087 push_gimplify_context ();
11088 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11089 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11092 if (ctx->srecord_type)
11093 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11095 push_gimplify_context ();
11097 par_olist = NULL;
11098 par_ilist = NULL;
11099 par_rlist = NULL;
11100 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11101 lower_omp (&par_body, ctx);
11102 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11103 lower_reduction_clauses (clauses, &par_rlist, ctx);
11105 /* Declare all the variables created by mapping and the variables
11106 declared in the scope of the parallel body. */
11107 record_vars_into (ctx->block_vars, child_fn);
11108 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11110 if (ctx->record_type)
11112 ctx->sender_decl
11113 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11114 : ctx->record_type, ".omp_data_o");
11115 DECL_NAMELESS (ctx->sender_decl) = 1;
11116 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11117 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11120 olist = NULL;
11121 ilist = NULL;
11122 lower_send_clauses (clauses, &ilist, &olist, ctx);
11123 lower_send_shared_vars (&ilist, &olist, ctx);
11125 if (ctx->record_type)
11127 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11128 TREE_THIS_VOLATILE (clobber) = 1;
11129 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11130 clobber));
11133 /* Once all the expansions are done, sequence all the different
11134 fragments inside gimple_omp_body. */
11136 new_body = NULL;
11138 if (ctx->record_type)
11140 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11141 /* fixup_child_record_type might have changed receiver_decl's type. */
11142 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11143 gimple_seq_add_stmt (&new_body,
11144 gimple_build_assign (ctx->receiver_decl, t));
11147 gimple_seq_add_seq (&new_body, par_ilist);
11148 gimple_seq_add_seq (&new_body, par_body);
11149 gimple_seq_add_seq (&new_body, par_rlist);
11150 if (ctx->cancellable)
11151 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11152 gimple_seq_add_seq (&new_body, par_olist);
11153 new_body = maybe_catch_exception (new_body);
11154 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11155 gimple_omp_set_body (stmt, new_body);
11157 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11158 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11159 gimple_bind_add_seq (bind, ilist);
11160 gimple_bind_add_stmt (bind, stmt);
11161 gimple_bind_add_seq (bind, olist);
11163 pop_gimplify_context (NULL);
11165 if (dep_bind)
11167 gimple_bind_add_seq (dep_bind, dep_ilist);
11168 gimple_bind_add_stmt (dep_bind, bind);
11169 gimple_bind_add_seq (dep_bind, dep_olist);
11170 pop_gimplify_context (dep_bind);
11174 /* Lower the GIMPLE_OMP_TARGET in the current statement
11175 in GSI_P. CTX holds context information for the directive. */
11177 static void
11178 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11180 tree clauses;
11181 tree child_fn, t, c;
11182 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11183 gbind *tgt_bind, *bind;
11184 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11185 location_t loc = gimple_location (stmt);
11186 bool offloaded, data_region;
11187 unsigned int map_cnt = 0;
11189 offloaded = is_gimple_omp_offloaded (stmt);
11190 switch (gimple_omp_target_kind (stmt))
11192 case GF_OMP_TARGET_KIND_REGION:
11193 case GF_OMP_TARGET_KIND_UPDATE:
11194 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11195 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11196 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11197 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11198 data_region = false;
11199 break;
11200 case GF_OMP_TARGET_KIND_DATA:
11201 case GF_OMP_TARGET_KIND_OACC_DATA:
11202 data_region = true;
11203 break;
11204 default:
11205 gcc_unreachable ();
11208 clauses = gimple_omp_target_clauses (stmt);
11210 tgt_bind = NULL;
11211 tgt_body = NULL;
11212 if (offloaded)
11214 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11215 tgt_body = gimple_bind_body (tgt_bind);
11217 else if (data_region)
11218 tgt_body = gimple_omp_body (stmt);
11219 child_fn = ctx->cb.dst_fn;
11221 push_gimplify_context ();
11223 irlist = NULL;
11224 orlist = NULL;
11225 if (offloaded
11226 && is_gimple_omp_oacc (stmt))
11227 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11229 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11230 switch (OMP_CLAUSE_CODE (c))
11232 tree var, x;
11234 default:
11235 break;
11236 case OMP_CLAUSE_MAP:
11237 #ifdef ENABLE_CHECKING
11238 /* First check what we're prepared to handle in the following. */
11239 switch (OMP_CLAUSE_MAP_KIND (c))
11241 case GOMP_MAP_ALLOC:
11242 case GOMP_MAP_TO:
11243 case GOMP_MAP_FROM:
11244 case GOMP_MAP_TOFROM:
11245 case GOMP_MAP_POINTER:
11246 case GOMP_MAP_TO_PSET:
11247 break;
11248 case GOMP_MAP_FORCE_ALLOC:
11249 case GOMP_MAP_FORCE_TO:
11250 case GOMP_MAP_FORCE_FROM:
11251 case GOMP_MAP_FORCE_TOFROM:
11252 case GOMP_MAP_FORCE_PRESENT:
11253 case GOMP_MAP_FORCE_DEALLOC:
11254 case GOMP_MAP_FORCE_DEVICEPTR:
11255 gcc_assert (is_gimple_omp_oacc (stmt));
11256 break;
11257 default:
11258 gcc_unreachable ();
11260 #endif
11261 /* FALLTHRU */
11262 case OMP_CLAUSE_TO:
11263 case OMP_CLAUSE_FROM:
11264 var = OMP_CLAUSE_DECL (c);
11265 if (!DECL_P (var))
11267 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11268 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11269 map_cnt++;
11270 continue;
11273 if (DECL_SIZE (var)
11274 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11276 tree var2 = DECL_VALUE_EXPR (var);
11277 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11278 var2 = TREE_OPERAND (var2, 0);
11279 gcc_assert (DECL_P (var2));
11280 var = var2;
11283 if (!maybe_lookup_field (var, ctx))
11284 continue;
11286 if (offloaded)
11288 x = build_receiver_ref (var, true, ctx);
11289 tree new_var = lookup_decl (var, ctx);
11290 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11291 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11292 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11293 x = build_simple_mem_ref (x);
11294 SET_DECL_VALUE_EXPR (new_var, x);
11295 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11297 map_cnt++;
11300 if (offloaded)
11302 target_nesting_level++;
11303 lower_omp (&tgt_body, ctx);
11304 target_nesting_level--;
11306 else if (data_region)
11307 lower_omp (&tgt_body, ctx);
11309 if (offloaded)
11311 /* Declare all the variables created by mapping and the variables
11312 declared in the scope of the target body. */
11313 record_vars_into (ctx->block_vars, child_fn);
11314 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11317 olist = NULL;
11318 ilist = NULL;
11319 if (ctx->record_type)
11321 ctx->sender_decl
11322 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11323 DECL_NAMELESS (ctx->sender_decl) = 1;
11324 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11325 t = make_tree_vec (3);
11326 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11327 TREE_VEC_ELT (t, 1)
11328 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11329 ".omp_data_sizes");
11330 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11331 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11332 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11333 tree tkind_type;
11334 int talign_shift;
11335 if (is_gimple_omp_oacc (stmt))
11337 tkind_type = short_unsigned_type_node;
11338 talign_shift = 8;
11340 else
11342 tkind_type = unsigned_char_type_node;
11343 talign_shift = 3;
11345 TREE_VEC_ELT (t, 2)
11346 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11347 ".omp_data_kinds");
11348 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11349 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11350 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11351 gimple_omp_target_set_data_arg (stmt, t);
11353 vec<constructor_elt, va_gc> *vsize;
11354 vec<constructor_elt, va_gc> *vkind;
11355 vec_alloc (vsize, map_cnt);
11356 vec_alloc (vkind, map_cnt);
11357 unsigned int map_idx = 0;
11359 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11360 switch (OMP_CLAUSE_CODE (c))
11362 tree ovar, nc;
11364 default:
11365 break;
11366 case OMP_CLAUSE_MAP:
11367 case OMP_CLAUSE_TO:
11368 case OMP_CLAUSE_FROM:
11369 nc = c;
11370 ovar = OMP_CLAUSE_DECL (c);
11371 if (!DECL_P (ovar))
11373 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11374 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11376 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11377 == get_base_address (ovar));
11378 nc = OMP_CLAUSE_CHAIN (c);
11379 ovar = OMP_CLAUSE_DECL (nc);
11381 else
11383 tree x = build_sender_ref (ovar, ctx);
11384 tree v
11385 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11386 gimplify_assign (x, v, &ilist);
11387 nc = NULL_TREE;
11390 else
11392 if (DECL_SIZE (ovar)
11393 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11395 tree ovar2 = DECL_VALUE_EXPR (ovar);
11396 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11397 ovar2 = TREE_OPERAND (ovar2, 0);
11398 gcc_assert (DECL_P (ovar2));
11399 ovar = ovar2;
11401 if (!maybe_lookup_field (ovar, ctx))
11402 continue;
11405 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11406 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11407 talign = DECL_ALIGN_UNIT (ovar);
11408 if (nc)
11410 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11411 tree x = build_sender_ref (ovar, ctx);
11412 if (maybe_lookup_oacc_reduction (var, ctx))
11414 gcc_checking_assert (offloaded
11415 && is_gimple_omp_oacc (stmt));
11416 gimplify_assign (x, var, &ilist);
11418 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11419 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11420 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11421 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11423 gcc_assert (offloaded);
11424 tree avar
11425 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11426 mark_addressable (avar);
11427 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11428 talign = DECL_ALIGN_UNIT (avar);
11429 avar = build_fold_addr_expr (avar);
11430 gimplify_assign (x, avar, &ilist);
11432 else if (is_gimple_reg (var))
11434 gcc_assert (offloaded);
11435 tree avar = create_tmp_var (TREE_TYPE (var));
11436 mark_addressable (avar);
11437 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11438 if (GOMP_MAP_COPY_TO_P (map_kind)
11439 || map_kind == GOMP_MAP_POINTER
11440 || map_kind == GOMP_MAP_TO_PSET
11441 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11442 gimplify_assign (avar, var, &ilist);
11443 avar = build_fold_addr_expr (avar);
11444 gimplify_assign (x, avar, &ilist);
11445 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11446 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11447 && !TYPE_READONLY (TREE_TYPE (var)))
11449 x = build_sender_ref (ovar, ctx);
11450 x = build_simple_mem_ref (x);
11451 gimplify_assign (var, x, &olist);
11454 else
11456 var = build_fold_addr_expr (var);
11457 gimplify_assign (x, var, &ilist);
11460 tree s = OMP_CLAUSE_SIZE (c);
11461 if (s == NULL_TREE)
11462 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11463 s = fold_convert (size_type_node, s);
11464 tree purpose = size_int (map_idx++);
11465 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11466 if (TREE_CODE (s) != INTEGER_CST)
11467 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11469 unsigned HOST_WIDE_INT tkind;
11470 switch (OMP_CLAUSE_CODE (c))
11472 case OMP_CLAUSE_MAP:
11473 tkind = OMP_CLAUSE_MAP_KIND (c);
11474 break;
11475 case OMP_CLAUSE_TO:
11476 tkind = GOMP_MAP_TO;
11477 break;
11478 case OMP_CLAUSE_FROM:
11479 tkind = GOMP_MAP_FROM;
11480 break;
11481 default:
11482 gcc_unreachable ();
11484 gcc_checking_assert (tkind
11485 < (HOST_WIDE_INT_C (1U) << talign_shift));
11486 talign = ceil_log2 (talign);
11487 tkind |= talign << talign_shift;
11488 gcc_checking_assert (tkind
11489 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11490 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11491 build_int_cstu (tkind_type, tkind));
11492 if (nc && nc != c)
11493 c = nc;
11496 gcc_assert (map_idx == map_cnt);
11498 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11499 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11500 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11501 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11502 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11504 gimple_seq initlist = NULL;
11505 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11506 TREE_VEC_ELT (t, 1)),
11507 &initlist, true, NULL_TREE);
11508 gimple_seq_add_seq (&ilist, initlist);
11510 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11511 NULL);
11512 TREE_THIS_VOLATILE (clobber) = 1;
11513 gimple_seq_add_stmt (&olist,
11514 gimple_build_assign (TREE_VEC_ELT (t, 1),
11515 clobber));
11518 tree clobber = build_constructor (ctx->record_type, NULL);
11519 TREE_THIS_VOLATILE (clobber) = 1;
11520 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11521 clobber));
11524 /* Once all the expansions are done, sequence all the different
11525 fragments inside gimple_omp_body. */
11527 new_body = NULL;
11529 if (offloaded
11530 && ctx->record_type)
11532 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11533 /* fixup_child_record_type might have changed receiver_decl's type. */
11534 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11535 gimple_seq_add_stmt (&new_body,
11536 gimple_build_assign (ctx->receiver_decl, t));
11539 if (offloaded)
11541 gimple_seq_add_seq (&new_body, tgt_body);
11542 new_body = maybe_catch_exception (new_body);
11544 else if (data_region)
11545 new_body = tgt_body;
11546 if (offloaded || data_region)
11548 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11549 gimple_omp_set_body (stmt, new_body);
11552 bind = gimple_build_bind (NULL, NULL,
11553 tgt_bind ? gimple_bind_block (tgt_bind)
11554 : NULL_TREE);
11555 gsi_replace (gsi_p, bind, true);
11556 gimple_bind_add_seq (bind, irlist);
11557 gimple_bind_add_seq (bind, ilist);
11558 gimple_bind_add_stmt (bind, stmt);
11559 gimple_bind_add_seq (bind, olist);
11560 gimple_bind_add_seq (bind, orlist);
11562 pop_gimplify_context (NULL);
11565 /* Expand code for an OpenMP teams directive. */
11567 static void
11568 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11570 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11571 push_gimplify_context ();
11573 tree block = make_node (BLOCK);
11574 gbind *bind = gimple_build_bind (NULL, NULL, block);
11575 gsi_replace (gsi_p, bind, true);
11576 gimple_seq bind_body = NULL;
11577 gimple_seq dlist = NULL;
11578 gimple_seq olist = NULL;
11580 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11581 OMP_CLAUSE_NUM_TEAMS);
11582 if (num_teams == NULL_TREE)
11583 num_teams = build_int_cst (unsigned_type_node, 0);
11584 else
11586 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11587 num_teams = fold_convert (unsigned_type_node, num_teams);
11588 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11590 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11591 OMP_CLAUSE_THREAD_LIMIT);
11592 if (thread_limit == NULL_TREE)
11593 thread_limit = build_int_cst (unsigned_type_node, 0);
11594 else
11596 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11597 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11598 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11599 fb_rvalue);
11602 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11603 &bind_body, &dlist, ctx, NULL);
11604 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11605 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11606 gimple_seq_add_stmt (&bind_body, teams_stmt);
11608 location_t loc = gimple_location (teams_stmt);
11609 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11610 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11611 gimple_set_location (call, loc);
11612 gimple_seq_add_stmt (&bind_body, call);
11614 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11615 gimple_omp_set_body (teams_stmt, NULL);
11616 gimple_seq_add_seq (&bind_body, olist);
11617 gimple_seq_add_seq (&bind_body, dlist);
11618 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11619 gimple_bind_set_body (bind, bind_body);
11621 pop_gimplify_context (bind);
11623 gimple_bind_append_vars (bind, ctx->block_vars);
11624 BLOCK_VARS (block) = ctx->block_vars;
11625 if (BLOCK_VARS (block))
11626 TREE_USED (block) = 1;
11630 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11631 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11632 of OMP context, but with task_shared_vars set. */
11634 static tree
11635 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11636 void *data)
11638 tree t = *tp;
11640 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11641 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11642 return t;
11644 if (task_shared_vars
11645 && DECL_P (t)
11646 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11647 return t;
11649 /* If a global variable has been privatized, TREE_CONSTANT on
11650 ADDR_EXPR might be wrong. */
11651 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11652 recompute_tree_invariant_for_addr_expr (t);
11654 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11655 return NULL_TREE;
11658 static void
11659 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11661 gimple stmt = gsi_stmt (*gsi_p);
11662 struct walk_stmt_info wi;
11663 gcall *call_stmt;
11665 if (gimple_has_location (stmt))
11666 input_location = gimple_location (stmt);
11668 if (task_shared_vars)
11669 memset (&wi, '\0', sizeof (wi));
11671 /* If we have issued syntax errors, avoid doing any heavy lifting.
11672 Just replace the OMP directives with a NOP to avoid
11673 confusing RTL expansion. */
11674 if (seen_error () && is_gimple_omp (stmt))
11676 gsi_replace (gsi_p, gimple_build_nop (), true);
11677 return;
11680 switch (gimple_code (stmt))
11682 case GIMPLE_COND:
11684 gcond *cond_stmt = as_a <gcond *> (stmt);
11685 if ((ctx || task_shared_vars)
11686 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11687 lower_omp_regimplify_p,
11688 ctx ? NULL : &wi, NULL)
11689 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11690 lower_omp_regimplify_p,
11691 ctx ? NULL : &wi, NULL)))
11692 gimple_regimplify_operands (cond_stmt, gsi_p);
11694 break;
11695 case GIMPLE_CATCH:
11696 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11697 break;
11698 case GIMPLE_EH_FILTER:
11699 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11700 break;
11701 case GIMPLE_TRY:
11702 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11703 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11704 break;
11705 case GIMPLE_TRANSACTION:
11706 lower_omp (gimple_transaction_body_ptr (
11707 as_a <gtransaction *> (stmt)),
11708 ctx);
11709 break;
11710 case GIMPLE_BIND:
11711 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11712 break;
11713 case GIMPLE_OMP_PARALLEL:
11714 case GIMPLE_OMP_TASK:
11715 ctx = maybe_lookup_ctx (stmt);
11716 gcc_assert (ctx);
11717 if (ctx->cancellable)
11718 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11719 lower_omp_taskreg (gsi_p, ctx);
11720 break;
11721 case GIMPLE_OMP_FOR:
11722 ctx = maybe_lookup_ctx (stmt);
11723 gcc_assert (ctx);
11724 if (ctx->cancellable)
11725 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11726 lower_omp_for (gsi_p, ctx);
11727 break;
11728 case GIMPLE_OMP_SECTIONS:
11729 ctx = maybe_lookup_ctx (stmt);
11730 gcc_assert (ctx);
11731 if (ctx->cancellable)
11732 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11733 lower_omp_sections (gsi_p, ctx);
11734 break;
11735 case GIMPLE_OMP_SINGLE:
11736 ctx = maybe_lookup_ctx (stmt);
11737 gcc_assert (ctx);
11738 lower_omp_single (gsi_p, ctx);
11739 break;
11740 case GIMPLE_OMP_MASTER:
11741 ctx = maybe_lookup_ctx (stmt);
11742 gcc_assert (ctx);
11743 lower_omp_master (gsi_p, ctx);
11744 break;
11745 case GIMPLE_OMP_TASKGROUP:
11746 ctx = maybe_lookup_ctx (stmt);
11747 gcc_assert (ctx);
11748 lower_omp_taskgroup (gsi_p, ctx);
11749 break;
11750 case GIMPLE_OMP_ORDERED:
11751 ctx = maybe_lookup_ctx (stmt);
11752 gcc_assert (ctx);
11753 lower_omp_ordered (gsi_p, ctx);
11754 break;
11755 case GIMPLE_OMP_CRITICAL:
11756 ctx = maybe_lookup_ctx (stmt);
11757 gcc_assert (ctx);
11758 lower_omp_critical (gsi_p, ctx);
11759 break;
11760 case GIMPLE_OMP_ATOMIC_LOAD:
11761 if ((ctx || task_shared_vars)
11762 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11763 as_a <gomp_atomic_load *> (stmt)),
11764 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11765 gimple_regimplify_operands (stmt, gsi_p);
11766 break;
11767 case GIMPLE_OMP_TARGET:
11768 ctx = maybe_lookup_ctx (stmt);
11769 gcc_assert (ctx);
11770 lower_omp_target (gsi_p, ctx);
11771 break;
11772 case GIMPLE_OMP_TEAMS:
11773 ctx = maybe_lookup_ctx (stmt);
11774 gcc_assert (ctx);
11775 lower_omp_teams (gsi_p, ctx);
11776 break;
11777 case GIMPLE_CALL:
11778 tree fndecl;
11779 call_stmt = as_a <gcall *> (stmt);
11780 fndecl = gimple_call_fndecl (call_stmt);
11781 if (fndecl
11782 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11783 switch (DECL_FUNCTION_CODE (fndecl))
11785 case BUILT_IN_GOMP_BARRIER:
11786 if (ctx == NULL)
11787 break;
11788 /* FALLTHRU */
11789 case BUILT_IN_GOMP_CANCEL:
11790 case BUILT_IN_GOMP_CANCELLATION_POINT:
11791 omp_context *cctx;
11792 cctx = ctx;
11793 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11794 cctx = cctx->outer;
11795 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
11796 if (!cctx->cancellable)
11798 if (DECL_FUNCTION_CODE (fndecl)
11799 == BUILT_IN_GOMP_CANCELLATION_POINT)
11801 stmt = gimple_build_nop ();
11802 gsi_replace (gsi_p, stmt, false);
11804 break;
11806 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11808 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11809 gimple_call_set_fndecl (call_stmt, fndecl);
11810 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
11812 tree lhs;
11813 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
11814 gimple_call_set_lhs (call_stmt, lhs);
11815 tree fallthru_label;
11816 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11817 gimple g;
11818 g = gimple_build_label (fallthru_label);
11819 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11820 g = gimple_build_cond (NE_EXPR, lhs,
11821 fold_convert (TREE_TYPE (lhs),
11822 boolean_false_node),
11823 cctx->cancel_label, fallthru_label);
11824 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11825 break;
11826 default:
11827 break;
11829 /* FALLTHRU */
11830 default:
11831 if ((ctx || task_shared_vars)
11832 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11833 ctx ? NULL : &wi))
11835 /* Just remove clobbers, this should happen only if we have
11836 "privatized" local addressable variables in SIMD regions,
11837 the clobber isn't needed in that case and gimplifying address
11838 of the ARRAY_REF into a pointer and creating MEM_REF based
11839 clobber would create worse code than we get with the clobber
11840 dropped. */
11841 if (gimple_clobber_p (stmt))
11843 gsi_replace (gsi_p, gimple_build_nop (), true);
11844 break;
11846 gimple_regimplify_operands (stmt, gsi_p);
11848 break;
11852 static void
11853 lower_omp (gimple_seq *body, omp_context *ctx)
11855 location_t saved_location = input_location;
11856 gimple_stmt_iterator gsi;
11857 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11858 lower_omp_1 (&gsi, ctx);
11859 /* During gimplification, we haven't folded statments inside offloading
11860 regions (gimplify.c:maybe_fold_stmt); do that now. */
11861 if (target_nesting_level)
11862 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11863 fold_stmt (&gsi);
11864 input_location = saved_location;
11867 /* Main entry point. */
11869 static unsigned int
11870 execute_lower_omp (void)
11872 gimple_seq body;
11873 int i;
11874 omp_context *ctx;
11876 /* This pass always runs, to provide PROP_gimple_lomp.
11877 But often, there is nothing to do. */
11878 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11879 && flag_openmp_simd == 0)
11880 return 0;
11882 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11883 delete_omp_context);
11885 body = gimple_body (current_function_decl);
11886 scan_omp (&body, NULL);
11887 gcc_assert (taskreg_nesting_level == 0);
11888 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11889 finish_taskreg_scan (ctx);
11890 taskreg_contexts.release ();
11892 if (all_contexts->root)
11894 if (task_shared_vars)
11895 push_gimplify_context ();
11896 lower_omp (&body, NULL);
11897 if (task_shared_vars)
11898 pop_gimplify_context (NULL);
11901 if (all_contexts)
11903 splay_tree_delete (all_contexts);
11904 all_contexts = NULL;
11906 BITMAP_FREE (task_shared_vars);
11907 return 0;
11910 namespace {
11912 const pass_data pass_data_lower_omp =
11914 GIMPLE_PASS, /* type */
11915 "omplower", /* name */
11916 OPTGROUP_NONE, /* optinfo_flags */
11917 TV_NONE, /* tv_id */
11918 PROP_gimple_any, /* properties_required */
11919 PROP_gimple_lomp, /* properties_provided */
11920 0, /* properties_destroyed */
11921 0, /* todo_flags_start */
11922 0, /* todo_flags_finish */
11925 class pass_lower_omp : public gimple_opt_pass
11927 public:
11928 pass_lower_omp (gcc::context *ctxt)
11929 : gimple_opt_pass (pass_data_lower_omp, ctxt)
11932 /* opt_pass methods: */
11933 virtual unsigned int execute (function *) { return execute_lower_omp (); }
11935 }; // class pass_lower_omp
11937 } // anon namespace
11939 gimple_opt_pass *
11940 make_pass_lower_omp (gcc::context *ctxt)
11942 return new pass_lower_omp (ctxt);
11945 /* The following is a utility to diagnose structured block violations.
11946 It is not part of the "omplower" pass, as that's invoked too late. It
11947 should be invoked by the respective front ends after gimplification. */
11949 static splay_tree all_labels;
11951 /* Check for mismatched contexts and generate an error if needed. Return
11952 true if an error is detected. */
11954 static bool
11955 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
11956 gimple branch_ctx, gimple label_ctx)
11958 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
11959 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
11961 if (label_ctx == branch_ctx)
11962 return false;
11964 const char* kind = NULL;
11966 if (flag_cilkplus)
11968 if ((branch_ctx
11969 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
11970 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
11971 || (label_ctx
11972 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
11973 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
11974 kind = "Cilk Plus";
11976 if (flag_openacc)
11978 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
11979 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
11981 gcc_checking_assert (kind == NULL);
11982 kind = "OpenACC";
11985 if (kind == NULL)
11987 gcc_checking_assert (flag_openmp);
11988 kind = "OpenMP";
11992 Previously we kept track of the label's entire context in diagnose_sb_[12]
11993 so we could traverse it and issue a correct "exit" or "enter" error
11994 message upon a structured block violation.
11996 We built the context by building a list with tree_cons'ing, but there is
11997 no easy counterpart in gimple tuples. It seems like far too much work
11998 for issuing exit/enter error messages. If someone really misses the
11999 distinct error message... patches welcome.
12002 #if 0
12003 /* Try to avoid confusing the user by producing and error message
12004 with correct "exit" or "enter" verbiage. We prefer "exit"
12005 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12006 if (branch_ctx == NULL)
12007 exit_p = false;
12008 else
12010 while (label_ctx)
12012 if (TREE_VALUE (label_ctx) == branch_ctx)
12014 exit_p = false;
12015 break;
12017 label_ctx = TREE_CHAIN (label_ctx);
12021 if (exit_p)
12022 error ("invalid exit from %s structured block", kind);
12023 else
12024 error ("invalid entry to %s structured block", kind);
12025 #endif
12027 /* If it's obvious we have an invalid entry, be specific about the error. */
12028 if (branch_ctx == NULL)
12029 error ("invalid entry to %s structured block", kind);
12030 else
12032 /* Otherwise, be vague and lazy, but efficient. */
12033 error ("invalid branch to/from %s structured block", kind);
12036 gsi_replace (gsi_p, gimple_build_nop (), false);
12037 return true;
12040 /* Pass 1: Create a minimal tree of structured blocks, and record
12041 where each label is found. */
12043 static tree
12044 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12045 struct walk_stmt_info *wi)
12047 gimple context = (gimple) wi->info;
12048 gimple inner_context;
12049 gimple stmt = gsi_stmt (*gsi_p);
12051 *handled_ops_p = true;
12053 switch (gimple_code (stmt))
12055 WALK_SUBSTMTS;
12057 case GIMPLE_OMP_PARALLEL:
12058 case GIMPLE_OMP_TASK:
12059 case GIMPLE_OMP_SECTIONS:
12060 case GIMPLE_OMP_SINGLE:
12061 case GIMPLE_OMP_SECTION:
12062 case GIMPLE_OMP_MASTER:
12063 case GIMPLE_OMP_ORDERED:
12064 case GIMPLE_OMP_CRITICAL:
12065 case GIMPLE_OMP_TARGET:
12066 case GIMPLE_OMP_TEAMS:
12067 case GIMPLE_OMP_TASKGROUP:
12068 /* The minimal context here is just the current OMP construct. */
12069 inner_context = stmt;
12070 wi->info = inner_context;
12071 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12072 wi->info = context;
12073 break;
12075 case GIMPLE_OMP_FOR:
12076 inner_context = stmt;
12077 wi->info = inner_context;
12078 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12079 walk them. */
12080 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12081 diagnose_sb_1, NULL, wi);
12082 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12083 wi->info = context;
12084 break;
12086 case GIMPLE_LABEL:
12087 splay_tree_insert (all_labels,
12088 (splay_tree_key) gimple_label_label (
12089 as_a <glabel *> (stmt)),
12090 (splay_tree_value) context);
12091 break;
12093 default:
12094 break;
12097 return NULL_TREE;
12100 /* Pass 2: Check each branch and see if its context differs from that of
12101 the destination label's context. */
12103 static tree
12104 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12105 struct walk_stmt_info *wi)
12107 gimple context = (gimple) wi->info;
12108 splay_tree_node n;
12109 gimple stmt = gsi_stmt (*gsi_p);
12111 *handled_ops_p = true;
12113 switch (gimple_code (stmt))
12115 WALK_SUBSTMTS;
12117 case GIMPLE_OMP_PARALLEL:
12118 case GIMPLE_OMP_TASK:
12119 case GIMPLE_OMP_SECTIONS:
12120 case GIMPLE_OMP_SINGLE:
12121 case GIMPLE_OMP_SECTION:
12122 case GIMPLE_OMP_MASTER:
12123 case GIMPLE_OMP_ORDERED:
12124 case GIMPLE_OMP_CRITICAL:
12125 case GIMPLE_OMP_TARGET:
12126 case GIMPLE_OMP_TEAMS:
12127 case GIMPLE_OMP_TASKGROUP:
12128 wi->info = stmt;
12129 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12130 wi->info = context;
12131 break;
12133 case GIMPLE_OMP_FOR:
12134 wi->info = stmt;
12135 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12136 walk them. */
12137 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12138 diagnose_sb_2, NULL, wi);
12139 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12140 wi->info = context;
12141 break;
12143 case GIMPLE_COND:
12145 gcond *cond_stmt = as_a <gcond *> (stmt);
12146 tree lab = gimple_cond_true_label (cond_stmt);
12147 if (lab)
12149 n = splay_tree_lookup (all_labels,
12150 (splay_tree_key) lab);
12151 diagnose_sb_0 (gsi_p, context,
12152 n ? (gimple) n->value : NULL);
12154 lab = gimple_cond_false_label (cond_stmt);
12155 if (lab)
12157 n = splay_tree_lookup (all_labels,
12158 (splay_tree_key) lab);
12159 diagnose_sb_0 (gsi_p, context,
12160 n ? (gimple) n->value : NULL);
12163 break;
12165 case GIMPLE_GOTO:
12167 tree lab = gimple_goto_dest (stmt);
12168 if (TREE_CODE (lab) != LABEL_DECL)
12169 break;
12171 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12172 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12174 break;
12176 case GIMPLE_SWITCH:
12178 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12179 unsigned int i;
12180 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12182 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12183 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12184 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12185 break;
12188 break;
12190 case GIMPLE_RETURN:
12191 diagnose_sb_0 (gsi_p, context, NULL);
12192 break;
12194 default:
12195 break;
12198 return NULL_TREE;
12201 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12202 GIMPLE_* codes. */
12203 bool
12204 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12205 int *region_idx)
12207 gimple last = last_stmt (bb);
12208 enum gimple_code code = gimple_code (last);
12209 struct omp_region *cur_region = *region;
12210 bool fallthru = false;
12212 switch (code)
12214 case GIMPLE_OMP_PARALLEL:
12215 case GIMPLE_OMP_TASK:
12216 case GIMPLE_OMP_FOR:
12217 case GIMPLE_OMP_SINGLE:
12218 case GIMPLE_OMP_TEAMS:
12219 case GIMPLE_OMP_MASTER:
12220 case GIMPLE_OMP_TASKGROUP:
12221 case GIMPLE_OMP_ORDERED:
12222 case GIMPLE_OMP_CRITICAL:
12223 case GIMPLE_OMP_SECTION:
12224 cur_region = new_omp_region (bb, code, cur_region);
12225 fallthru = true;
12226 break;
12228 case GIMPLE_OMP_TARGET:
12229 cur_region = new_omp_region (bb, code, cur_region);
12230 fallthru = true;
12231 switch (gimple_omp_target_kind (last))
12233 case GF_OMP_TARGET_KIND_REGION:
12234 case GF_OMP_TARGET_KIND_DATA:
12235 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12236 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12237 case GF_OMP_TARGET_KIND_OACC_DATA:
12238 break;
12239 case GF_OMP_TARGET_KIND_UPDATE:
12240 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12241 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12242 cur_region = cur_region->outer;
12243 break;
12244 default:
12245 gcc_unreachable ();
12247 break;
12249 case GIMPLE_OMP_SECTIONS:
12250 cur_region = new_omp_region (bb, code, cur_region);
12251 fallthru = true;
12252 break;
12254 case GIMPLE_OMP_SECTIONS_SWITCH:
12255 fallthru = false;
12256 break;
12258 case GIMPLE_OMP_ATOMIC_LOAD:
12259 case GIMPLE_OMP_ATOMIC_STORE:
12260 fallthru = true;
12261 break;
12263 case GIMPLE_OMP_RETURN:
12264 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12265 somewhere other than the next block. This will be
12266 created later. */
12267 cur_region->exit = bb;
12268 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12269 cur_region = cur_region->outer;
12270 break;
12272 case GIMPLE_OMP_CONTINUE:
12273 cur_region->cont = bb;
12274 switch (cur_region->type)
12276 case GIMPLE_OMP_FOR:
12277 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12278 succs edges as abnormal to prevent splitting
12279 them. */
12280 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12281 /* Make the loopback edge. */
12282 make_edge (bb, single_succ (cur_region->entry),
12283 EDGE_ABNORMAL);
12285 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12286 corresponds to the case that the body of the loop
12287 is not executed at all. */
12288 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12289 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12290 fallthru = false;
12291 break;
12293 case GIMPLE_OMP_SECTIONS:
12294 /* Wire up the edges into and out of the nested sections. */
12296 basic_block switch_bb = single_succ (cur_region->entry);
12298 struct omp_region *i;
12299 for (i = cur_region->inner; i ; i = i->next)
12301 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12302 make_edge (switch_bb, i->entry, 0);
12303 make_edge (i->exit, bb, EDGE_FALLTHRU);
12306 /* Make the loopback edge to the block with
12307 GIMPLE_OMP_SECTIONS_SWITCH. */
12308 make_edge (bb, switch_bb, 0);
12310 /* Make the edge from the switch to exit. */
12311 make_edge (switch_bb, bb->next_bb, 0);
12312 fallthru = false;
12314 break;
12316 default:
12317 gcc_unreachable ();
12319 break;
12321 default:
12322 gcc_unreachable ();
12325 if (*region != cur_region)
12327 *region = cur_region;
12328 if (cur_region)
12329 *region_idx = cur_region->entry->index;
12330 else
12331 *region_idx = 0;
12334 return fallthru;
12337 static unsigned int
12338 diagnose_omp_structured_block_errors (void)
12340 struct walk_stmt_info wi;
12341 gimple_seq body = gimple_body (current_function_decl);
12343 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12345 memset (&wi, 0, sizeof (wi));
12346 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12348 memset (&wi, 0, sizeof (wi));
12349 wi.want_locations = true;
12350 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12352 gimple_set_body (current_function_decl, body);
12354 splay_tree_delete (all_labels);
12355 all_labels = NULL;
12357 return 0;
12360 namespace {
12362 const pass_data pass_data_diagnose_omp_blocks =
12364 GIMPLE_PASS, /* type */
12365 "*diagnose_omp_blocks", /* name */
12366 OPTGROUP_NONE, /* optinfo_flags */
12367 TV_NONE, /* tv_id */
12368 PROP_gimple_any, /* properties_required */
12369 0, /* properties_provided */
12370 0, /* properties_destroyed */
12371 0, /* todo_flags_start */
12372 0, /* todo_flags_finish */
12375 class pass_diagnose_omp_blocks : public gimple_opt_pass
12377 public:
12378 pass_diagnose_omp_blocks (gcc::context *ctxt)
12379 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12382 /* opt_pass methods: */
12383 virtual bool gate (function *)
12385 return flag_cilkplus || flag_openacc || flag_openmp;
12387 virtual unsigned int execute (function *)
12389 return diagnose_omp_structured_block_errors ();
12392 }; // class pass_diagnose_omp_blocks
12394 } // anon namespace
12396 gimple_opt_pass *
12397 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12399 return new pass_diagnose_omp_blocks (ctxt);
12402 /* SIMD clone supporting code. */
12404 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12405 of arguments to reserve space for. */
12407 static struct cgraph_simd_clone *
12408 simd_clone_struct_alloc (int nargs)
12410 struct cgraph_simd_clone *clone_info;
12411 size_t len = (sizeof (struct cgraph_simd_clone)
12412 + nargs * sizeof (struct cgraph_simd_clone_arg));
12413 clone_info = (struct cgraph_simd_clone *)
12414 ggc_internal_cleared_alloc (len);
12415 return clone_info;
12418 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12420 static inline void
12421 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12422 struct cgraph_simd_clone *from)
12424 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12425 + ((from->nargs - from->inbranch)
12426 * sizeof (struct cgraph_simd_clone_arg))));
12429 /* Return vector of parameter types of function FNDECL. This uses
12430 TYPE_ARG_TYPES if available, otherwise falls back to types of
12431 DECL_ARGUMENTS types. */
12433 vec<tree>
12434 simd_clone_vector_of_formal_parm_types (tree fndecl)
12436 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12437 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12438 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12439 unsigned int i;
12440 tree arg;
12441 FOR_EACH_VEC_ELT (args, i, arg)
12442 args[i] = TREE_TYPE (args[i]);
12443 return args;
12446 /* Given a simd function in NODE, extract the simd specific
12447 information from the OMP clauses passed in CLAUSES, and return
12448 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12449 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12450 otherwise set to FALSE. */
12452 static struct cgraph_simd_clone *
12453 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12454 bool *inbranch_specified)
12456 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12457 tree t;
12458 int n;
12459 *inbranch_specified = false;
12461 n = args.length ();
12462 if (n > 0 && args.last () == void_type_node)
12463 n--;
12465 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12466 be cloned have a distinctive artificial label in addition to "omp
12467 declare simd". */
12468 bool cilk_clone
12469 = (flag_cilkplus
12470 && lookup_attribute ("cilk simd function",
12471 DECL_ATTRIBUTES (node->decl)));
12473 /* Allocate one more than needed just in case this is an in-branch
12474 clone which will require a mask argument. */
12475 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12476 clone_info->nargs = n;
12477 clone_info->cilk_elemental = cilk_clone;
12479 if (!clauses)
12481 args.release ();
12482 return clone_info;
12484 clauses = TREE_VALUE (clauses);
12485 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12486 return clone_info;
12488 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12490 switch (OMP_CLAUSE_CODE (t))
12492 case OMP_CLAUSE_INBRANCH:
12493 clone_info->inbranch = 1;
12494 *inbranch_specified = true;
12495 break;
12496 case OMP_CLAUSE_NOTINBRANCH:
12497 clone_info->inbranch = 0;
12498 *inbranch_specified = true;
12499 break;
12500 case OMP_CLAUSE_SIMDLEN:
12501 clone_info->simdlen
12502 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12503 break;
12504 case OMP_CLAUSE_LINEAR:
12506 tree decl = OMP_CLAUSE_DECL (t);
12507 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12508 int argno = TREE_INT_CST_LOW (decl);
12509 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12511 clone_info->args[argno].arg_type
12512 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12513 clone_info->args[argno].linear_step = tree_to_shwi (step);
12514 gcc_assert (clone_info->args[argno].linear_step >= 0
12515 && clone_info->args[argno].linear_step < n);
12517 else
12519 if (POINTER_TYPE_P (args[argno]))
12520 step = fold_convert (ssizetype, step);
12521 if (!tree_fits_shwi_p (step))
12523 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12524 "ignoring large linear step");
12525 args.release ();
12526 return NULL;
12528 else if (integer_zerop (step))
12530 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12531 "ignoring zero linear step");
12532 args.release ();
12533 return NULL;
12535 else
12537 clone_info->args[argno].arg_type
12538 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12539 clone_info->args[argno].linear_step = tree_to_shwi (step);
12542 break;
12544 case OMP_CLAUSE_UNIFORM:
12546 tree decl = OMP_CLAUSE_DECL (t);
12547 int argno = tree_to_uhwi (decl);
12548 clone_info->args[argno].arg_type
12549 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12550 break;
12552 case OMP_CLAUSE_ALIGNED:
12554 tree decl = OMP_CLAUSE_DECL (t);
12555 int argno = tree_to_uhwi (decl);
12556 clone_info->args[argno].alignment
12557 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12558 break;
12560 default:
12561 break;
12564 args.release ();
12565 return clone_info;
12568 /* Given a SIMD clone in NODE, calculate the characteristic data
12569 type and return the coresponding type. The characteristic data
12570 type is computed as described in the Intel Vector ABI. */
12572 static tree
12573 simd_clone_compute_base_data_type (struct cgraph_node *node,
12574 struct cgraph_simd_clone *clone_info)
12576 tree type = integer_type_node;
12577 tree fndecl = node->decl;
12579 /* a) For non-void function, the characteristic data type is the
12580 return type. */
12581 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12582 type = TREE_TYPE (TREE_TYPE (fndecl));
12584 /* b) If the function has any non-uniform, non-linear parameters,
12585 then the characteristic data type is the type of the first
12586 such parameter. */
12587 else
12589 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12590 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12591 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12593 type = map[i];
12594 break;
12596 map.release ();
12599 /* c) If the characteristic data type determined by a) or b) above
12600 is struct, union, or class type which is pass-by-value (except
12601 for the type that maps to the built-in complex data type), the
12602 characteristic data type is int. */
12603 if (RECORD_OR_UNION_TYPE_P (type)
12604 && !aggregate_value_p (type, NULL)
12605 && TREE_CODE (type) != COMPLEX_TYPE)
12606 return integer_type_node;
12608 /* d) If none of the above three classes is applicable, the
12609 characteristic data type is int. */
12611 return type;
12613 /* e) For Intel Xeon Phi native and offload compilation, if the
12614 resulting characteristic data type is 8-bit or 16-bit integer
12615 data type, the characteristic data type is int. */
12616 /* Well, we don't handle Xeon Phi yet. */
12619 static tree
12620 simd_clone_mangle (struct cgraph_node *node,
12621 struct cgraph_simd_clone *clone_info)
12623 char vecsize_mangle = clone_info->vecsize_mangle;
12624 char mask = clone_info->inbranch ? 'M' : 'N';
12625 unsigned int simdlen = clone_info->simdlen;
12626 unsigned int n;
12627 pretty_printer pp;
12629 gcc_assert (vecsize_mangle && simdlen);
12631 pp_string (&pp, "_ZGV");
12632 pp_character (&pp, vecsize_mangle);
12633 pp_character (&pp, mask);
12634 pp_decimal_int (&pp, simdlen);
12636 for (n = 0; n < clone_info->nargs; ++n)
12638 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12640 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12641 pp_character (&pp, 'u');
12642 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12644 gcc_assert (arg.linear_step != 0);
12645 pp_character (&pp, 'l');
12646 if (arg.linear_step > 1)
12647 pp_unsigned_wide_integer (&pp, arg.linear_step);
12648 else if (arg.linear_step < 0)
12650 pp_character (&pp, 'n');
12651 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12652 arg.linear_step));
12655 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12657 pp_character (&pp, 's');
12658 pp_unsigned_wide_integer (&pp, arg.linear_step);
12660 else
12661 pp_character (&pp, 'v');
12662 if (arg.alignment)
12664 pp_character (&pp, 'a');
12665 pp_decimal_int (&pp, arg.alignment);
12669 pp_underscore (&pp);
12670 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12671 if (*str == '*')
12672 ++str;
12673 pp_string (&pp, str);
12674 str = pp_formatted_text (&pp);
12676 /* If there already is a SIMD clone with the same mangled name, don't
12677 add another one. This can happen e.g. for
12678 #pragma omp declare simd
12679 #pragma omp declare simd simdlen(8)
12680 int foo (int, int);
12681 if the simdlen is assumed to be 8 for the first one, etc. */
12682 for (struct cgraph_node *clone = node->simd_clones; clone;
12683 clone = clone->simdclone->next_clone)
12684 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12685 str) == 0)
12686 return NULL_TREE;
12688 return get_identifier (str);
12691 /* Create a simd clone of OLD_NODE and return it. */
12693 static struct cgraph_node *
12694 simd_clone_create (struct cgraph_node *old_node)
12696 struct cgraph_node *new_node;
12697 if (old_node->definition)
12699 if (!old_node->has_gimple_body_p ())
12700 return NULL;
12701 old_node->get_body ();
12702 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12703 false, NULL, NULL,
12704 "simdclone");
12706 else
12708 tree old_decl = old_node->decl;
12709 tree new_decl = copy_node (old_node->decl);
12710 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12711 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12712 SET_DECL_RTL (new_decl, NULL);
12713 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12714 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12715 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12716 symtab->call_cgraph_insertion_hooks (new_node);
12718 if (new_node == NULL)
12719 return new_node;
12721 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12723 /* The function cgraph_function_versioning () will force the new
12724 symbol local. Undo this, and inherit external visability from
12725 the old node. */
12726 new_node->local.local = old_node->local.local;
12727 new_node->externally_visible = old_node->externally_visible;
12729 return new_node;
12732 /* Adjust the return type of the given function to its appropriate
12733 vector counterpart. Returns a simd array to be used throughout the
12734 function as a return value. */
12736 static tree
12737 simd_clone_adjust_return_type (struct cgraph_node *node)
12739 tree fndecl = node->decl;
12740 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12741 unsigned int veclen;
12742 tree t;
12744 /* Adjust the function return type. */
12745 if (orig_rettype == void_type_node)
12746 return NULL_TREE;
12747 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12748 t = TREE_TYPE (TREE_TYPE (fndecl));
12749 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12750 veclen = node->simdclone->vecsize_int;
12751 else
12752 veclen = node->simdclone->vecsize_float;
12753 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12754 if (veclen > node->simdclone->simdlen)
12755 veclen = node->simdclone->simdlen;
12756 if (POINTER_TYPE_P (t))
12757 t = pointer_sized_int_node;
12758 if (veclen == node->simdclone->simdlen)
12759 t = build_vector_type (t, node->simdclone->simdlen);
12760 else
12762 t = build_vector_type (t, veclen);
12763 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
12765 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12766 if (!node->definition)
12767 return NULL_TREE;
12769 t = DECL_RESULT (fndecl);
12770 /* Adjust the DECL_RESULT. */
12771 gcc_assert (TREE_TYPE (t) != void_type_node);
12772 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12773 relayout_decl (t);
12775 tree atype = build_array_type_nelts (orig_rettype,
12776 node->simdclone->simdlen);
12777 if (veclen != node->simdclone->simdlen)
12778 return build1 (VIEW_CONVERT_EXPR, atype, t);
12780 /* Set up a SIMD array to use as the return value. */
12781 tree retval = create_tmp_var_raw (atype, "retval");
12782 gimple_add_tmp_var (retval);
12783 return retval;
12786 /* Each vector argument has a corresponding array to be used locally
12787 as part of the eventual loop. Create such temporary array and
12788 return it.
12790 PREFIX is the prefix to be used for the temporary.
12792 TYPE is the inner element type.
12794 SIMDLEN is the number of elements. */
12796 static tree
12797 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12799 tree atype = build_array_type_nelts (type, simdlen);
12800 tree avar = create_tmp_var_raw (atype, prefix);
12801 gimple_add_tmp_var (avar);
12802 return avar;
12805 /* Modify the function argument types to their corresponding vector
12806 counterparts if appropriate. Also, create one array for each simd
12807 argument to be used locally when using the function arguments as
12808 part of the loop.
12810 NODE is the function whose arguments are to be adjusted.
12812 Returns an adjustment vector that will be filled describing how the
12813 argument types will be adjusted. */
12815 static ipa_parm_adjustment_vec
12816 simd_clone_adjust_argument_types (struct cgraph_node *node)
12818 vec<tree> args;
12819 ipa_parm_adjustment_vec adjustments;
12821 if (node->definition)
12822 args = ipa_get_vector_of_formal_parms (node->decl);
12823 else
12824 args = simd_clone_vector_of_formal_parm_types (node->decl);
12825 adjustments.create (args.length ());
12826 unsigned i, j, veclen;
12827 struct ipa_parm_adjustment adj;
12828 for (i = 0; i < node->simdclone->nargs; ++i)
12830 memset (&adj, 0, sizeof (adj));
12831 tree parm = args[i];
12832 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12833 adj.base_index = i;
12834 adj.base = parm;
12836 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12837 node->simdclone->args[i].orig_type = parm_type;
12839 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12841 /* No adjustment necessary for scalar arguments. */
12842 adj.op = IPA_PARM_OP_COPY;
12844 else
12846 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12847 veclen = node->simdclone->vecsize_int;
12848 else
12849 veclen = node->simdclone->vecsize_float;
12850 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12851 if (veclen > node->simdclone->simdlen)
12852 veclen = node->simdclone->simdlen;
12853 adj.arg_prefix = "simd";
12854 if (POINTER_TYPE_P (parm_type))
12855 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12856 else
12857 adj.type = build_vector_type (parm_type, veclen);
12858 node->simdclone->args[i].vector_type = adj.type;
12859 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12861 adjustments.safe_push (adj);
12862 if (j == veclen)
12864 memset (&adj, 0, sizeof (adj));
12865 adj.op = IPA_PARM_OP_NEW;
12866 adj.arg_prefix = "simd";
12867 adj.base_index = i;
12868 adj.type = node->simdclone->args[i].vector_type;
12872 if (node->definition)
12873 node->simdclone->args[i].simd_array
12874 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12875 parm_type, node->simdclone->simdlen);
12877 adjustments.safe_push (adj);
12880 if (node->simdclone->inbranch)
12882 tree base_type
12883 = simd_clone_compute_base_data_type (node->simdclone->origin,
12884 node->simdclone);
12886 memset (&adj, 0, sizeof (adj));
12887 adj.op = IPA_PARM_OP_NEW;
12888 adj.arg_prefix = "mask";
12890 adj.base_index = i;
12891 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12892 veclen = node->simdclone->vecsize_int;
12893 else
12894 veclen = node->simdclone->vecsize_float;
12895 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12896 if (veclen > node->simdclone->simdlen)
12897 veclen = node->simdclone->simdlen;
12898 if (POINTER_TYPE_P (base_type))
12899 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12900 else
12901 adj.type = build_vector_type (base_type, veclen);
12902 adjustments.safe_push (adj);
12904 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12905 adjustments.safe_push (adj);
12907 /* We have previously allocated one extra entry for the mask. Use
12908 it and fill it. */
12909 struct cgraph_simd_clone *sc = node->simdclone;
12910 sc->nargs++;
12911 if (node->definition)
12913 sc->args[i].orig_arg
12914 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12915 sc->args[i].simd_array
12916 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12918 sc->args[i].orig_type = base_type;
12919 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12922 if (node->definition)
12923 ipa_modify_formal_parameters (node->decl, adjustments);
12924 else
12926 tree new_arg_types = NULL_TREE, new_reversed;
12927 bool last_parm_void = false;
12928 if (args.length () > 0 && args.last () == void_type_node)
12929 last_parm_void = true;
12931 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12932 j = adjustments.length ();
12933 for (i = 0; i < j; i++)
12935 struct ipa_parm_adjustment *adj = &adjustments[i];
12936 tree ptype;
12937 if (adj->op == IPA_PARM_OP_COPY)
12938 ptype = args[adj->base_index];
12939 else
12940 ptype = adj->type;
12941 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12943 new_reversed = nreverse (new_arg_types);
12944 if (last_parm_void)
12946 if (new_reversed)
12947 TREE_CHAIN (new_arg_types) = void_list_node;
12948 else
12949 new_reversed = void_list_node;
12952 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
12953 TYPE_ARG_TYPES (new_type) = new_reversed;
12954 TREE_TYPE (node->decl) = new_type;
12956 adjustments.release ();
12958 args.release ();
12959 return adjustments;
12962 /* Initialize and copy the function arguments in NODE to their
12963 corresponding local simd arrays. Returns a fresh gimple_seq with
12964 the instruction sequence generated. */
12966 static gimple_seq
12967 simd_clone_init_simd_arrays (struct cgraph_node *node,
12968 ipa_parm_adjustment_vec adjustments)
12970 gimple_seq seq = NULL;
12971 unsigned i = 0, j = 0, k;
12973 for (tree arg = DECL_ARGUMENTS (node->decl);
12974 arg;
12975 arg = DECL_CHAIN (arg), i++, j++)
12977 if (adjustments[j].op == IPA_PARM_OP_COPY)
12978 continue;
12980 node->simdclone->args[i].vector_arg = arg;
12982 tree array = node->simdclone->args[i].simd_array;
12983 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
12985 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12986 tree ptr = build_fold_addr_expr (array);
12987 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
12988 build_int_cst (ptype, 0));
12989 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
12990 gimplify_and_add (t, &seq);
12992 else
12994 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
12995 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12996 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
12998 tree ptr = build_fold_addr_expr (array);
12999 int elemsize;
13000 if (k)
13002 arg = DECL_CHAIN (arg);
13003 j++;
13005 elemsize
13006 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13007 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13008 build_int_cst (ptype, k * elemsize));
13009 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13010 gimplify_and_add (t, &seq);
13014 return seq;
13017 /* Callback info for ipa_simd_modify_stmt_ops below. */
13019 struct modify_stmt_info {
13020 ipa_parm_adjustment_vec adjustments;
13021 gimple stmt;
13022 /* True if the parent statement was modified by
13023 ipa_simd_modify_stmt_ops. */
13024 bool modified;
13027 /* Callback for walk_gimple_op.
13029 Adjust operands from a given statement as specified in the
13030 adjustments vector in the callback data. */
13032 static tree
13033 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13035 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13036 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13037 tree *orig_tp = tp;
13038 if (TREE_CODE (*tp) == ADDR_EXPR)
13039 tp = &TREE_OPERAND (*tp, 0);
13040 struct ipa_parm_adjustment *cand = NULL;
13041 if (TREE_CODE (*tp) == PARM_DECL)
13042 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13043 else
13045 if (TYPE_P (*tp))
13046 *walk_subtrees = 0;
13049 tree repl = NULL_TREE;
13050 if (cand)
13051 repl = unshare_expr (cand->new_decl);
13052 else
13054 if (tp != orig_tp)
13056 *walk_subtrees = 0;
13057 bool modified = info->modified;
13058 info->modified = false;
13059 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13060 if (!info->modified)
13062 info->modified = modified;
13063 return NULL_TREE;
13065 info->modified = modified;
13066 repl = *tp;
13068 else
13069 return NULL_TREE;
13072 if (tp != orig_tp)
13074 repl = build_fold_addr_expr (repl);
13075 gimple stmt;
13076 if (is_gimple_debug (info->stmt))
13078 tree vexpr = make_node (DEBUG_EXPR_DECL);
13079 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13080 DECL_ARTIFICIAL (vexpr) = 1;
13081 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13082 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13083 repl = vexpr;
13085 else
13087 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13088 repl = gimple_assign_lhs (stmt);
13090 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13091 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13092 *orig_tp = repl;
13094 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13096 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13097 *tp = vce;
13099 else
13100 *tp = repl;
13102 info->modified = true;
13103 return NULL_TREE;
13106 /* Traverse the function body and perform all modifications as
13107 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13108 modified such that the replacement/reduction value will now be an
13109 offset into the corresponding simd_array.
13111 This function will replace all function argument uses with their
13112 corresponding simd array elements, and ajust the return values
13113 accordingly. */
13115 static void
13116 ipa_simd_modify_function_body (struct cgraph_node *node,
13117 ipa_parm_adjustment_vec adjustments,
13118 tree retval_array, tree iter)
13120 basic_block bb;
13121 unsigned int i, j, l;
13123 /* Re-use the adjustments array, but this time use it to replace
13124 every function argument use to an offset into the corresponding
13125 simd_array. */
13126 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13128 if (!node->simdclone->args[i].vector_arg)
13129 continue;
13131 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13132 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13133 adjustments[j].new_decl
13134 = build4 (ARRAY_REF,
13135 basetype,
13136 node->simdclone->args[i].simd_array,
13137 iter,
13138 NULL_TREE, NULL_TREE);
13139 if (adjustments[j].op == IPA_PARM_OP_NONE
13140 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13141 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13144 l = adjustments.length ();
13145 for (i = 1; i < num_ssa_names; i++)
13147 tree name = ssa_name (i);
13148 if (name
13149 && SSA_NAME_VAR (name)
13150 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13152 for (j = 0; j < l; j++)
13153 if (SSA_NAME_VAR (name) == adjustments[j].base
13154 && adjustments[j].new_decl)
13156 tree base_var;
13157 if (adjustments[j].new_ssa_base == NULL_TREE)
13159 base_var
13160 = copy_var_decl (adjustments[j].base,
13161 DECL_NAME (adjustments[j].base),
13162 TREE_TYPE (adjustments[j].base));
13163 adjustments[j].new_ssa_base = base_var;
13165 else
13166 base_var = adjustments[j].new_ssa_base;
13167 if (SSA_NAME_IS_DEFAULT_DEF (name))
13169 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13170 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13171 tree new_decl = unshare_expr (adjustments[j].new_decl);
13172 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13173 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13174 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13175 gimple stmt = gimple_build_assign (name, new_decl);
13176 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13178 else
13179 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13184 struct modify_stmt_info info;
13185 info.adjustments = adjustments;
13187 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13189 gimple_stmt_iterator gsi;
13191 gsi = gsi_start_bb (bb);
13192 while (!gsi_end_p (gsi))
13194 gimple stmt = gsi_stmt (gsi);
13195 info.stmt = stmt;
13196 struct walk_stmt_info wi;
13198 memset (&wi, 0, sizeof (wi));
13199 info.modified = false;
13200 wi.info = &info;
13201 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13203 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13205 tree retval = gimple_return_retval (return_stmt);
13206 if (!retval)
13208 gsi_remove (&gsi, true);
13209 continue;
13212 /* Replace `return foo' with `retval_array[iter] = foo'. */
13213 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13214 retval_array, iter, NULL, NULL);
13215 stmt = gimple_build_assign (ref, retval);
13216 gsi_replace (&gsi, stmt, true);
13217 info.modified = true;
13220 if (info.modified)
13222 update_stmt (stmt);
13223 if (maybe_clean_eh_stmt (stmt))
13224 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13226 gsi_next (&gsi);
13231 /* Adjust the argument types in NODE to their appropriate vector
13232 counterparts. */
13234 static void
13235 simd_clone_adjust (struct cgraph_node *node)
13237 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13239 targetm.simd_clone.adjust (node);
13241 tree retval = simd_clone_adjust_return_type (node);
13242 ipa_parm_adjustment_vec adjustments
13243 = simd_clone_adjust_argument_types (node);
13245 push_gimplify_context ();
13247 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13249 /* Adjust all uses of vector arguments accordingly. Adjust all
13250 return values accordingly. */
13251 tree iter = create_tmp_var (unsigned_type_node, "iter");
13252 tree iter1 = make_ssa_name (iter);
13253 tree iter2 = make_ssa_name (iter);
13254 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13256 /* Initialize the iteration variable. */
13257 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13258 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13259 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13260 /* Insert the SIMD array and iv initialization at function
13261 entry. */
13262 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13264 pop_gimplify_context (NULL);
13266 /* Create a new BB right before the original exit BB, to hold the
13267 iteration increment and the condition/branch. */
13268 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13269 basic_block incr_bb = create_empty_bb (orig_exit);
13270 add_bb_to_loop (incr_bb, body_bb->loop_father);
13271 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13272 flag. Set it now to be a FALLTHRU_EDGE. */
13273 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13274 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13275 for (unsigned i = 0;
13276 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13278 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13279 redirect_edge_succ (e, incr_bb);
13281 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13282 e->probability = REG_BR_PROB_BASE;
13283 gsi = gsi_last_bb (incr_bb);
13284 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13285 build_int_cst (unsigned_type_node, 1));
13286 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13288 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13289 struct loop *loop = alloc_loop ();
13290 cfun->has_force_vectorize_loops = true;
13291 loop->safelen = node->simdclone->simdlen;
13292 loop->force_vectorize = true;
13293 loop->header = body_bb;
13295 /* Branch around the body if the mask applies. */
13296 if (node->simdclone->inbranch)
13298 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13299 tree mask_array
13300 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13301 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13302 tree aref = build4 (ARRAY_REF,
13303 TREE_TYPE (TREE_TYPE (mask_array)),
13304 mask_array, iter1,
13305 NULL, NULL);
13306 g = gimple_build_assign (mask, aref);
13307 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13308 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13309 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13311 aref = build1 (VIEW_CONVERT_EXPR,
13312 build_nonstandard_integer_type (bitsize, 0), mask);
13313 mask = make_ssa_name (TREE_TYPE (aref));
13314 g = gimple_build_assign (mask, aref);
13315 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13318 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13319 NULL, NULL);
13320 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13321 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13322 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13325 /* Generate the condition. */
13326 g = gimple_build_cond (LT_EXPR,
13327 iter2,
13328 build_int_cst (unsigned_type_node,
13329 node->simdclone->simdlen),
13330 NULL, NULL);
13331 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13332 e = split_block (incr_bb, gsi_stmt (gsi));
13333 basic_block latch_bb = e->dest;
13334 basic_block new_exit_bb;
13335 new_exit_bb = split_block (latch_bb, NULL)->dest;
13336 loop->latch = latch_bb;
13338 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13340 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13341 /* The successor of incr_bb is already pointing to latch_bb; just
13342 change the flags.
13343 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13344 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13346 gphi *phi = create_phi_node (iter1, body_bb);
13347 edge preheader_edge = find_edge (entry_bb, body_bb);
13348 edge latch_edge = single_succ_edge (latch_bb);
13349 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13350 UNKNOWN_LOCATION);
13351 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13353 /* Generate the new return. */
13354 gsi = gsi_last_bb (new_exit_bb);
13355 if (retval
13356 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13357 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13358 retval = TREE_OPERAND (retval, 0);
13359 else if (retval)
13361 retval = build1 (VIEW_CONVERT_EXPR,
13362 TREE_TYPE (TREE_TYPE (node->decl)),
13363 retval);
13364 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13365 false, GSI_CONTINUE_LINKING);
13367 g = gimple_build_return (retval);
13368 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13370 /* Handle aligned clauses by replacing default defs of the aligned
13371 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13372 lhs. Handle linear by adding PHIs. */
13373 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13374 if (node->simdclone->args[i].alignment
13375 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13376 && (node->simdclone->args[i].alignment
13377 & (node->simdclone->args[i].alignment - 1)) == 0
13378 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13379 == POINTER_TYPE)
13381 unsigned int alignment = node->simdclone->args[i].alignment;
13382 tree orig_arg = node->simdclone->args[i].orig_arg;
13383 tree def = ssa_default_def (cfun, orig_arg);
13384 if (def && !has_zero_uses (def))
13386 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13387 gimple_seq seq = NULL;
13388 bool need_cvt = false;
13389 gcall *call
13390 = gimple_build_call (fn, 2, def, size_int (alignment));
13391 g = call;
13392 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13393 ptr_type_node))
13394 need_cvt = true;
13395 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13396 gimple_call_set_lhs (g, t);
13397 gimple_seq_add_stmt_without_update (&seq, g);
13398 if (need_cvt)
13400 t = make_ssa_name (orig_arg);
13401 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13402 gimple_seq_add_stmt_without_update (&seq, g);
13404 gsi_insert_seq_on_edge_immediate
13405 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13407 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13408 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13409 entry_bb);
13410 node->create_edge (cgraph_node::get_create (fn),
13411 call, entry_bb->count, freq);
13413 imm_use_iterator iter;
13414 use_operand_p use_p;
13415 gimple use_stmt;
13416 tree repl = gimple_get_lhs (g);
13417 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13418 if (is_gimple_debug (use_stmt) || use_stmt == call)
13419 continue;
13420 else
13421 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13422 SET_USE (use_p, repl);
13425 else if (node->simdclone->args[i].arg_type
13426 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13428 tree orig_arg = node->simdclone->args[i].orig_arg;
13429 tree def = ssa_default_def (cfun, orig_arg);
13430 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13431 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13432 if (def && !has_zero_uses (def))
13434 iter1 = make_ssa_name (orig_arg);
13435 iter2 = make_ssa_name (orig_arg);
13436 phi = create_phi_node (iter1, body_bb);
13437 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13438 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13439 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13440 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13441 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13442 ? TREE_TYPE (orig_arg) : sizetype;
13443 tree addcst
13444 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13445 g = gimple_build_assign (iter2, code, iter1, addcst);
13446 gsi = gsi_last_bb (incr_bb);
13447 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13449 imm_use_iterator iter;
13450 use_operand_p use_p;
13451 gimple use_stmt;
13452 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13453 if (use_stmt == phi)
13454 continue;
13455 else
13456 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13457 SET_USE (use_p, iter1);
13461 calculate_dominance_info (CDI_DOMINATORS);
13462 add_loop (loop, loop->header->loop_father);
13463 update_ssa (TODO_update_ssa);
13465 pop_cfun ();
13468 /* If the function in NODE is tagged as an elemental SIMD function,
13469 create the appropriate SIMD clones. */
13471 static void
13472 expand_simd_clones (struct cgraph_node *node)
13474 tree attr = lookup_attribute ("omp declare simd",
13475 DECL_ATTRIBUTES (node->decl));
13476 if (attr == NULL_TREE
13477 || node->global.inlined_to
13478 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13479 return;
13481 /* Ignore
13482 #pragma omp declare simd
13483 extern int foo ();
13484 in C, there we don't know the argument types at all. */
13485 if (!node->definition
13486 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13487 return;
13491 /* Start with parsing the "omp declare simd" attribute(s). */
13492 bool inbranch_clause_specified;
13493 struct cgraph_simd_clone *clone_info
13494 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13495 &inbranch_clause_specified);
13496 if (clone_info == NULL)
13497 continue;
13499 int orig_simdlen = clone_info->simdlen;
13500 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13501 /* The target can return 0 (no simd clones should be created),
13502 1 (just one ISA of simd clones should be created) or higher
13503 count of ISA variants. In that case, clone_info is initialized
13504 for the first ISA variant. */
13505 int count
13506 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13507 base_type, 0);
13508 if (count == 0)
13509 continue;
13511 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13512 also create one inbranch and one !inbranch clone of it. */
13513 for (int i = 0; i < count * 2; i++)
13515 struct cgraph_simd_clone *clone = clone_info;
13516 if (inbranch_clause_specified && (i & 1) != 0)
13517 continue;
13519 if (i != 0)
13521 clone = simd_clone_struct_alloc (clone_info->nargs
13522 + ((i & 1) != 0));
13523 simd_clone_struct_copy (clone, clone_info);
13524 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13525 and simd_clone_adjust_argument_types did to the first
13526 clone's info. */
13527 clone->nargs -= clone_info->inbranch;
13528 clone->simdlen = orig_simdlen;
13529 /* And call the target hook again to get the right ISA. */
13530 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13531 base_type,
13532 i / 2);
13533 if ((i & 1) != 0)
13534 clone->inbranch = 1;
13537 /* simd_clone_mangle might fail if such a clone has been created
13538 already. */
13539 tree id = simd_clone_mangle (node, clone);
13540 if (id == NULL_TREE)
13541 continue;
13543 /* Only when we are sure we want to create the clone actually
13544 clone the function (or definitions) or create another
13545 extern FUNCTION_DECL (for prototypes without definitions). */
13546 struct cgraph_node *n = simd_clone_create (node);
13547 if (n == NULL)
13548 continue;
13550 n->simdclone = clone;
13551 clone->origin = node;
13552 clone->next_clone = NULL;
13553 if (node->simd_clones == NULL)
13555 clone->prev_clone = n;
13556 node->simd_clones = n;
13558 else
13560 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13561 clone->prev_clone->simdclone->next_clone = n;
13562 node->simd_clones->simdclone->prev_clone = n;
13564 symtab->change_decl_assembler_name (n->decl, id);
13565 /* And finally adjust the return type, parameters and for
13566 definitions also function body. */
13567 if (node->definition)
13568 simd_clone_adjust (n);
13569 else
13571 simd_clone_adjust_return_type (n);
13572 simd_clone_adjust_argument_types (n);
13576 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13579 /* Entry point for IPA simd clone creation pass. */
13581 static unsigned int
13582 ipa_omp_simd_clone (void)
13584 struct cgraph_node *node;
13585 FOR_EACH_FUNCTION (node)
13586 expand_simd_clones (node);
13587 return 0;
13590 namespace {
13592 const pass_data pass_data_omp_simd_clone =
13594 SIMPLE_IPA_PASS, /* type */
13595 "simdclone", /* name */
13596 OPTGROUP_NONE, /* optinfo_flags */
13597 TV_NONE, /* tv_id */
13598 ( PROP_ssa | PROP_cfg ), /* properties_required */
13599 0, /* properties_provided */
13600 0, /* properties_destroyed */
13601 0, /* todo_flags_start */
13602 0, /* todo_flags_finish */
13605 class pass_omp_simd_clone : public simple_ipa_opt_pass
13607 public:
13608 pass_omp_simd_clone(gcc::context *ctxt)
13609 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13612 /* opt_pass methods: */
13613 virtual bool gate (function *);
13614 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13617 bool
13618 pass_omp_simd_clone::gate (function *)
13620 return ((flag_openmp || flag_openmp_simd
13621 || flag_cilkplus
13622 || (in_lto_p && !flag_wpa))
13623 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13626 } // anon namespace
13628 simple_ipa_opt_pass *
13629 make_pass_omp_simd_clone (gcc::context *ctxt)
13631 return new pass_omp_simd_clone (ctxt);
13634 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13635 adds their addresses and sizes to constructor-vector V_CTOR. */
13636 static void
13637 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13638 vec<constructor_elt, va_gc> *v_ctor)
13640 unsigned len = vec_safe_length (v_decls);
13641 for (unsigned i = 0; i < len; i++)
13643 tree it = (*v_decls)[i];
13644 bool is_function = TREE_CODE (it) != VAR_DECL;
13646 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13647 if (!is_function)
13648 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13649 fold_convert (const_ptr_type_node,
13650 DECL_SIZE_UNIT (it)));
13654 /* Create new symbols containing (address, size) pairs for global variables,
13655 marked with "omp declare target" attribute, as well as addresses for the
13656 functions, which are outlined offloading regions. */
13657 void
13658 omp_finish_file (void)
13660 unsigned num_funcs = vec_safe_length (offload_funcs);
13661 unsigned num_vars = vec_safe_length (offload_vars);
13663 if (num_funcs == 0 && num_vars == 0)
13664 return;
13666 if (targetm_common.have_named_sections)
13668 vec<constructor_elt, va_gc> *v_f, *v_v;
13669 vec_alloc (v_f, num_funcs);
13670 vec_alloc (v_v, num_vars * 2);
13672 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13673 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13675 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13676 num_vars * 2);
13677 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13678 num_funcs);
13679 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13680 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13681 tree ctor_v = build_constructor (vars_decl_type, v_v);
13682 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13683 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13684 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13685 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13686 get_identifier (".offload_func_table"),
13687 funcs_decl_type);
13688 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13689 get_identifier (".offload_var_table"),
13690 vars_decl_type);
13691 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13692 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13693 otherwise a joint table in a binary will contain padding between
13694 tables from multiple object files. */
13695 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13696 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13697 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13698 DECL_INITIAL (funcs_decl) = ctor_f;
13699 DECL_INITIAL (vars_decl) = ctor_v;
13700 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13701 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13703 varpool_node::finalize_decl (vars_decl);
13704 varpool_node::finalize_decl (funcs_decl);
13706 else
13708 for (unsigned i = 0; i < num_funcs; i++)
13710 tree it = (*offload_funcs)[i];
13711 targetm.record_offload_symbol (it);
13713 for (unsigned i = 0; i < num_vars; i++)
13715 tree it = (*offload_vars)[i];
13716 targetm.record_offload_symbol (it);
13721 #include "gt-omp-low.h"