svn merge -r 217500:218679 svn+ssh://gcc.gnu.org/svn/gcc/trunk
[official-gcc.git] / gcc / omp-low.c
bloba1fbccfed8cc2dc8ebbc7c381a43b5d2ae82a875
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005-2014 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "stringpool.h"
30 #include "stor-layout.h"
31 #include "rtl.h"
32 #include "predict.h"
33 #include "vec.h"
34 #include "hashtab.h"
35 #include "hash-set.h"
36 #include "machmode.h"
37 #include "hard-reg-set.h"
38 #include "input.h"
39 #include "function.h"
40 #include "dominance.h"
41 #include "cfg.h"
42 #include "cfganal.h"
43 #include "basic-block.h"
44 #include "tree-ssa-alias.h"
45 #include "internal-fn.h"
46 #include "gimple-fold.h"
47 #include "gimple-expr.h"
48 #include "is-a.h"
49 #include "gimple.h"
50 #include "gimplify.h"
51 #include "gimple-iterator.h"
52 #include "gimplify-me.h"
53 #include "gimple-walk.h"
54 #include "tree-iterator.h"
55 #include "tree-inline.h"
56 #include "langhooks.h"
57 #include "diagnostic-core.h"
58 #include "gimple-ssa.h"
59 #include "hash-map.h"
60 #include "plugin-api.h"
61 #include "ipa-ref.h"
62 #include "cgraph.h"
63 #include "tree-cfg.h"
64 #include "tree-phinodes.h"
65 #include "ssa-iterators.h"
66 #include "tree-ssanames.h"
67 #include "tree-into-ssa.h"
68 #include "expr.h"
69 #include "tree-dfa.h"
70 #include "tree-ssa.h"
71 #include "flags.h"
72 #include "expr.h"
73 #include "tree-pass.h"
74 #include "except.h"
75 #include "splay-tree.h"
76 #include "insn-codes.h"
77 #include "optabs.h"
78 #include "cfgloop.h"
79 #include "target.h"
80 #include "common/common-target.h"
81 #include "omp-low.h"
82 #include "gimple-low.h"
83 #include "tree-cfgcleanup.h"
84 #include "pretty-print.h"
85 #include "alloc-pool.h"
86 #include "ipa-prop.h"
87 #include "tree-nested.h"
88 #include "tree-eh.h"
89 #include "cilk.h"
90 #include "context.h"
91 #include "lto-section-names.h"
94 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
95 phases. The first phase scans the function looking for OMP statements
96 and then for variables that must be replaced to satisfy data sharing
97 clauses. The second phase expands code for the constructs, as well as
98 re-gimplifying things when variables have been replaced with complex
99 expressions.
101 Final code generation is done by pass_expand_omp. The flowgraph is
102 scanned for parallel regions which are then moved to a new
103 function, to be invoked by the thread library. */
105 /* Parallel region information. Every parallel and workshare
106 directive is enclosed between two markers, the OMP_* directive
107 and a corresponding OMP_RETURN statement. */
109 struct omp_region
111 /* The enclosing region. */
112 struct omp_region *outer;
114 /* First child region. */
115 struct omp_region *inner;
117 /* Next peer region. */
118 struct omp_region *next;
120 /* Block containing the omp directive as its last stmt. */
121 basic_block entry;
123 /* Block containing the OMP_RETURN as its last stmt. */
124 basic_block exit;
126 /* Block containing the OMP_CONTINUE as its last stmt. */
127 basic_block cont;
129 /* If this is a combined parallel+workshare region, this is a list
130 of additional arguments needed by the combined parallel+workshare
131 library call. */
132 vec<tree, va_gc> *ws_args;
134 /* The code for the omp directive of this region. */
135 enum gimple_code type;
137 /* Schedule kind, only used for OMP_FOR type regions. */
138 enum omp_clause_schedule_kind sched_kind;
140 /* True if this is a combined parallel+workshare region. */
141 bool is_combined_parallel;
144 /* Context structure. Used to store information about each parallel
145 directive in the code. */
147 typedef struct omp_context
149 /* This field must be at the beginning, as we do "inheritance": Some
150 callback functions for tree-inline.c (e.g., omp_copy_decl)
151 receive a copy_body_data pointer that is up-casted to an
152 omp_context pointer. */
153 copy_body_data cb;
155 /* The tree of contexts corresponding to the encountered constructs. */
156 struct omp_context *outer;
157 gimple stmt;
159 /* Map variables to fields in a structure that allows communication
160 between sending and receiving threads. */
161 splay_tree field_map;
162 tree record_type;
163 tree sender_decl;
164 tree receiver_decl;
166 /* These are used just by task contexts, if task firstprivate fn is
167 needed. srecord_type is used to communicate from the thread
168 that encountered the task construct to task firstprivate fn,
169 record_type is allocated by GOMP_task, initialized by task firstprivate
170 fn and passed to the task body fn. */
171 splay_tree sfield_map;
172 tree srecord_type;
174 /* A chain of variables to add to the top-level block surrounding the
175 construct. In the case of a parallel, this is in the child function. */
176 tree block_vars;
178 /* A map of reduction pointer variables. For accelerators, each
179 reduction variable is replaced with an array. Each thread, in turn,
180 is assigned to a slot on that array. */
181 splay_tree reduction_map;
183 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
184 barriers should jump to during omplower pass. */
185 tree cancel_label;
187 /* What to do with variables with implicitly determined sharing
188 attributes. */
189 enum omp_clause_default_kind default_kind;
191 /* Nesting depth of this context. Used to beautify error messages re
192 invalid gotos. The outermost ctx is depth 1, with depth 0 being
193 reserved for the main body of the function. */
194 int depth;
196 /* True if this parallel directive is nested within another. */
197 bool is_nested;
199 /* True if this construct can be cancelled. */
200 bool cancellable;
201 } omp_context;
203 /* A structure holding the elements of:
204 for (V = N1; V cond N2; V += STEP) [...] */
206 struct omp_for_data_loop
208 tree v, n1, n2, step;
209 enum tree_code cond_code;
212 /* A structure describing the main elements of a parallel loop. */
214 struct omp_for_data
216 struct omp_for_data_loop loop;
217 tree chunk_size;
218 gomp_for *for_stmt;
219 tree pre, iter_type;
220 int collapse;
221 bool have_nowait, have_ordered;
222 enum omp_clause_schedule_kind sched_kind;
223 struct omp_for_data_loop *loops;
227 static splay_tree all_contexts;
228 static int taskreg_nesting_level;
229 static int target_nesting_level;
230 static struct omp_region *root_omp_region;
231 static bitmap task_shared_vars;
232 static vec<omp_context *> taskreg_contexts;
234 static void scan_omp (gimple_seq *, omp_context *);
235 static tree scan_omp_1_op (tree *, int *, void *);
237 #define WALK_SUBSTMTS \
238 case GIMPLE_BIND: \
239 case GIMPLE_TRY: \
240 case GIMPLE_CATCH: \
241 case GIMPLE_EH_FILTER: \
242 case GIMPLE_TRANSACTION: \
243 /* The sub-statements for these should be walked. */ \
244 *handled_ops_p = false; \
245 break;
247 /* Helper function to get the name of the array containing the partial
248 reductions for OpenACC reductions. */
249 static const char *
250 oacc_get_reduction_array_id (tree node)
252 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
253 int len = strlen ("OACC") + strlen (id);
254 char *temp_name = XALLOCAVEC (char, len + 1);
255 snprintf (temp_name, len + 1, "OACC%s", id);
256 return IDENTIFIER_POINTER (get_identifier (temp_name));
259 /* Determine the number of threads OpenACC threads used to determine the
260 size of the array of partial reductions. Currently, this is num_gangs
261 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
262 because it is independed of the device used. */
264 static tree
265 oacc_max_threads (omp_context *ctx)
267 tree nthreads, vector_length, gangs, clauses;
269 gangs = fold_convert (sizetype, integer_one_node);
270 vector_length = gangs;
272 /* The reduction clause may be nested inside a loop directive.
273 Scan for the innermost vector_length clause. */
274 for (omp_context *oc = ctx; oc; oc = oc->outer)
276 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
277 || (gimple_omp_target_kind (oc->stmt)
278 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
279 continue;
281 clauses = gimple_omp_target_clauses (oc->stmt);
283 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
284 if (vector_length)
285 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
286 sizetype,
287 OMP_CLAUSE_VECTOR_LENGTH_EXPR
288 (vector_length));
289 else
290 vector_length = fold_convert (sizetype, integer_one_node);
292 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
293 if (gangs)
294 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
295 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
296 else
297 gangs = fold_convert (sizetype, integer_one_node);
299 break;
302 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
304 return nthreads;
307 /* Holds offload tables with decls. */
308 vec<tree, va_gc> *offload_funcs, *offload_vars;
310 /* Holds a decl for __OFFLOAD_TABLE__. */
311 static GTY(()) tree offload_symbol_decl;
313 /* Get the __OFFLOAD_TABLE__ symbol. */
314 static tree
315 get_offload_symbol_decl (void)
317 if (!offload_symbol_decl)
319 tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
320 get_identifier ("__OFFLOAD_TABLE__"),
321 ptr_type_node);
322 TREE_ADDRESSABLE (decl) = 1;
323 TREE_PUBLIC (decl) = 1;
324 DECL_EXTERNAL (decl) = 1;
325 DECL_WEAK (decl) = 1;
326 DECL_ATTRIBUTES (decl)
327 = tree_cons (get_identifier ("weak"),
328 NULL_TREE, DECL_ATTRIBUTES (decl));
329 offload_symbol_decl = decl;
331 return offload_symbol_decl;
334 /* Convenience function for calling scan_omp_1_op on tree operands. */
336 static inline tree
337 scan_omp_op (tree *tp, omp_context *ctx)
339 struct walk_stmt_info wi;
341 memset (&wi, 0, sizeof (wi));
342 wi.info = ctx;
343 wi.want_locations = true;
345 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
348 static void lower_omp (gimple_seq *, omp_context *);
349 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
350 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
352 /* Find an OpenMP clause of type KIND within CLAUSES. */
354 tree
355 find_omp_clause (tree clauses, enum omp_clause_code kind)
357 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
358 if (OMP_CLAUSE_CODE (clauses) == kind)
359 return clauses;
361 return NULL_TREE;
364 /* Return true if CTX is for an omp parallel. */
366 static inline bool
367 is_parallel_ctx (omp_context *ctx)
369 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
373 /* Return true if CTX is for an omp task. */
375 static inline bool
376 is_task_ctx (omp_context *ctx)
378 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
382 /* Return true if CTX is for an omp parallel or omp task. */
384 static inline bool
385 is_taskreg_ctx (omp_context *ctx)
387 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
388 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
392 /* Return true if REGION is a combined parallel+workshare region. */
394 static inline bool
395 is_combined_parallel (struct omp_region *region)
397 return region->is_combined_parallel;
401 /* Extract the header elements of parallel loop FOR_STMT and store
402 them into *FD. */
404 static void
405 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
406 struct omp_for_data_loop *loops)
408 tree t, var, *collapse_iter, *collapse_count;
409 tree count = NULL_TREE, iter_type = long_integer_type_node;
410 struct omp_for_data_loop *loop;
411 int i;
412 struct omp_for_data_loop dummy_loop;
413 location_t loc = gimple_location (for_stmt);
414 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
415 bool distribute = gimple_omp_for_kind (for_stmt)
416 == GF_OMP_FOR_KIND_DISTRIBUTE;
418 fd->for_stmt = for_stmt;
419 fd->pre = NULL;
420 fd->collapse = gimple_omp_for_collapse (for_stmt);
421 if (fd->collapse > 1)
422 fd->loops = loops;
423 else
424 fd->loops = &fd->loop;
426 fd->have_nowait = (gimple_omp_for_kind (for_stmt) != GF_OMP_FOR_KIND_FOR);
427 fd->have_ordered = false;
428 fd->sched_kind = /* TODO: OACC_LOOP */ OMP_CLAUSE_SCHEDULE_STATIC;
429 fd->chunk_size = NULL_TREE;
430 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
431 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
432 collapse_iter = NULL;
433 collapse_count = NULL;
435 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
436 switch (OMP_CLAUSE_CODE (t))
438 case OMP_CLAUSE_NOWAIT:
439 fd->have_nowait = true;
440 break;
441 case OMP_CLAUSE_ORDERED:
442 fd->have_ordered = true;
443 break;
444 case OMP_CLAUSE_SCHEDULE:
445 gcc_assert (!distribute);
446 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
447 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
448 break;
449 case OMP_CLAUSE_DIST_SCHEDULE:
450 gcc_assert (distribute);
451 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
452 break;
453 case OMP_CLAUSE_COLLAPSE:
454 if (fd->collapse > 1)
456 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
457 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
459 break;
460 default:
461 break;
464 /* FIXME: for now map schedule(auto) to schedule(static).
465 There should be analysis to determine whether all iterations
466 are approximately the same amount of work (then schedule(static)
467 is best) or if it varies (then schedule(dynamic,N) is better). */
468 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
470 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
471 gcc_assert (fd->chunk_size == NULL);
473 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
474 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
475 gcc_assert (fd->chunk_size == NULL);
476 else if (fd->chunk_size == NULL)
478 /* We only need to compute a default chunk size for ordered
479 static loops and dynamic loops. */
480 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
481 || fd->have_ordered)
482 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
483 ? integer_zero_node : integer_one_node;
486 for (i = 0; i < fd->collapse; i++)
488 if (fd->collapse == 1)
489 loop = &fd->loop;
490 else if (loops != NULL)
491 loop = loops + i;
492 else
493 loop = &dummy_loop;
495 loop->v = gimple_omp_for_index (for_stmt, i);
496 gcc_assert (SSA_VAR_P (loop->v));
497 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
498 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
499 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
500 loop->n1 = gimple_omp_for_initial (for_stmt, i);
502 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
503 loop->n2 = gimple_omp_for_final (for_stmt, i);
504 switch (loop->cond_code)
506 case LT_EXPR:
507 case GT_EXPR:
508 break;
509 case NE_EXPR:
510 gcc_assert (gimple_omp_for_kind (for_stmt)
511 == GF_OMP_FOR_KIND_CILKSIMD
512 || (gimple_omp_for_kind (for_stmt)
513 == GF_OMP_FOR_KIND_CILKFOR));
514 break;
515 case LE_EXPR:
516 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
517 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
518 else
519 loop->n2 = fold_build2_loc (loc,
520 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
521 build_int_cst (TREE_TYPE (loop->n2), 1));
522 loop->cond_code = LT_EXPR;
523 break;
524 case GE_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 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
530 build_int_cst (TREE_TYPE (loop->n2), 1));
531 loop->cond_code = GT_EXPR;
532 break;
533 default:
534 gcc_unreachable ();
537 t = gimple_omp_for_incr (for_stmt, i);
538 gcc_assert (TREE_OPERAND (t, 0) == var);
539 switch (TREE_CODE (t))
541 case PLUS_EXPR:
542 loop->step = TREE_OPERAND (t, 1);
543 break;
544 case POINTER_PLUS_EXPR:
545 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
546 break;
547 case MINUS_EXPR:
548 loop->step = TREE_OPERAND (t, 1);
549 loop->step = fold_build1_loc (loc,
550 NEGATE_EXPR, TREE_TYPE (loop->step),
551 loop->step);
552 break;
553 default:
554 gcc_unreachable ();
557 if (simd
558 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
559 && !fd->have_ordered))
561 if (fd->collapse == 1)
562 iter_type = TREE_TYPE (loop->v);
563 else if (i == 0
564 || TYPE_PRECISION (iter_type)
565 < TYPE_PRECISION (TREE_TYPE (loop->v)))
566 iter_type
567 = build_nonstandard_integer_type
568 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
570 else if (iter_type != long_long_unsigned_type_node)
572 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
573 iter_type = long_long_unsigned_type_node;
574 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
575 && TYPE_PRECISION (TREE_TYPE (loop->v))
576 >= TYPE_PRECISION (iter_type))
578 tree n;
580 if (loop->cond_code == LT_EXPR)
581 n = fold_build2_loc (loc,
582 PLUS_EXPR, TREE_TYPE (loop->v),
583 loop->n2, loop->step);
584 else
585 n = loop->n1;
586 if (TREE_CODE (n) != INTEGER_CST
587 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
588 iter_type = long_long_unsigned_type_node;
590 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
591 > TYPE_PRECISION (iter_type))
593 tree n1, n2;
595 if (loop->cond_code == LT_EXPR)
597 n1 = loop->n1;
598 n2 = fold_build2_loc (loc,
599 PLUS_EXPR, TREE_TYPE (loop->v),
600 loop->n2, loop->step);
602 else
604 n1 = fold_build2_loc (loc,
605 MINUS_EXPR, TREE_TYPE (loop->v),
606 loop->n2, loop->step);
607 n2 = loop->n1;
609 if (TREE_CODE (n1) != INTEGER_CST
610 || TREE_CODE (n2) != INTEGER_CST
611 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
612 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
613 iter_type = long_long_unsigned_type_node;
617 if (collapse_count && *collapse_count == NULL)
619 t = fold_binary (loop->cond_code, boolean_type_node,
620 fold_convert (TREE_TYPE (loop->v), loop->n1),
621 fold_convert (TREE_TYPE (loop->v), loop->n2));
622 if (t && integer_zerop (t))
623 count = build_zero_cst (long_long_unsigned_type_node);
624 else if ((i == 0 || count != NULL_TREE)
625 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
626 && TREE_CONSTANT (loop->n1)
627 && TREE_CONSTANT (loop->n2)
628 && TREE_CODE (loop->step) == INTEGER_CST)
630 tree itype = TREE_TYPE (loop->v);
632 if (POINTER_TYPE_P (itype))
633 itype = signed_type_for (itype);
634 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
635 t = fold_build2_loc (loc,
636 PLUS_EXPR, itype,
637 fold_convert_loc (loc, itype, loop->step), t);
638 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
639 fold_convert_loc (loc, itype, loop->n2));
640 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
641 fold_convert_loc (loc, itype, loop->n1));
642 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
643 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
644 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
645 fold_build1_loc (loc, NEGATE_EXPR, itype,
646 fold_convert_loc (loc, itype,
647 loop->step)));
648 else
649 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
650 fold_convert_loc (loc, itype, loop->step));
651 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
652 if (count != NULL_TREE)
653 count = fold_build2_loc (loc,
654 MULT_EXPR, long_long_unsigned_type_node,
655 count, t);
656 else
657 count = t;
658 if (TREE_CODE (count) != INTEGER_CST)
659 count = NULL_TREE;
661 else if (count && !integer_zerop (count))
662 count = NULL_TREE;
666 if (count
667 && !simd
668 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
669 || fd->have_ordered))
671 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
672 iter_type = long_long_unsigned_type_node;
673 else
674 iter_type = long_integer_type_node;
676 else if (collapse_iter && *collapse_iter != NULL)
677 iter_type = TREE_TYPE (*collapse_iter);
678 fd->iter_type = iter_type;
679 if (collapse_iter && *collapse_iter == NULL)
680 *collapse_iter = create_tmp_var (iter_type, ".iter");
681 if (collapse_count && *collapse_count == NULL)
683 if (count)
684 *collapse_count = fold_convert_loc (loc, iter_type, count);
685 else
686 *collapse_count = create_tmp_var (iter_type, ".count");
689 if (fd->collapse > 1)
691 fd->loop.v = *collapse_iter;
692 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
693 fd->loop.n2 = *collapse_count;
694 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
695 fd->loop.cond_code = LT_EXPR;
698 //TODO
699 /* For OpenACC loops, force a chunk size of one, as this avoids the default
700 scheduling where several subsequent iterations are being executed by the
701 same thread. */
702 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
704 gcc_assert (fd->chunk_size == NULL_TREE);
705 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
710 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
711 is the immediate dominator of PAR_ENTRY_BB, return true if there
712 are no data dependencies that would prevent expanding the parallel
713 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
715 When expanding a combined parallel+workshare region, the call to
716 the child function may need additional arguments in the case of
717 GIMPLE_OMP_FOR regions. In some cases, these arguments are
718 computed out of variables passed in from the parent to the child
719 via 'struct .omp_data_s'. For instance:
721 #pragma omp parallel for schedule (guided, i * 4)
722 for (j ...)
724 Is lowered into:
726 # BLOCK 2 (PAR_ENTRY_BB)
727 .omp_data_o.i = i;
728 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
730 # BLOCK 3 (WS_ENTRY_BB)
731 .omp_data_i = &.omp_data_o;
732 D.1667 = .omp_data_i->i;
733 D.1598 = D.1667 * 4;
734 #pragma omp for schedule (guided, D.1598)
736 When we outline the parallel region, the call to the child function
737 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
738 that value is computed *after* the call site. So, in principle we
739 cannot do the transformation.
741 To see whether the code in WS_ENTRY_BB blocks the combined
742 parallel+workshare call, we collect all the variables used in the
743 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
744 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
745 call.
747 FIXME. If we had the SSA form built at this point, we could merely
748 hoist the code in block 3 into block 2 and be done with it. But at
749 this point we don't have dataflow information and though we could
750 hack something up here, it is really not worth the aggravation. */
752 static bool
753 workshare_safe_to_combine_p (basic_block ws_entry_bb)
755 struct omp_for_data fd;
756 gimple ws_stmt = last_stmt (ws_entry_bb);
758 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
759 return true;
761 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
763 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
765 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
766 return false;
767 if (fd.iter_type != long_integer_type_node)
768 return false;
770 /* FIXME. We give up too easily here. If any of these arguments
771 are not constants, they will likely involve variables that have
772 been mapped into fields of .omp_data_s for sharing with the child
773 function. With appropriate data flow, it would be possible to
774 see through this. */
775 if (!is_gimple_min_invariant (fd.loop.n1)
776 || !is_gimple_min_invariant (fd.loop.n2)
777 || !is_gimple_min_invariant (fd.loop.step)
778 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
779 return false;
781 return true;
785 /* Collect additional arguments needed to emit a combined
786 parallel+workshare call. WS_STMT is the workshare directive being
787 expanded. */
789 static vec<tree, va_gc> *
790 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
792 tree t;
793 location_t loc = gimple_location (ws_stmt);
794 vec<tree, va_gc> *ws_args;
796 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
798 struct omp_for_data fd;
799 tree n1, n2;
801 extract_omp_for_data (for_stmt, &fd, NULL);
802 n1 = fd.loop.n1;
803 n2 = fd.loop.n2;
805 if (gimple_omp_for_combined_into_p (for_stmt))
807 tree innerc
808 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
809 OMP_CLAUSE__LOOPTEMP_);
810 gcc_assert (innerc);
811 n1 = OMP_CLAUSE_DECL (innerc);
812 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
813 OMP_CLAUSE__LOOPTEMP_);
814 gcc_assert (innerc);
815 n2 = OMP_CLAUSE_DECL (innerc);
818 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
820 t = fold_convert_loc (loc, long_integer_type_node, n1);
821 ws_args->quick_push (t);
823 t = fold_convert_loc (loc, long_integer_type_node, n2);
824 ws_args->quick_push (t);
826 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
827 ws_args->quick_push (t);
829 if (fd.chunk_size)
831 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
832 ws_args->quick_push (t);
835 return ws_args;
837 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
839 /* Number of sections is equal to the number of edges from the
840 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
841 the exit of the sections region. */
842 basic_block bb = single_succ (gimple_bb (ws_stmt));
843 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
844 vec_alloc (ws_args, 1);
845 ws_args->quick_push (t);
846 return ws_args;
849 gcc_unreachable ();
853 /* Discover whether REGION is a combined parallel+workshare region. */
855 static void
856 determine_parallel_type (struct omp_region *region)
858 basic_block par_entry_bb, par_exit_bb;
859 basic_block ws_entry_bb, ws_exit_bb;
861 if (region == NULL || region->inner == NULL
862 || region->exit == NULL || region->inner->exit == NULL
863 || region->inner->cont == NULL)
864 return;
866 /* We only support parallel+for and parallel+sections. */
867 if (region->type != GIMPLE_OMP_PARALLEL
868 || (region->inner->type != GIMPLE_OMP_FOR
869 && region->inner->type != GIMPLE_OMP_SECTIONS))
870 return;
872 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
873 WS_EXIT_BB -> PAR_EXIT_BB. */
874 par_entry_bb = region->entry;
875 par_exit_bb = region->exit;
876 ws_entry_bb = region->inner->entry;
877 ws_exit_bb = region->inner->exit;
879 if (single_succ (par_entry_bb) == ws_entry_bb
880 && single_succ (ws_exit_bb) == par_exit_bb
881 && workshare_safe_to_combine_p (ws_entry_bb)
882 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
883 || (last_and_only_stmt (ws_entry_bb)
884 && last_and_only_stmt (par_exit_bb))))
886 gimple par_stmt = last_stmt (par_entry_bb);
887 gimple ws_stmt = last_stmt (ws_entry_bb);
889 if (region->inner->type == GIMPLE_OMP_FOR)
891 /* If this is a combined parallel loop, we need to determine
892 whether or not to use the combined library calls. There
893 are two cases where we do not apply the transformation:
894 static loops and any kind of ordered loop. In the first
895 case, we already open code the loop so there is no need
896 to do anything else. In the latter case, the combined
897 parallel loop call would still need extra synchronization
898 to implement ordered semantics, so there would not be any
899 gain in using the combined call. */
900 tree clauses = gimple_omp_for_clauses (ws_stmt);
901 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
902 if (c == NULL
903 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
904 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
906 region->is_combined_parallel = false;
907 region->inner->is_combined_parallel = false;
908 return;
912 region->is_combined_parallel = true;
913 region->inner->is_combined_parallel = true;
914 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
919 /* Return true if EXPR is variable sized. */
921 static inline bool
922 is_variable_sized (const_tree expr)
924 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
927 /* Return true if DECL is a reference type. */
929 static inline bool
930 is_reference (tree decl)
932 return lang_hooks.decls.omp_privatize_by_reference (decl);
935 /* Return the type of a decl. If the decl is reference type,
936 return its base type. */
937 static inline tree
938 get_base_type (tree decl)
940 tree type = TREE_TYPE (decl);
941 if (is_reference (decl))
942 type = TREE_TYPE (type);
943 return type;
946 /* Lookup variables. The "maybe" form
947 allows for the variable form to not have been entered, otherwise we
948 assert that the variable must have been entered. */
950 static inline tree
951 lookup_decl (tree var, omp_context *ctx)
953 tree *n = ctx->cb.decl_map->get (var);
954 return *n;
957 static inline tree
958 maybe_lookup_decl (const_tree var, omp_context *ctx)
960 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
961 return n ? *n : NULL_TREE;
964 static inline tree
965 lookup_field (tree var, omp_context *ctx)
967 splay_tree_node n;
968 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
969 return (tree) n->value;
972 static inline tree
973 lookup_sfield (tree var, omp_context *ctx)
975 splay_tree_node n;
976 n = splay_tree_lookup (ctx->sfield_map
977 ? ctx->sfield_map : ctx->field_map,
978 (splay_tree_key) var);
979 return (tree) n->value;
982 static inline tree
983 maybe_lookup_field (tree var, omp_context *ctx)
985 splay_tree_node n;
986 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
987 return n ? (tree) n->value : NULL_TREE;
990 static inline tree
991 lookup_oacc_reduction (const char *id, omp_context *ctx)
993 gcc_assert (is_gimple_omp_oacc_specifically (ctx->stmt));
995 splay_tree_node n;
996 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
997 return (tree) n->value;
1000 static inline tree
1001 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
1003 splay_tree_node n = NULL;
1004 if (ctx->reduction_map)
1005 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
1006 return n ? (tree) n->value : NULL_TREE;
1009 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1010 the parallel context if DECL is to be shared. */
1012 static bool
1013 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1015 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1016 return true;
1018 /* We can only use copy-in/copy-out semantics for shared variables
1019 when we know the value is not accessible from an outer scope. */
1020 if (shared_ctx)
1022 gcc_assert (!is_gimple_omp_oacc_specifically (shared_ctx->stmt));
1024 /* ??? Trivially accessible from anywhere. But why would we even
1025 be passing an address in this case? Should we simply assert
1026 this to be false, or should we have a cleanup pass that removes
1027 these from the list of mappings? */
1028 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1029 return true;
1031 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1032 without analyzing the expression whether or not its location
1033 is accessible to anyone else. In the case of nested parallel
1034 regions it certainly may be. */
1035 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1036 return true;
1038 /* Do not use copy-in/copy-out for variables that have their
1039 address taken. */
1040 if (TREE_ADDRESSABLE (decl))
1041 return true;
1043 /* lower_send_shared_vars only uses copy-in, but not copy-out
1044 for these. */
1045 if (TREE_READONLY (decl)
1046 || ((TREE_CODE (decl) == RESULT_DECL
1047 || TREE_CODE (decl) == PARM_DECL)
1048 && DECL_BY_REFERENCE (decl)))
1049 return false;
1051 /* Disallow copy-in/out in nested parallel if
1052 decl is shared in outer parallel, otherwise
1053 each thread could store the shared variable
1054 in its own copy-in location, making the
1055 variable no longer really shared. */
1056 if (shared_ctx->is_nested)
1058 omp_context *up;
1060 for (up = shared_ctx->outer; up; up = up->outer)
1061 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1062 break;
1064 if (up)
1066 tree c;
1068 for (c = gimple_omp_taskreg_clauses (up->stmt);
1069 c; c = OMP_CLAUSE_CHAIN (c))
1070 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1071 && OMP_CLAUSE_DECL (c) == decl)
1072 break;
1074 if (c)
1075 goto maybe_mark_addressable_and_ret;
1079 /* For tasks avoid using copy-in/out. As tasks can be
1080 deferred or executed in different thread, when GOMP_task
1081 returns, the task hasn't necessarily terminated. */
1082 if (is_task_ctx (shared_ctx))
1084 tree outer;
1085 maybe_mark_addressable_and_ret:
1086 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1087 if (is_gimple_reg (outer))
1089 /* Taking address of OUTER in lower_send_shared_vars
1090 might need regimplification of everything that uses the
1091 variable. */
1092 if (!task_shared_vars)
1093 task_shared_vars = BITMAP_ALLOC (NULL);
1094 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1095 TREE_ADDRESSABLE (outer) = 1;
1097 return true;
1101 return false;
1104 /* Construct a new automatic decl similar to VAR. */
1106 static tree
1107 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1109 tree copy = copy_var_decl (var, name, type);
1111 DECL_CONTEXT (copy) = current_function_decl;
1112 DECL_CHAIN (copy) = ctx->block_vars;
1113 ctx->block_vars = copy;
1115 return copy;
1118 static tree
1119 omp_copy_decl_1 (tree var, omp_context *ctx)
1121 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1124 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1125 as appropriate. */
1126 static tree
1127 omp_build_component_ref (tree obj, tree field)
1129 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1130 if (TREE_THIS_VOLATILE (field))
1131 TREE_THIS_VOLATILE (ret) |= 1;
1132 if (TREE_READONLY (field))
1133 TREE_READONLY (ret) |= 1;
1134 return ret;
1137 /* Build tree nodes to access the field for VAR on the receiver side. */
1139 static tree
1140 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1142 tree x, field = lookup_field (var, ctx);
1144 /* If the receiver record type was remapped in the child function,
1145 remap the field into the new record type. */
1146 x = maybe_lookup_field (field, ctx);
1147 if (x != NULL)
1148 field = x;
1150 x = build_simple_mem_ref (ctx->receiver_decl);
1151 x = omp_build_component_ref (x, field);
1152 if (by_ref)
1153 x = build_simple_mem_ref (x);
1155 return x;
1158 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1159 of a parallel, this is a component reference; for workshare constructs
1160 this is some variable. */
1162 static tree
1163 build_outer_var_ref (tree var, omp_context *ctx)
1165 tree x;
1167 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1168 x = var;
1169 else if (is_variable_sized (var))
1171 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1172 x = build_outer_var_ref (x, ctx);
1173 x = build_simple_mem_ref (x);
1175 else if (is_taskreg_ctx (ctx))
1177 bool by_ref = use_pointer_for_field (var, NULL);
1178 x = build_receiver_ref (var, by_ref, ctx);
1180 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1181 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1183 /* #pragma omp simd isn't a worksharing construct, and can reference even
1184 private vars in its linear etc. clauses. */
1185 x = NULL_TREE;
1186 if (ctx->outer && is_taskreg_ctx (ctx))
1187 x = lookup_decl (var, ctx->outer);
1188 else if (ctx->outer)
1189 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1190 if (x == NULL_TREE)
1191 x = var;
1193 else if (ctx->outer)
1194 x = lookup_decl (var, ctx->outer);
1195 else if (is_reference (var))
1196 /* This can happen with orphaned constructs. If var is reference, it is
1197 possible it is shared and as such valid. */
1198 x = var;
1199 else
1200 gcc_unreachable ();
1202 if (is_reference (var))
1203 x = build_simple_mem_ref (x);
1205 return x;
1208 /* Build tree nodes to access the field for VAR on the sender side. */
1210 static tree
1211 build_sender_ref (tree var, omp_context *ctx)
1213 tree field = lookup_sfield (var, ctx);
1214 return omp_build_component_ref (ctx->sender_decl, field);
1217 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1219 static void
1220 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1222 tree field, type, sfield = NULL_TREE;
1224 gcc_assert ((mask & 1) == 0
1225 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1226 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1227 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1228 gcc_assert ((mask & 3) == 3
1229 || !is_gimple_omp_oacc_specifically (ctx->stmt));
1231 type = TREE_TYPE (var);
1232 if (mask & 4)
1234 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1235 type = build_pointer_type (build_pointer_type (type));
1237 else if (by_ref)
1238 type = build_pointer_type (type);
1239 else if ((mask & 3) == 1 && is_reference (var))
1240 type = TREE_TYPE (type);
1242 field = build_decl (DECL_SOURCE_LOCATION (var),
1243 FIELD_DECL, DECL_NAME (var), type);
1245 /* Remember what variable this field was created for. This does have a
1246 side effect of making dwarf2out ignore this member, so for helpful
1247 debugging we clear it later in delete_omp_context. */
1248 DECL_ABSTRACT_ORIGIN (field) = var;
1249 if (type == TREE_TYPE (var))
1251 DECL_ALIGN (field) = DECL_ALIGN (var);
1252 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1253 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1255 else
1256 DECL_ALIGN (field) = TYPE_ALIGN (type);
1258 if ((mask & 3) == 3)
1260 insert_field_into_struct (ctx->record_type, field);
1261 if (ctx->srecord_type)
1263 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1264 FIELD_DECL, DECL_NAME (var), type);
1265 DECL_ABSTRACT_ORIGIN (sfield) = var;
1266 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1267 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1268 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1269 insert_field_into_struct (ctx->srecord_type, sfield);
1272 else
1274 if (ctx->srecord_type == NULL_TREE)
1276 tree t;
1278 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1279 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1280 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1282 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1283 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1284 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1285 insert_field_into_struct (ctx->srecord_type, sfield);
1286 splay_tree_insert (ctx->sfield_map,
1287 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1288 (splay_tree_value) sfield);
1291 sfield = field;
1292 insert_field_into_struct ((mask & 1) ? ctx->record_type
1293 : ctx->srecord_type, field);
1296 if (mask & 1)
1297 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1298 (splay_tree_value) field);
1299 if ((mask & 2) && ctx->sfield_map)
1300 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1301 (splay_tree_value) sfield);
1304 static tree
1305 install_var_local (tree var, omp_context *ctx)
1307 tree new_var = omp_copy_decl_1 (var, ctx);
1308 insert_decl_map (&ctx->cb, var, new_var);
1309 return new_var;
1312 /* Adjust the replacement for DECL in CTX for the new context. This means
1313 copying the DECL_VALUE_EXPR, and fixing up the type. */
1315 static void
1316 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1318 tree new_decl, size;
1320 new_decl = lookup_decl (decl, ctx);
1322 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1324 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1325 && DECL_HAS_VALUE_EXPR_P (decl))
1327 tree ve = DECL_VALUE_EXPR (decl);
1328 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1329 SET_DECL_VALUE_EXPR (new_decl, ve);
1330 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1333 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1335 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1336 if (size == error_mark_node)
1337 size = TYPE_SIZE (TREE_TYPE (new_decl));
1338 DECL_SIZE (new_decl) = size;
1340 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1341 if (size == error_mark_node)
1342 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1343 DECL_SIZE_UNIT (new_decl) = size;
1347 /* The callback for remap_decl. Search all containing contexts for a
1348 mapping of the variable; this avoids having to duplicate the splay
1349 tree ahead of time. We know a mapping doesn't already exist in the
1350 given context. Create new mappings to implement default semantics. */
1352 static tree
1353 omp_copy_decl (tree var, copy_body_data *cb)
1355 omp_context *ctx = (omp_context *) cb;
1356 tree new_var;
1358 if (TREE_CODE (var) == LABEL_DECL)
1360 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1361 DECL_CONTEXT (new_var) = current_function_decl;
1362 insert_decl_map (&ctx->cb, var, new_var);
1363 return new_var;
1366 while (!is_taskreg_ctx (ctx))
1368 ctx = ctx->outer;
1369 if (ctx == NULL)
1370 return var;
1371 new_var = maybe_lookup_decl (var, ctx);
1372 if (new_var)
1373 return new_var;
1376 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1377 return var;
1379 return error_mark_node;
1383 /* Debugging dumps for parallel regions. */
1384 void dump_omp_region (FILE *, struct omp_region *, int);
1385 void debug_omp_region (struct omp_region *);
1386 void debug_all_omp_regions (void);
1388 /* Dump the parallel region tree rooted at REGION. */
1390 void
1391 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1393 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1394 gimple_code_name[region->type]);
1396 if (region->inner)
1397 dump_omp_region (file, region->inner, indent + 4);
1399 if (region->cont)
1401 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1402 region->cont->index);
1405 if (region->exit)
1406 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1407 region->exit->index);
1408 else
1409 fprintf (file, "%*s[no exit marker]\n", indent, "");
1411 if (region->next)
1412 dump_omp_region (file, region->next, indent);
1415 DEBUG_FUNCTION void
1416 debug_omp_region (struct omp_region *region)
1418 dump_omp_region (stderr, region, 0);
1421 DEBUG_FUNCTION void
1422 debug_all_omp_regions (void)
1424 dump_omp_region (stderr, root_omp_region, 0);
1428 /* Create a new parallel region starting at STMT inside region PARENT. */
1430 static struct omp_region *
1431 new_omp_region (basic_block bb, enum gimple_code type,
1432 struct omp_region *parent)
1434 struct omp_region *region = XCNEW (struct omp_region);
1436 region->outer = parent;
1437 region->entry = bb;
1438 region->type = type;
1440 if (parent)
1442 /* This is a nested region. Add it to the list of inner
1443 regions in PARENT. */
1444 region->next = parent->inner;
1445 parent->inner = region;
1447 else
1449 /* This is a toplevel region. Add it to the list of toplevel
1450 regions in ROOT_OMP_REGION. */
1451 region->next = root_omp_region;
1452 root_omp_region = region;
1455 return region;
1458 /* Release the memory associated with the region tree rooted at REGION. */
1460 static void
1461 free_omp_region_1 (struct omp_region *region)
1463 struct omp_region *i, *n;
1465 for (i = region->inner; i ; i = n)
1467 n = i->next;
1468 free_omp_region_1 (i);
1471 free (region);
1474 /* Release the memory for the entire omp region tree. */
1476 void
1477 free_omp_regions (void)
1479 struct omp_region *r, *n;
1480 for (r = root_omp_region; r ; r = n)
1482 n = r->next;
1483 free_omp_region_1 (r);
1485 root_omp_region = NULL;
1489 /* Create a new context, with OUTER_CTX being the surrounding context. */
1491 static omp_context *
1492 new_omp_context (gimple stmt, omp_context *outer_ctx)
1494 omp_context *ctx = XCNEW (omp_context);
1496 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1497 (splay_tree_value) ctx);
1498 ctx->stmt = stmt;
1500 if (outer_ctx)
1502 ctx->outer = outer_ctx;
1503 ctx->cb = outer_ctx->cb;
1504 ctx->cb.block = NULL;
1505 ctx->depth = outer_ctx->depth + 1;
1506 /* FIXME: handle reductions recursively. */
1507 ctx->reduction_map = outer_ctx->reduction_map;
1509 else
1511 ctx->cb.src_fn = current_function_decl;
1512 ctx->cb.dst_fn = current_function_decl;
1513 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1514 gcc_checking_assert (ctx->cb.src_node);
1515 ctx->cb.dst_node = ctx->cb.src_node;
1516 ctx->cb.src_cfun = cfun;
1517 ctx->cb.copy_decl = omp_copy_decl;
1518 ctx->cb.eh_lp_nr = 0;
1519 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1520 ctx->depth = 1;
1521 //TODO ctx->reduction_map = TODO;
1524 ctx->cb.decl_map = new hash_map<tree, tree>;
1526 return ctx;
1529 static gimple_seq maybe_catch_exception (gimple_seq);
1531 /* Finalize task copyfn. */
1533 static void
1534 finalize_task_copyfn (gomp_task *task_stmt)
1536 struct function *child_cfun;
1537 tree child_fn;
1538 gimple_seq seq = NULL, new_seq;
1539 gbind *bind;
1541 child_fn = gimple_omp_task_copy_fn (task_stmt);
1542 if (child_fn == NULL_TREE)
1543 return;
1545 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1546 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1548 push_cfun (child_cfun);
1549 bind = gimplify_body (child_fn, false);
1550 gimple_seq_add_stmt (&seq, bind);
1551 new_seq = maybe_catch_exception (seq);
1552 if (new_seq != seq)
1554 bind = gimple_build_bind (NULL, new_seq, NULL);
1555 seq = NULL;
1556 gimple_seq_add_stmt (&seq, bind);
1558 gimple_set_body (child_fn, seq);
1559 pop_cfun ();
1561 /* Inform the callgraph about the new function. */
1562 cgraph_node::add_new_function (child_fn, false);
1565 /* Destroy a omp_context data structures. Called through the splay tree
1566 value delete callback. */
1568 static void
1569 delete_omp_context (splay_tree_value value)
1571 omp_context *ctx = (omp_context *) value;
1573 delete ctx->cb.decl_map;
1575 if (ctx->field_map)
1576 splay_tree_delete (ctx->field_map);
1577 if (ctx->sfield_map)
1578 splay_tree_delete (ctx->sfield_map);
1579 if (ctx->reduction_map
1580 /* Shared over several omp_contexts. */
1581 && (ctx->outer == NULL
1582 || ctx->reduction_map != ctx->outer->reduction_map))
1583 splay_tree_delete (ctx->reduction_map);
1585 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1586 it produces corrupt debug information. */
1587 if (ctx->record_type)
1589 tree t;
1590 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1591 DECL_ABSTRACT_ORIGIN (t) = NULL;
1593 if (ctx->srecord_type)
1595 tree t;
1596 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1597 DECL_ABSTRACT_ORIGIN (t) = NULL;
1600 if (is_task_ctx (ctx))
1601 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1603 XDELETE (ctx);
1606 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1607 context. */
1609 static void
1610 fixup_child_record_type (omp_context *ctx)
1612 tree f, type = ctx->record_type;
1614 /* ??? It isn't sufficient to just call remap_type here, because
1615 variably_modified_type_p doesn't work the way we expect for
1616 record types. Testing each field for whether it needs remapping
1617 and creating a new record by hand works, however. */
1618 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1619 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1620 break;
1621 if (f)
1623 tree name, new_fields = NULL;
1625 type = lang_hooks.types.make_type (RECORD_TYPE);
1626 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1627 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1628 TYPE_DECL, name, type);
1629 TYPE_NAME (type) = name;
1631 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1633 tree new_f = copy_node (f);
1634 DECL_CONTEXT (new_f) = type;
1635 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1636 DECL_CHAIN (new_f) = new_fields;
1637 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1638 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1639 &ctx->cb, NULL);
1640 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1641 &ctx->cb, NULL);
1642 new_fields = new_f;
1644 /* Arrange to be able to look up the receiver field
1645 given the sender field. */
1646 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1647 (splay_tree_value) new_f);
1649 TYPE_FIELDS (type) = nreverse (new_fields);
1650 layout_type (type);
1653 TREE_TYPE (ctx->receiver_decl)
1654 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1657 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1658 specified by CLAUSES. */
1660 static void
1661 scan_sharing_clauses (tree clauses, omp_context *ctx)
1663 tree c, decl;
1664 bool scan_array_reductions = false;
1666 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1668 bool by_ref;
1670 switch (OMP_CLAUSE_CODE (c))
1672 case OMP_CLAUSE_PRIVATE:
1673 decl = OMP_CLAUSE_DECL (c);
1674 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1675 goto do_private;
1676 else if (!is_variable_sized (decl))
1677 install_var_local (decl, ctx);
1678 break;
1680 case OMP_CLAUSE_SHARED:
1681 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1682 decl = OMP_CLAUSE_DECL (c);
1683 /* Ignore shared directives in teams construct. */
1684 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1686 /* Global variables don't need to be copied,
1687 the receiver side will use them directly. */
1688 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1689 if (is_global_var (odecl))
1690 break;
1691 insert_decl_map (&ctx->cb, decl, odecl);
1692 break;
1694 gcc_assert (is_taskreg_ctx (ctx));
1695 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1696 || !is_variable_sized (decl));
1697 /* Global variables don't need to be copied,
1698 the receiver side will use them directly. */
1699 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1700 break;
1701 by_ref = use_pointer_for_field (decl, ctx);
1702 if (! TREE_READONLY (decl)
1703 || TREE_ADDRESSABLE (decl)
1704 || by_ref
1705 || is_reference (decl))
1707 install_var_field (decl, by_ref, 3, ctx);
1708 install_var_local (decl, ctx);
1709 break;
1711 /* We don't need to copy const scalar vars back. */
1712 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1713 goto do_private;
1715 case OMP_CLAUSE_LASTPRIVATE:
1716 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1717 /* Let the corresponding firstprivate clause create
1718 the variable. */
1719 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1720 break;
1721 /* FALLTHRU */
1723 case OMP_CLAUSE_FIRSTPRIVATE:
1724 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1726 sorry ("clause not supported yet");
1727 break;
1729 /* FALLTHRU */
1730 case OMP_CLAUSE_LINEAR:
1731 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1732 /* FALLTHRU */
1733 case OMP_CLAUSE_REDUCTION:
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 //TODO
1760 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1762 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1764 /* Create a decl for the reduction array. */
1765 tree var = OMP_CLAUSE_DECL (c);
1766 tree type = get_base_type (var);
1767 tree ptype = build_pointer_type (type);
1768 tree array = create_tmp_var (ptype,
1769 oacc_get_reduction_array_id (var));
1770 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1771 install_var_field (array, true, 3, c);
1772 install_var_local (array, c);
1774 /* Insert it into the current context. */
1775 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1776 oacc_get_reduction_array_id (var),
1777 (splay_tree_value) array);
1778 splay_tree_insert (ctx->reduction_map,
1779 (splay_tree_key) array,
1780 (splay_tree_value) array);
1783 break;
1785 case OMP_CLAUSE__LOOPTEMP_:
1786 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1787 gcc_assert (is_parallel_ctx (ctx));
1788 decl = OMP_CLAUSE_DECL (c);
1789 install_var_field (decl, false, 3, ctx);
1790 install_var_local (decl, ctx);
1791 break;
1793 case OMP_CLAUSE_COPYPRIVATE:
1794 case OMP_CLAUSE_COPYIN:
1795 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1796 decl = OMP_CLAUSE_DECL (c);
1797 by_ref = use_pointer_for_field (decl, NULL);
1798 install_var_field (decl, by_ref, 3, ctx);
1799 break;
1801 case OMP_CLAUSE_DEFAULT:
1802 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1803 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1804 break;
1806 case OMP_CLAUSE_FINAL:
1807 case OMP_CLAUSE_NUM_THREADS:
1808 case OMP_CLAUSE_NUM_TEAMS:
1809 case OMP_CLAUSE_THREAD_LIMIT:
1810 case OMP_CLAUSE_DEVICE:
1811 case OMP_CLAUSE_SCHEDULE:
1812 case OMP_CLAUSE_DIST_SCHEDULE:
1813 case OMP_CLAUSE_DEPEND:
1814 case OMP_CLAUSE__CILK_FOR_COUNT_:
1815 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1816 /* FALLTHRU */
1817 case OMP_CLAUSE_IF:
1818 case OMP_CLAUSE_NUM_GANGS:
1819 case OMP_CLAUSE_NUM_WORKERS:
1820 case OMP_CLAUSE_VECTOR_LENGTH:
1821 if (ctx->outer)
1822 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1823 break;
1825 case OMP_CLAUSE_TO:
1826 case OMP_CLAUSE_FROM:
1827 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1828 /* FALLTHRU */
1829 case OMP_CLAUSE_MAP:
1830 switch (OMP_CLAUSE_CODE (c))
1832 case OMP_CLAUSE_TO:
1833 case OMP_CLAUSE_FROM:
1834 /* The to and from clauses are only ever seen with OpenMP target
1835 update constructs. */
1836 gcc_assert (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1837 && (gimple_omp_target_kind (ctx->stmt)
1838 == GF_OMP_TARGET_KIND_UPDATE));
1839 break;
1840 case OMP_CLAUSE_MAP:
1841 /* The map clause is never seen with OpenMP target update
1842 constructs. */
1843 gcc_assert (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
1844 || (gimple_omp_target_kind (ctx->stmt)
1845 != GF_OMP_TARGET_KIND_UPDATE));
1846 break;
1847 default:
1848 gcc_unreachable ();
1850 if (ctx->outer)
1851 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1852 decl = OMP_CLAUSE_DECL (c);
1853 /* Global variables with "omp declare target" attribute
1854 don't need to be copied, the receiver side will use them
1855 directly. */
1856 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1857 && DECL_P (decl)
1858 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1859 && varpool_node::get_create (decl)->offloadable)
1861 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1862 break;
1864 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1865 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1867 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1868 target regions that are not offloaded; there is nothing to map for
1869 those. */
1870 if (!is_gimple_omp_offloaded (ctx->stmt)
1871 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1872 break;
1874 #if 0
1875 /* In target regions that are not offloaded, libgomp won't pay
1876 attention to OMP_CLAUSE_MAP_FORCE_DEVICEPTR -- but I think we need
1877 to handle it here anyway, in order to create a visible copy of the
1878 variable. */
1879 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1880 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
1882 if (!is_gimple_omp_offloaded (ctx->stmt))
1883 break;
1885 #endif
1886 if (DECL_P (decl))
1888 if (DECL_SIZE (decl)
1889 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1891 tree decl2 = DECL_VALUE_EXPR (decl);
1892 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1893 decl2 = TREE_OPERAND (decl2, 0);
1894 gcc_assert (DECL_P (decl2));
1895 install_var_field (decl2, true, 3, ctx);
1896 install_var_local (decl2, ctx);
1897 install_var_local (decl, ctx);
1899 else
1901 gcc_assert (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
1902 || (OMP_CLAUSE_MAP_KIND (c)
1903 != OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
1904 || TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE);
1905 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1906 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1907 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1908 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1909 install_var_field (decl, true, 7, ctx);
1910 else
1911 install_var_field (decl, true, 3, ctx);
1912 if (is_gimple_omp_offloaded (ctx->stmt))
1913 install_var_local (decl, ctx);
1916 else
1918 tree base = get_base_address (decl);
1919 tree nc = OMP_CLAUSE_CHAIN (c);
1920 if (DECL_P (base)
1921 && nc != NULL_TREE
1922 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1923 && OMP_CLAUSE_DECL (nc) == base
1924 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1925 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1927 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1928 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1930 else
1932 if (ctx->outer)
1934 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1935 decl = OMP_CLAUSE_DECL (c);
1937 gcc_assert (!splay_tree_lookup (ctx->field_map,
1938 (splay_tree_key) decl));
1939 tree field
1940 = build_decl (OMP_CLAUSE_LOCATION (c),
1941 FIELD_DECL, NULL_TREE, ptr_type_node);
1942 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1943 insert_field_into_struct (ctx->record_type, field);
1944 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1945 (splay_tree_value) field);
1948 break;
1950 case OMP_CLAUSE_NOWAIT:
1951 case OMP_CLAUSE_ORDERED:
1952 case OMP_CLAUSE_UNTIED:
1953 case OMP_CLAUSE_MERGEABLE:
1954 case OMP_CLAUSE_PROC_BIND:
1955 case OMP_CLAUSE_SAFELEN:
1956 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1958 sorry ("clause not supported yet");
1959 break;
1961 /* FALLTHRU */
1962 case OMP_CLAUSE_COLLAPSE:
1963 case OMP_CLAUSE_ASYNC:
1964 case OMP_CLAUSE_WAIT:
1965 break;
1967 case OMP_CLAUSE_ALIGNED:
1968 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1969 decl = OMP_CLAUSE_DECL (c);
1970 if (is_global_var (decl)
1971 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1972 install_var_local (decl, ctx);
1973 break;
1975 case OMP_CLAUSE_DEVICE_RESIDENT:
1976 case OMP_CLAUSE_USE_DEVICE:
1977 case OMP_CLAUSE_GANG:
1978 case OMP_CLAUSE__CACHE_:
1979 case OMP_CLAUSE_INDEPENDENT:
1980 case OMP_CLAUSE_WORKER:
1981 case OMP_CLAUSE_VECTOR:
1982 sorry ("Clause not supported yet");
1983 break;
1985 default:
1986 gcc_unreachable ();
1990 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1992 switch (OMP_CLAUSE_CODE (c))
1994 case OMP_CLAUSE_LASTPRIVATE:
1995 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1996 /* Let the corresponding firstprivate clause create
1997 the variable. */
1998 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1999 scan_array_reductions = true;
2000 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2001 break;
2002 /* FALLTHRU */
2004 case OMP_CLAUSE_FIRSTPRIVATE:
2005 if (is_gimple_omp_oacc_specifically (ctx->stmt))
2007 sorry ("clause not supported yet");
2008 break;
2010 /* FALLTHRU */
2011 case OMP_CLAUSE_LINEAR:
2012 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
2013 /* FALLTHRU */
2014 case OMP_CLAUSE_REDUCTION:
2015 case OMP_CLAUSE_PRIVATE:
2016 decl = OMP_CLAUSE_DECL (c);
2017 if (is_variable_sized (decl))
2018 install_var_local (decl, ctx);
2019 fixup_remapped_decl (decl, ctx,
2020 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2021 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2022 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2023 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2024 scan_array_reductions = true;
2025 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2026 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2027 scan_array_reductions = true;
2028 break;
2030 case OMP_CLAUSE_SHARED:
2031 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
2032 /* Ignore shared directives in teams construct. */
2033 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2034 break;
2035 decl = OMP_CLAUSE_DECL (c);
2036 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2037 fixup_remapped_decl (decl, ctx, false);
2038 break;
2040 case OMP_CLAUSE_MAP:
2041 /* The map clause is never seen with OpenMP target update
2042 constructs. */
2043 gcc_assert (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2044 || (gimple_omp_target_kind (ctx->stmt)
2045 != GF_OMP_TARGET_KIND_UPDATE));
2046 if (!is_gimple_omp_offloaded (ctx->stmt))
2047 break;
2048 decl = OMP_CLAUSE_DECL (c);
2049 if (DECL_P (decl)
2050 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2051 && varpool_node::get_create (decl)->offloadable)
2053 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
2054 break;
2056 if (DECL_P (decl))
2058 gcc_assert ((OMP_CLAUSE_MAP_KIND (c)
2059 != OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
2060 || TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE);
2061 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
2062 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2063 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2065 tree new_decl = lookup_decl (decl, ctx);
2066 TREE_TYPE (new_decl)
2067 = remap_type (TREE_TYPE (decl), &ctx->cb);
2069 else if (DECL_SIZE (decl)
2070 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2072 gcc_assert (OMP_CLAUSE_MAP_KIND (c)
2073 != OMP_CLAUSE_MAP_FORCE_DEVICEPTR);
2075 tree decl2 = DECL_VALUE_EXPR (decl);
2076 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2077 decl2 = TREE_OPERAND (decl2, 0);
2078 gcc_assert (DECL_P (decl2));
2079 fixup_remapped_decl (decl2, ctx, false);
2080 fixup_remapped_decl (decl, ctx, true);
2082 else
2083 fixup_remapped_decl (decl, ctx, false);
2085 break;
2087 case OMP_CLAUSE_COPYPRIVATE:
2088 case OMP_CLAUSE_COPYIN:
2089 case OMP_CLAUSE_DEFAULT:
2090 case OMP_CLAUSE_NUM_THREADS:
2091 case OMP_CLAUSE_NUM_TEAMS:
2092 case OMP_CLAUSE_THREAD_LIMIT:
2093 case OMP_CLAUSE_DEVICE:
2094 case OMP_CLAUSE_SCHEDULE:
2095 case OMP_CLAUSE_DIST_SCHEDULE:
2096 case OMP_CLAUSE_NOWAIT:
2097 case OMP_CLAUSE_ORDERED:
2098 case OMP_CLAUSE_UNTIED:
2099 case OMP_CLAUSE_FINAL:
2100 case OMP_CLAUSE_MERGEABLE:
2101 case OMP_CLAUSE_PROC_BIND:
2102 case OMP_CLAUSE_SAFELEN:
2103 case OMP_CLAUSE_ALIGNED:
2104 case OMP_CLAUSE_DEPEND:
2105 case OMP_CLAUSE__LOOPTEMP_:
2106 case OMP_CLAUSE_TO:
2107 case OMP_CLAUSE_FROM:
2108 case OMP_CLAUSE__CILK_FOR_COUNT_:
2109 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
2110 /* FALLTHRU */
2111 case OMP_CLAUSE_ASYNC:
2112 case OMP_CLAUSE_COLLAPSE:
2113 case OMP_CLAUSE_IF:
2114 case OMP_CLAUSE_NUM_GANGS:
2115 case OMP_CLAUSE_NUM_WORKERS:
2116 case OMP_CLAUSE_VECTOR_LENGTH:
2117 case OMP_CLAUSE_WAIT:
2118 break;
2120 case OMP_CLAUSE_DEVICE_RESIDENT:
2121 case OMP_CLAUSE_USE_DEVICE:
2122 case OMP_CLAUSE_GANG:
2123 case OMP_CLAUSE__CACHE_:
2124 case OMP_CLAUSE_INDEPENDENT:
2125 case OMP_CLAUSE_WORKER:
2126 case OMP_CLAUSE_VECTOR:
2127 sorry ("Clause not supported yet");
2128 break;
2130 default:
2131 gcc_unreachable ();
2135 if (scan_array_reductions)
2137 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
2138 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2139 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2140 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2142 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2143 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2145 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2146 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2147 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2148 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2149 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2150 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2154 /* Create a new name for omp child function. Returns an identifier. If
2155 IS_CILK_FOR is true then the suffix for the child function is
2156 "_cilk_for_fn." */
2158 static tree
2159 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2161 if (is_cilk_for)
2162 return clone_function_name (current_function_decl, "_cilk_for_fn");
2163 return clone_function_name (current_function_decl,
2164 task_copy ? "_omp_cpyfn" : "_omp_fn");
2167 /* Returns the type of the induction variable for the child function for
2168 _Cilk_for and the types for _high and _low variables based on TYPE. */
2170 static tree
2171 cilk_for_check_loop_diff_type (tree type)
2173 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2175 if (TYPE_UNSIGNED (type))
2176 return uint32_type_node;
2177 else
2178 return integer_type_node;
2180 else
2182 if (TYPE_UNSIGNED (type))
2183 return uint64_type_node;
2184 else
2185 return long_long_integer_type_node;
2189 /* Build a decl for the omp child function. It'll not contain a body
2190 yet, just the bare decl. */
2192 static void
2193 create_omp_child_function (omp_context *ctx, bool task_copy)
2195 tree decl, type, name, t;
2197 tree cilk_for_count
2198 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2199 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2200 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2201 tree cilk_var_type = NULL_TREE;
2203 name = create_omp_child_function_name (task_copy,
2204 cilk_for_count != NULL_TREE);
2205 if (task_copy)
2206 type = build_function_type_list (void_type_node, ptr_type_node,
2207 ptr_type_node, NULL_TREE);
2208 else if (cilk_for_count)
2210 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2211 cilk_var_type = cilk_for_check_loop_diff_type (type);
2212 type = build_function_type_list (void_type_node, ptr_type_node,
2213 cilk_var_type, cilk_var_type, NULL_TREE);
2215 else
2216 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2218 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2220 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt)
2221 || !task_copy);
2222 if (!task_copy)
2223 ctx->cb.dst_fn = decl;
2224 else
2225 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2227 TREE_STATIC (decl) = 1;
2228 TREE_USED (decl) = 1;
2229 DECL_ARTIFICIAL (decl) = 1;
2230 DECL_IGNORED_P (decl) = 0;
2231 TREE_PUBLIC (decl) = 0;
2232 DECL_UNINLINABLE (decl) = 1;
2233 DECL_EXTERNAL (decl) = 0;
2234 DECL_CONTEXT (decl) = NULL_TREE;
2235 DECL_INITIAL (decl) = make_node (BLOCK);
2236 if (cgraph_node::get (current_function_decl)->offloadable)
2237 cgraph_node::get_create (decl)->offloadable = 1;
2238 else
2240 omp_context *octx;
2241 for (octx = ctx; octx; octx = octx->outer)
2242 if (is_gimple_omp_offloaded (octx->stmt))
2244 cgraph_node::get_create (decl)->offloadable = 1;
2245 #ifdef ENABLE_OFFLOADING
2246 g->have_offload = true;
2247 #endif
2248 break;
2252 t = build_decl (DECL_SOURCE_LOCATION (decl),
2253 RESULT_DECL, NULL_TREE, void_type_node);
2254 DECL_ARTIFICIAL (t) = 1;
2255 DECL_IGNORED_P (t) = 1;
2256 DECL_CONTEXT (t) = decl;
2257 DECL_RESULT (decl) = t;
2259 /* _Cilk_for's child function requires two extra parameters called
2260 __low and __high that are set the by Cilk runtime when it calls this
2261 function. */
2262 if (cilk_for_count)
2264 t = build_decl (DECL_SOURCE_LOCATION (decl),
2265 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2266 DECL_ARTIFICIAL (t) = 1;
2267 DECL_NAMELESS (t) = 1;
2268 DECL_ARG_TYPE (t) = ptr_type_node;
2269 DECL_CONTEXT (t) = current_function_decl;
2270 TREE_USED (t) = 1;
2271 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2272 DECL_ARGUMENTS (decl) = t;
2274 t = build_decl (DECL_SOURCE_LOCATION (decl),
2275 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2276 DECL_ARTIFICIAL (t) = 1;
2277 DECL_NAMELESS (t) = 1;
2278 DECL_ARG_TYPE (t) = ptr_type_node;
2279 DECL_CONTEXT (t) = current_function_decl;
2280 TREE_USED (t) = 1;
2281 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2282 DECL_ARGUMENTS (decl) = t;
2285 tree data_name = get_identifier (".omp_data_i");
2286 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2287 ptr_type_node);
2288 DECL_ARTIFICIAL (t) = 1;
2289 DECL_NAMELESS (t) = 1;
2290 DECL_ARG_TYPE (t) = ptr_type_node;
2291 DECL_CONTEXT (t) = current_function_decl;
2292 TREE_USED (t) = 1;
2293 if (cilk_for_count)
2294 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2295 DECL_ARGUMENTS (decl) = t;
2296 if (!task_copy)
2297 ctx->receiver_decl = t;
2298 else
2300 t = build_decl (DECL_SOURCE_LOCATION (decl),
2301 PARM_DECL, get_identifier (".omp_data_o"),
2302 ptr_type_node);
2303 DECL_ARTIFICIAL (t) = 1;
2304 DECL_NAMELESS (t) = 1;
2305 DECL_ARG_TYPE (t) = ptr_type_node;
2306 DECL_CONTEXT (t) = current_function_decl;
2307 TREE_USED (t) = 1;
2308 TREE_ADDRESSABLE (t) = 1;
2309 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2310 DECL_ARGUMENTS (decl) = t;
2313 /* Allocate memory for the function structure. The call to
2314 allocate_struct_function clobbers CFUN, so we need to restore
2315 it afterward. */
2316 push_struct_function (decl);
2317 cfun->function_end_locus = gimple_location (ctx->stmt);
2318 pop_cfun ();
2321 /* Callback for walk_gimple_seq. Check if combined parallel
2322 contains gimple_omp_for_combined_into_p OMP_FOR. */
2324 static tree
2325 find_combined_for (gimple_stmt_iterator *gsi_p,
2326 bool *handled_ops_p,
2327 struct walk_stmt_info *wi)
2329 gimple stmt = gsi_stmt (*gsi_p);
2331 *handled_ops_p = true;
2332 switch (gimple_code (stmt))
2334 WALK_SUBSTMTS;
2336 case GIMPLE_OMP_FOR:
2337 if (gimple_omp_for_combined_into_p (stmt)
2338 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2340 wi->info = stmt;
2341 return integer_zero_node;
2343 break;
2344 default:
2345 break;
2347 return NULL;
2350 /* Scan an OpenMP parallel directive. */
2352 static void
2353 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2355 omp_context *ctx;
2356 tree name;
2357 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2359 /* Ignore parallel directives with empty bodies, unless there
2360 are copyin clauses. */
2361 if (optimize > 0
2362 && empty_body_p (gimple_omp_body (stmt))
2363 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2364 OMP_CLAUSE_COPYIN) == NULL)
2366 gsi_replace (gsi, gimple_build_nop (), false);
2367 return;
2370 if (gimple_omp_parallel_combined_p (stmt))
2372 struct walk_stmt_info wi;
2374 memset (&wi, 0, sizeof (wi));
2375 wi.val_only = true;
2376 walk_gimple_seq (gimple_omp_body (stmt),
2377 find_combined_for, NULL, &wi);
2378 if (wi.info)
2380 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2381 struct omp_for_data fd;
2382 extract_omp_for_data (for_stmt, &fd, NULL);
2383 /* We need two temporaries with fd.loop.v type (istart/iend)
2384 and then (fd.collapse - 1) temporaries with the same
2385 type for count2 ... countN-1 vars if not constant. */
2386 size_t count = 2, i;
2387 tree type = fd.iter_type;
2388 if (fd.collapse > 1
2389 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2390 count += fd.collapse - 1;
2391 for (i = 0; i < count; i++)
2393 tree temp = create_tmp_var (type);
2394 tree c = build_omp_clause (UNKNOWN_LOCATION,
2395 OMP_CLAUSE__LOOPTEMP_);
2396 insert_decl_map (&outer_ctx->cb, temp, temp);
2397 OMP_CLAUSE_DECL (c) = temp;
2398 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2399 gimple_omp_parallel_set_clauses (stmt, c);
2404 ctx = new_omp_context (stmt, outer_ctx);
2405 taskreg_contexts.safe_push (ctx);
2406 if (taskreg_nesting_level > 1)
2407 ctx->is_nested = true;
2408 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2409 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2410 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2411 name = create_tmp_var_name (".omp_data_s");
2412 name = build_decl (gimple_location (stmt),
2413 TYPE_DECL, name, ctx->record_type);
2414 DECL_ARTIFICIAL (name) = 1;
2415 DECL_NAMELESS (name) = 1;
2416 TYPE_NAME (ctx->record_type) = name;
2417 create_omp_child_function (ctx, false);
2418 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2420 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2421 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2423 if (TYPE_FIELDS (ctx->record_type) == NULL)
2424 ctx->record_type = ctx->receiver_decl = NULL;
2427 /* Scan an OpenMP task directive. */
2429 static void
2430 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2432 omp_context *ctx;
2433 tree name, t;
2434 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2436 /* Ignore task directives with empty bodies. */
2437 if (optimize > 0
2438 && empty_body_p (gimple_omp_body (stmt)))
2440 gsi_replace (gsi, gimple_build_nop (), false);
2441 return;
2444 ctx = new_omp_context (stmt, outer_ctx);
2445 taskreg_contexts.safe_push (ctx);
2446 if (taskreg_nesting_level > 1)
2447 ctx->is_nested = true;
2448 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2449 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2450 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2451 name = create_tmp_var_name (".omp_data_s");
2452 name = build_decl (gimple_location (stmt),
2453 TYPE_DECL, name, ctx->record_type);
2454 DECL_ARTIFICIAL (name) = 1;
2455 DECL_NAMELESS (name) = 1;
2456 TYPE_NAME (ctx->record_type) = name;
2457 create_omp_child_function (ctx, false);
2458 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2460 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2462 if (ctx->srecord_type)
2464 name = create_tmp_var_name (".omp_data_a");
2465 name = build_decl (gimple_location (stmt),
2466 TYPE_DECL, name, ctx->srecord_type);
2467 DECL_ARTIFICIAL (name) = 1;
2468 DECL_NAMELESS (name) = 1;
2469 TYPE_NAME (ctx->srecord_type) = name;
2470 create_omp_child_function (ctx, true);
2473 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2475 if (TYPE_FIELDS (ctx->record_type) == NULL)
2477 ctx->record_type = ctx->receiver_decl = NULL;
2478 t = build_int_cst (long_integer_type_node, 0);
2479 gimple_omp_task_set_arg_size (stmt, t);
2480 t = build_int_cst (long_integer_type_node, 1);
2481 gimple_omp_task_set_arg_align (stmt, t);
2486 /* If any decls have been made addressable during scan_omp,
2487 adjust their fields if needed, and layout record types
2488 of parallel/task constructs. */
2490 static void
2491 finish_taskreg_scan (omp_context *ctx)
2493 if (ctx->record_type == NULL_TREE)
2494 return;
2496 /* If any task_shared_vars were needed, verify all
2497 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2498 statements if use_pointer_for_field hasn't changed
2499 because of that. If it did, update field types now. */
2500 if (task_shared_vars)
2502 tree c;
2504 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2505 c; c = OMP_CLAUSE_CHAIN (c))
2506 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2508 tree decl = OMP_CLAUSE_DECL (c);
2510 /* Global variables don't need to be copied,
2511 the receiver side will use them directly. */
2512 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2513 continue;
2514 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2515 || !use_pointer_for_field (decl, ctx))
2516 continue;
2517 tree field = lookup_field (decl, ctx);
2518 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2519 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2520 continue;
2521 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2522 TREE_THIS_VOLATILE (field) = 0;
2523 DECL_USER_ALIGN (field) = 0;
2524 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2525 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2526 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2527 if (ctx->srecord_type)
2529 tree sfield = lookup_sfield (decl, ctx);
2530 TREE_TYPE (sfield) = TREE_TYPE (field);
2531 TREE_THIS_VOLATILE (sfield) = 0;
2532 DECL_USER_ALIGN (sfield) = 0;
2533 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2534 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2535 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2540 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2542 layout_type (ctx->record_type);
2543 fixup_child_record_type (ctx);
2545 else
2547 location_t loc = gimple_location (ctx->stmt);
2548 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2549 /* Move VLA fields to the end. */
2550 p = &TYPE_FIELDS (ctx->record_type);
2551 while (*p)
2552 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2553 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2555 *q = *p;
2556 *p = TREE_CHAIN (*p);
2557 TREE_CHAIN (*q) = NULL_TREE;
2558 q = &TREE_CHAIN (*q);
2560 else
2561 p = &DECL_CHAIN (*p);
2562 *p = vla_fields;
2563 layout_type (ctx->record_type);
2564 fixup_child_record_type (ctx);
2565 if (ctx->srecord_type)
2566 layout_type (ctx->srecord_type);
2567 tree t = fold_convert_loc (loc, long_integer_type_node,
2568 TYPE_SIZE_UNIT (ctx->record_type));
2569 gimple_omp_task_set_arg_size (ctx->stmt, t);
2570 t = build_int_cst (long_integer_type_node,
2571 TYPE_ALIGN_UNIT (ctx->record_type));
2572 gimple_omp_task_set_arg_align (ctx->stmt, t);
2577 /* Scan a GIMPLE_OMP_FOR. */
2579 static void
2580 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2582 omp_context *ctx;
2583 size_t i;
2585 ctx = new_omp_context (stmt, outer_ctx);
2587 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2589 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2590 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2592 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2593 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2594 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2595 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2597 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2600 /* Scan an OpenMP sections directive. */
2602 static void
2603 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2605 omp_context *ctx;
2607 ctx = new_omp_context (stmt, outer_ctx);
2608 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2609 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2612 /* Scan an OpenMP single directive. */
2614 static void
2615 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2617 omp_context *ctx;
2618 tree name;
2620 ctx = new_omp_context (stmt, outer_ctx);
2621 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2622 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2623 name = create_tmp_var_name (".omp_copy_s");
2624 name = build_decl (gimple_location (stmt),
2625 TYPE_DECL, name, ctx->record_type);
2626 TYPE_NAME (ctx->record_type) = name;
2628 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2629 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2631 if (TYPE_FIELDS (ctx->record_type) == NULL)
2632 ctx->record_type = NULL;
2633 else
2634 layout_type (ctx->record_type);
2637 /* Scan a GIMPLE_OMP_TARGET. */
2639 static void
2640 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2642 omp_context *ctx;
2643 tree name;
2644 bool offloaded = is_gimple_omp_offloaded (stmt);
2646 ctx = new_omp_context (stmt, outer_ctx);
2647 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2648 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2649 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2650 name = create_tmp_var_name (".omp_data_t");
2651 name = build_decl (gimple_location (stmt),
2652 TYPE_DECL, name, ctx->record_type);
2653 DECL_ARTIFICIAL (name) = 1;
2654 DECL_NAMELESS (name) = 1;
2655 TYPE_NAME (ctx->record_type) = name;
2656 if (offloaded)
2658 if (is_gimple_omp_oacc_specifically (stmt))
2659 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2660 0, 0);
2662 create_omp_child_function (ctx, false);
2663 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2666 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2667 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2669 if (TYPE_FIELDS (ctx->record_type) == NULL)
2670 ctx->record_type = ctx->receiver_decl = NULL;
2671 else
2673 TYPE_FIELDS (ctx->record_type)
2674 = nreverse (TYPE_FIELDS (ctx->record_type));
2675 #ifdef ENABLE_CHECKING
2676 tree field;
2677 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2678 for (field = TYPE_FIELDS (ctx->record_type);
2679 field;
2680 field = DECL_CHAIN (field))
2681 gcc_assert (DECL_ALIGN (field) == align);
2682 #endif
2683 layout_type (ctx->record_type);
2684 if (offloaded)
2685 fixup_child_record_type (ctx);
2689 /* Scan an OpenMP teams directive. */
2691 static void
2692 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2694 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2695 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2696 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2699 /* Check nesting restrictions. */
2700 static bool
2701 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2703 /* TODO: Some OpenACC/OpenMP nesting should be allowed. */
2705 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2706 inside an OpenACC CTX. */
2707 if (!(is_gimple_omp (stmt)
2708 && is_gimple_omp_oacc_specifically (stmt)))
2710 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2711 if (is_gimple_omp (ctx_->stmt)
2712 && is_gimple_omp_oacc_specifically (ctx_->stmt))
2714 error_at (gimple_location (stmt),
2715 "non-OpenACC construct inside of OpenACC region");
2716 return false;
2720 if (ctx != NULL)
2722 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2723 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2725 error_at (gimple_location (stmt),
2726 "OpenMP constructs may not be nested inside simd region");
2727 return false;
2729 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2731 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2732 || (gimple_omp_for_kind (stmt)
2733 != GF_OMP_FOR_KIND_DISTRIBUTE))
2734 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2736 error_at (gimple_location (stmt),
2737 "only distribute or parallel constructs are allowed to "
2738 "be closely nested inside teams construct");
2739 return false;
2743 switch (gimple_code (stmt))
2745 case GIMPLE_OMP_FOR:
2746 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2747 return true;
2748 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2750 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2752 error_at (gimple_location (stmt),
2753 "distribute construct must be closely nested inside "
2754 "teams construct");
2755 return false;
2757 return true;
2759 /* FALLTHRU */
2760 case GIMPLE_CALL:
2761 if (is_gimple_call (stmt)
2762 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2763 == BUILT_IN_GOMP_CANCEL
2764 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2765 == BUILT_IN_GOMP_CANCELLATION_POINT))
2767 const char *bad = NULL;
2768 const char *kind = NULL;
2769 if (ctx == NULL)
2771 error_at (gimple_location (stmt), "orphaned %qs construct",
2772 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2773 == BUILT_IN_GOMP_CANCEL
2774 ? "#pragma omp cancel"
2775 : "#pragma omp cancellation point");
2776 return false;
2778 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2779 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2780 : 0)
2782 case 1:
2783 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2784 bad = "#pragma omp parallel";
2785 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2786 == BUILT_IN_GOMP_CANCEL
2787 && !integer_zerop (gimple_call_arg (stmt, 1)))
2788 ctx->cancellable = true;
2789 kind = "parallel";
2790 break;
2791 case 2:
2792 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2793 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2794 bad = "#pragma omp for";
2795 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2796 == BUILT_IN_GOMP_CANCEL
2797 && !integer_zerop (gimple_call_arg (stmt, 1)))
2799 ctx->cancellable = true;
2800 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2801 OMP_CLAUSE_NOWAIT))
2802 warning_at (gimple_location (stmt), 0,
2803 "%<#pragma omp cancel for%> inside "
2804 "%<nowait%> for construct");
2805 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2806 OMP_CLAUSE_ORDERED))
2807 warning_at (gimple_location (stmt), 0,
2808 "%<#pragma omp cancel for%> inside "
2809 "%<ordered%> for construct");
2811 kind = "for";
2812 break;
2813 case 4:
2814 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2815 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2816 bad = "#pragma omp sections";
2817 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2818 == BUILT_IN_GOMP_CANCEL
2819 && !integer_zerop (gimple_call_arg (stmt, 1)))
2821 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2823 ctx->cancellable = true;
2824 if (find_omp_clause (gimple_omp_sections_clauses
2825 (ctx->stmt),
2826 OMP_CLAUSE_NOWAIT))
2827 warning_at (gimple_location (stmt), 0,
2828 "%<#pragma omp cancel sections%> inside "
2829 "%<nowait%> sections construct");
2831 else
2833 gcc_assert (ctx->outer
2834 && gimple_code (ctx->outer->stmt)
2835 == GIMPLE_OMP_SECTIONS);
2836 ctx->outer->cancellable = true;
2837 if (find_omp_clause (gimple_omp_sections_clauses
2838 (ctx->outer->stmt),
2839 OMP_CLAUSE_NOWAIT))
2840 warning_at (gimple_location (stmt), 0,
2841 "%<#pragma omp cancel sections%> inside "
2842 "%<nowait%> sections construct");
2845 kind = "sections";
2846 break;
2847 case 8:
2848 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2849 bad = "#pragma omp task";
2850 else
2851 ctx->cancellable = true;
2852 kind = "taskgroup";
2853 break;
2854 default:
2855 error_at (gimple_location (stmt), "invalid arguments");
2856 return false;
2858 if (bad)
2860 error_at (gimple_location (stmt),
2861 "%<%s %s%> construct not closely nested inside of %qs",
2862 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2863 == BUILT_IN_GOMP_CANCEL
2864 ? "#pragma omp cancel"
2865 : "#pragma omp cancellation point", kind, bad);
2866 return false;
2869 /* FALLTHRU */
2870 case GIMPLE_OMP_SECTIONS:
2871 case GIMPLE_OMP_SINGLE:
2872 for (; ctx != NULL; ctx = ctx->outer)
2873 switch (gimple_code (ctx->stmt))
2875 case GIMPLE_OMP_FOR:
2876 case GIMPLE_OMP_SECTIONS:
2877 case GIMPLE_OMP_SINGLE:
2878 case GIMPLE_OMP_ORDERED:
2879 case GIMPLE_OMP_MASTER:
2880 case GIMPLE_OMP_TASK:
2881 case GIMPLE_OMP_CRITICAL:
2882 if (is_gimple_call (stmt))
2884 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2885 != BUILT_IN_GOMP_BARRIER)
2886 return true;
2887 error_at (gimple_location (stmt),
2888 "barrier region may not be closely nested inside "
2889 "of work-sharing, critical, ordered, master or "
2890 "explicit task region");
2891 return false;
2893 error_at (gimple_location (stmt),
2894 "work-sharing region may not be closely nested inside "
2895 "of work-sharing, critical, ordered, master or explicit "
2896 "task region");
2897 return false;
2898 case GIMPLE_OMP_PARALLEL:
2899 return true;
2900 default:
2901 break;
2903 break;
2904 case GIMPLE_OMP_MASTER:
2905 for (; ctx != NULL; ctx = ctx->outer)
2906 switch (gimple_code (ctx->stmt))
2908 case GIMPLE_OMP_FOR:
2909 case GIMPLE_OMP_SECTIONS:
2910 case GIMPLE_OMP_SINGLE:
2911 case GIMPLE_OMP_TASK:
2912 error_at (gimple_location (stmt),
2913 "master region may not be closely nested inside "
2914 "of work-sharing or explicit task region");
2915 return false;
2916 case GIMPLE_OMP_PARALLEL:
2917 return true;
2918 default:
2919 break;
2921 break;
2922 case GIMPLE_OMP_ORDERED:
2923 for (; ctx != NULL; ctx = ctx->outer)
2924 switch (gimple_code (ctx->stmt))
2926 case GIMPLE_OMP_CRITICAL:
2927 case GIMPLE_OMP_TASK:
2928 error_at (gimple_location (stmt),
2929 "ordered region may not be closely nested inside "
2930 "of critical or explicit task region");
2931 return false;
2932 case GIMPLE_OMP_FOR:
2933 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2934 OMP_CLAUSE_ORDERED) == NULL)
2936 error_at (gimple_location (stmt),
2937 "ordered region must be closely nested inside "
2938 "a loop region with an ordered clause");
2939 return false;
2941 return true;
2942 case GIMPLE_OMP_PARALLEL:
2943 error_at (gimple_location (stmt),
2944 "ordered region must be closely nested inside "
2945 "a loop region with an ordered clause");
2946 return false;
2947 default:
2948 break;
2950 break;
2951 case GIMPLE_OMP_CRITICAL:
2953 tree this_stmt_name
2954 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2955 for (; ctx != NULL; ctx = ctx->outer)
2956 if (gomp_critical *other_crit
2957 = dyn_cast <gomp_critical *> (ctx->stmt))
2958 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2960 error_at (gimple_location (stmt),
2961 "critical region may not be nested inside a critical "
2962 "region with the same name");
2963 return false;
2966 break;
2967 case GIMPLE_OMP_TEAMS:
2968 if (ctx == NULL
2969 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2970 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2972 error_at (gimple_location (stmt),
2973 "teams construct not closely nested inside of target "
2974 "region");
2975 return false;
2977 break;
2978 case GIMPLE_OMP_TARGET:
2979 for (; ctx != NULL; ctx = ctx->outer)
2981 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2983 if (is_gimple_omp (stmt)
2984 && is_gimple_omp_oacc_specifically (stmt)
2985 && is_gimple_omp (ctx->stmt))
2987 error_at (gimple_location (stmt),
2988 "OpenACC construct inside of non-OpenACC region");
2989 return false;
2991 continue;
2994 const char *stmt_name, *ctx_stmt_name;
2995 switch (gimple_omp_target_kind (stmt))
2997 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
2998 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
2999 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3000 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3001 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3002 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3003 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3004 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3005 default: gcc_unreachable ();
3007 switch (gimple_omp_target_kind (ctx->stmt))
3009 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3010 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3011 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3012 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3013 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3014 default: gcc_unreachable ();
3017 /* OpenACC/OpenMP mismatch? */
3018 if (is_gimple_omp_oacc_specifically (stmt)
3019 != is_gimple_omp_oacc_specifically (ctx->stmt))
3021 error_at (gimple_location (stmt),
3022 "%s %s construct inside of %s %s region",
3023 (is_gimple_omp_oacc_specifically (stmt)
3024 ? "OpenACC" : "OpenMP"), stmt_name,
3025 (is_gimple_omp_oacc_specifically (ctx->stmt)
3026 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3027 return false;
3029 if (is_gimple_omp_offloaded (ctx->stmt))
3031 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3032 if (is_gimple_omp_oacc_specifically (ctx->stmt))
3034 error_at (gimple_location (stmt),
3035 "%s construct inside of %s region",
3036 stmt_name, ctx_stmt_name);
3037 return false;
3039 else
3041 gcc_assert (!is_gimple_omp_oacc_specifically (stmt));
3042 warning_at (gimple_location (stmt), 0,
3043 "%s construct inside of %s region",
3044 stmt_name, ctx_stmt_name);
3048 break;
3049 default:
3050 break;
3052 return true;
3056 /* Helper function scan_omp.
3058 Callback for walk_tree or operators in walk_gimple_stmt used to
3059 scan for OpenMP directives in TP. */
3061 static tree
3062 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3064 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3065 omp_context *ctx = (omp_context *) wi->info;
3066 tree t = *tp;
3068 switch (TREE_CODE (t))
3070 case VAR_DECL:
3071 case PARM_DECL:
3072 case LABEL_DECL:
3073 case RESULT_DECL:
3074 if (ctx)
3075 *tp = remap_decl (t, &ctx->cb);
3076 break;
3078 default:
3079 if (ctx && TYPE_P (t))
3080 *tp = remap_type (t, &ctx->cb);
3081 else if (!DECL_P (t))
3083 *walk_subtrees = 1;
3084 if (ctx)
3086 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3087 if (tem != TREE_TYPE (t))
3089 if (TREE_CODE (t) == INTEGER_CST)
3090 *tp = wide_int_to_tree (tem, t);
3091 else
3092 TREE_TYPE (t) = tem;
3096 break;
3099 return NULL_TREE;
3102 /* Return true if FNDECL is a setjmp or a longjmp. */
3104 static bool
3105 setjmp_or_longjmp_p (const_tree fndecl)
3107 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3108 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3109 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3110 return true;
3112 tree declname = DECL_NAME (fndecl);
3113 if (!declname)
3114 return false;
3115 const char *name = IDENTIFIER_POINTER (declname);
3116 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3120 /* Helper function for scan_omp.
3122 Callback for walk_gimple_stmt used to scan for OpenMP directives in
3123 the current statement in GSI. */
3125 static tree
3126 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3127 struct walk_stmt_info *wi)
3129 gimple stmt = gsi_stmt (*gsi);
3130 omp_context *ctx = (omp_context *) wi->info;
3132 if (gimple_has_location (stmt))
3133 input_location = gimple_location (stmt);
3135 /* Check the OpenMP nesting restrictions. */
3136 bool remove = false;
3137 if (is_gimple_omp (stmt))
3138 remove = !check_omp_nesting_restrictions (stmt, ctx);
3139 else if (is_gimple_call (stmt))
3141 tree fndecl = gimple_call_fndecl (stmt);
3142 if (fndecl)
3144 if (setjmp_or_longjmp_p (fndecl)
3145 && ctx
3146 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3147 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3149 remove = true;
3150 error_at (gimple_location (stmt),
3151 "setjmp/longjmp inside simd construct");
3153 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3154 switch (DECL_FUNCTION_CODE (fndecl))
3156 case BUILT_IN_GOMP_BARRIER:
3157 case BUILT_IN_GOMP_CANCEL:
3158 case BUILT_IN_GOMP_CANCELLATION_POINT:
3159 case BUILT_IN_GOMP_TASKYIELD:
3160 case BUILT_IN_GOMP_TASKWAIT:
3161 case BUILT_IN_GOMP_TASKGROUP_START:
3162 case BUILT_IN_GOMP_TASKGROUP_END:
3163 remove = !check_omp_nesting_restrictions (stmt, ctx);
3164 break;
3165 default:
3166 break;
3170 if (remove)
3172 stmt = gimple_build_nop ();
3173 gsi_replace (gsi, stmt, false);
3176 *handled_ops_p = true;
3178 switch (gimple_code (stmt))
3180 case GIMPLE_OMP_PARALLEL:
3181 taskreg_nesting_level++;
3182 scan_omp_parallel (gsi, ctx);
3183 taskreg_nesting_level--;
3184 break;
3186 case GIMPLE_OMP_TASK:
3187 taskreg_nesting_level++;
3188 scan_omp_task (gsi, ctx);
3189 taskreg_nesting_level--;
3190 break;
3192 case GIMPLE_OMP_FOR:
3193 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3194 break;
3196 case GIMPLE_OMP_SECTIONS:
3197 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3198 break;
3200 case GIMPLE_OMP_SINGLE:
3201 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3202 break;
3204 case GIMPLE_OMP_SECTION:
3205 case GIMPLE_OMP_MASTER:
3206 case GIMPLE_OMP_TASKGROUP:
3207 case GIMPLE_OMP_ORDERED:
3208 case GIMPLE_OMP_CRITICAL:
3209 ctx = new_omp_context (stmt, ctx);
3210 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3211 break;
3213 case GIMPLE_OMP_TARGET:
3214 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3215 break;
3217 case GIMPLE_OMP_TEAMS:
3218 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3219 break;
3221 case GIMPLE_BIND:
3223 tree var;
3225 *handled_ops_p = false;
3226 if (ctx)
3227 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3228 var ;
3229 var = DECL_CHAIN (var))
3230 insert_decl_map (&ctx->cb, var, var);
3232 break;
3233 default:
3234 *handled_ops_p = false;
3235 break;
3238 return NULL_TREE;
3242 /* Scan all the statements starting at the current statement. CTX
3243 contains context information about the OpenMP directives and
3244 clauses found during the scan. */
3246 static void
3247 scan_omp (gimple_seq *body_p, omp_context *ctx)
3249 location_t saved_location;
3250 struct walk_stmt_info wi;
3252 memset (&wi, 0, sizeof (wi));
3253 wi.info = ctx;
3254 wi.want_locations = true;
3256 saved_location = input_location;
3257 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3258 input_location = saved_location;
3261 /* Re-gimplification and code generation routines. */
3263 /* Build a call to GOMP_barrier. */
3265 static gimple
3266 build_omp_barrier (tree lhs)
3268 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3269 : BUILT_IN_GOMP_BARRIER);
3270 gcall *g = gimple_build_call (fndecl, 0);
3271 if (lhs)
3272 gimple_call_set_lhs (g, lhs);
3273 return g;
3276 /* If a context was created for STMT when it was scanned, return it. */
3278 static omp_context *
3279 maybe_lookup_ctx (gimple stmt)
3281 splay_tree_node n;
3282 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3283 return n ? (omp_context *) n->value : NULL;
3287 /* Find the mapping for DECL in CTX or the immediately enclosing
3288 context that has a mapping for DECL.
3290 If CTX is a nested parallel directive, we may have to use the decl
3291 mappings created in CTX's parent context. Suppose that we have the
3292 following parallel nesting (variable UIDs showed for clarity):
3294 iD.1562 = 0;
3295 #omp parallel shared(iD.1562) -> outer parallel
3296 iD.1562 = iD.1562 + 1;
3298 #omp parallel shared (iD.1562) -> inner parallel
3299 iD.1562 = iD.1562 - 1;
3301 Each parallel structure will create a distinct .omp_data_s structure
3302 for copying iD.1562 in/out of the directive:
3304 outer parallel .omp_data_s.1.i -> iD.1562
3305 inner parallel .omp_data_s.2.i -> iD.1562
3307 A shared variable mapping will produce a copy-out operation before
3308 the parallel directive and a copy-in operation after it. So, in
3309 this case we would have:
3311 iD.1562 = 0;
3312 .omp_data_o.1.i = iD.1562;
3313 #omp parallel shared(iD.1562) -> outer parallel
3314 .omp_data_i.1 = &.omp_data_o.1
3315 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3317 .omp_data_o.2.i = iD.1562; -> **
3318 #omp parallel shared(iD.1562) -> inner parallel
3319 .omp_data_i.2 = &.omp_data_o.2
3320 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3323 ** This is a problem. The symbol iD.1562 cannot be referenced
3324 inside the body of the outer parallel region. But since we are
3325 emitting this copy operation while expanding the inner parallel
3326 directive, we need to access the CTX structure of the outer
3327 parallel directive to get the correct mapping:
3329 .omp_data_o.2.i = .omp_data_i.1->i
3331 Since there may be other workshare or parallel directives enclosing
3332 the parallel directive, it may be necessary to walk up the context
3333 parent chain. This is not a problem in general because nested
3334 parallelism happens only rarely. */
3336 static tree
3337 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3339 tree t;
3340 omp_context *up;
3342 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3343 t = maybe_lookup_decl (decl, up);
3345 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3347 return t ? t : decl;
3351 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3352 in outer contexts. */
3354 static tree
3355 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3357 tree t = NULL;
3358 omp_context *up;
3360 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3361 t = maybe_lookup_decl (decl, up);
3363 return t ? t : decl;
3367 /* Construct the initialization value for reduction CLAUSE. */
3369 tree
3370 omp_reduction_init (tree clause, tree type)
3372 location_t loc = OMP_CLAUSE_LOCATION (clause);
3373 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3375 case PLUS_EXPR:
3376 case MINUS_EXPR:
3377 case BIT_IOR_EXPR:
3378 case BIT_XOR_EXPR:
3379 case TRUTH_OR_EXPR:
3380 case TRUTH_ORIF_EXPR:
3381 case TRUTH_XOR_EXPR:
3382 case NE_EXPR:
3383 return build_zero_cst (type);
3385 case MULT_EXPR:
3386 case TRUTH_AND_EXPR:
3387 case TRUTH_ANDIF_EXPR:
3388 case EQ_EXPR:
3389 return fold_convert_loc (loc, type, integer_one_node);
3391 case BIT_AND_EXPR:
3392 return fold_convert_loc (loc, type, integer_minus_one_node);
3394 case MAX_EXPR:
3395 if (SCALAR_FLOAT_TYPE_P (type))
3397 REAL_VALUE_TYPE max, min;
3398 if (HONOR_INFINITIES (type))
3400 real_inf (&max);
3401 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3403 else
3404 real_maxval (&min, 1, TYPE_MODE (type));
3405 return build_real (type, min);
3407 else
3409 gcc_assert (INTEGRAL_TYPE_P (type));
3410 return TYPE_MIN_VALUE (type);
3413 case MIN_EXPR:
3414 if (SCALAR_FLOAT_TYPE_P (type))
3416 REAL_VALUE_TYPE max;
3417 if (HONOR_INFINITIES (type))
3418 real_inf (&max);
3419 else
3420 real_maxval (&max, 0, TYPE_MODE (type));
3421 return build_real (type, max);
3423 else
3425 gcc_assert (INTEGRAL_TYPE_P (type));
3426 return TYPE_MAX_VALUE (type);
3429 default:
3430 gcc_unreachable ();
3434 /* Return alignment to be assumed for var in CLAUSE, which should be
3435 OMP_CLAUSE_ALIGNED. */
3437 static tree
3438 omp_clause_aligned_alignment (tree clause)
3440 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3441 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3443 /* Otherwise return implementation defined alignment. */
3444 unsigned int al = 1;
3445 machine_mode mode, vmode;
3446 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3447 if (vs)
3448 vs = 1 << floor_log2 (vs);
3449 static enum mode_class classes[]
3450 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3451 for (int i = 0; i < 4; i += 2)
3452 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3453 mode != VOIDmode;
3454 mode = GET_MODE_WIDER_MODE (mode))
3456 vmode = targetm.vectorize.preferred_simd_mode (mode);
3457 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3458 continue;
3459 while (vs
3460 && GET_MODE_SIZE (vmode) < vs
3461 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3462 vmode = GET_MODE_2XWIDER_MODE (vmode);
3464 tree type = lang_hooks.types.type_for_mode (mode, 1);
3465 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3466 continue;
3467 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3468 / GET_MODE_SIZE (mode));
3469 if (TYPE_MODE (type) != vmode)
3470 continue;
3471 if (TYPE_ALIGN_UNIT (type) > al)
3472 al = TYPE_ALIGN_UNIT (type);
3474 return build_int_cst (integer_type_node, al);
3477 /* Return maximum possible vectorization factor for the target. */
3479 static int
3480 omp_max_vf (void)
3482 if (!optimize
3483 || optimize_debug
3484 || !flag_tree_loop_optimize
3485 || (!flag_tree_loop_vectorize
3486 && (global_options_set.x_flag_tree_loop_vectorize
3487 || global_options_set.x_flag_tree_vectorize)))
3488 return 1;
3490 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3491 if (vs)
3493 vs = 1 << floor_log2 (vs);
3494 return vs;
3496 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3497 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3498 return GET_MODE_NUNITS (vqimode);
3499 return 1;
3502 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3503 privatization. */
3505 static bool
3506 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3507 tree &idx, tree &lane, tree &ivar, tree &lvar)
3509 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
3511 if (max_vf == 0)
3513 max_vf = omp_max_vf ();
3514 if (max_vf > 1)
3516 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3517 OMP_CLAUSE_SAFELEN);
3518 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3519 max_vf = 1;
3520 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3521 max_vf) == -1)
3522 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3524 if (max_vf > 1)
3526 idx = create_tmp_var (unsigned_type_node);
3527 lane = create_tmp_var (unsigned_type_node);
3530 if (max_vf == 1)
3531 return false;
3533 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3534 tree avar = create_tmp_var_raw (atype);
3535 if (TREE_ADDRESSABLE (new_var))
3536 TREE_ADDRESSABLE (avar) = 1;
3537 DECL_ATTRIBUTES (avar)
3538 = tree_cons (get_identifier ("omp simd array"), NULL,
3539 DECL_ATTRIBUTES (avar));
3540 gimple_add_tmp_var (avar);
3541 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3542 NULL_TREE, NULL_TREE);
3543 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3544 NULL_TREE, NULL_TREE);
3545 if (DECL_P (new_var))
3547 SET_DECL_VALUE_EXPR (new_var, lvar);
3548 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3550 return true;
3553 /* Helper function of lower_rec_input_clauses. For a reference
3554 in simd reduction, add an underlying variable it will reference. */
3556 static void
3557 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3559 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3560 if (TREE_CONSTANT (z))
3562 const char *name = NULL;
3563 if (DECL_NAME (new_vard))
3564 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3566 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3567 gimple_add_tmp_var (z);
3568 TREE_ADDRESSABLE (z) = 1;
3569 z = build_fold_addr_expr_loc (loc, z);
3570 gimplify_assign (new_vard, z, ilist);
3574 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3575 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3576 private variables. Initialization statements go in ILIST, while calls
3577 to destructors go in DLIST. */
3579 static void
3580 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3581 omp_context *ctx, struct omp_for_data *fd)
3583 tree c, dtor, copyin_seq, x, ptr;
3584 bool copyin_by_ref = false;
3585 bool lastprivate_firstprivate = false;
3586 bool reduction_omp_orig_ref = false;
3587 int pass;
3588 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3589 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3590 int max_vf = 0;
3591 tree lane = NULL_TREE, idx = NULL_TREE;
3592 tree ivar = NULL_TREE, lvar = NULL_TREE;
3593 gimple_seq llist[2] = { NULL, NULL };
3595 copyin_seq = NULL;
3597 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3598 with data sharing clauses referencing variable sized vars. That
3599 is unnecessarily hard to support and very unlikely to result in
3600 vectorized code anyway. */
3601 if (is_simd)
3602 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3603 switch (OMP_CLAUSE_CODE (c))
3605 case OMP_CLAUSE_LINEAR:
3606 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3607 max_vf = 1;
3608 /* FALLTHRU */
3609 case OMP_CLAUSE_REDUCTION:
3610 case OMP_CLAUSE_PRIVATE:
3611 case OMP_CLAUSE_FIRSTPRIVATE:
3612 case OMP_CLAUSE_LASTPRIVATE:
3613 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3614 max_vf = 1;
3615 break;
3616 default:
3617 continue;
3620 /* Do all the fixed sized types in the first pass, and the variable sized
3621 types in the second pass. This makes sure that the scalar arguments to
3622 the variable sized types are processed before we use them in the
3623 variable sized operations. */
3624 for (pass = 0; pass < 2; ++pass)
3626 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3628 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3629 tree var, new_var;
3630 bool by_ref;
3631 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3633 switch (c_kind)
3635 case OMP_CLAUSE_PRIVATE:
3636 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3637 continue;
3638 break;
3639 case OMP_CLAUSE_SHARED:
3640 /* Ignore shared directives in teams construct. */
3641 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3642 continue;
3643 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3645 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3646 continue;
3648 case OMP_CLAUSE_FIRSTPRIVATE:
3649 case OMP_CLAUSE_COPYIN:
3650 case OMP_CLAUSE_LINEAR:
3651 break;
3652 case OMP_CLAUSE_REDUCTION:
3653 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3654 reduction_omp_orig_ref = true;
3655 break;
3656 case OMP_CLAUSE__LOOPTEMP_:
3657 /* Handle _looptemp_ clauses only on parallel. */
3658 if (fd)
3659 continue;
3660 break;
3661 case OMP_CLAUSE_LASTPRIVATE:
3662 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3664 lastprivate_firstprivate = true;
3665 if (pass != 0)
3666 continue;
3668 /* Even without corresponding firstprivate, if
3669 decl is Fortran allocatable, it needs outer var
3670 reference. */
3671 else if (pass == 0
3672 && lang_hooks.decls.omp_private_outer_ref
3673 (OMP_CLAUSE_DECL (c)))
3674 lastprivate_firstprivate = true;
3675 break;
3676 case OMP_CLAUSE_ALIGNED:
3677 if (pass == 0)
3678 continue;
3679 var = OMP_CLAUSE_DECL (c);
3680 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3681 && !is_global_var (var))
3683 new_var = maybe_lookup_decl (var, ctx);
3684 if (new_var == NULL_TREE)
3685 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3686 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3687 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3688 omp_clause_aligned_alignment (c));
3689 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3690 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3691 gimplify_and_add (x, ilist);
3693 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3694 && is_global_var (var))
3696 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3697 new_var = lookup_decl (var, ctx);
3698 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3699 t = build_fold_addr_expr_loc (clause_loc, t);
3700 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3701 t = build_call_expr_loc (clause_loc, t2, 2, t,
3702 omp_clause_aligned_alignment (c));
3703 t = fold_convert_loc (clause_loc, ptype, t);
3704 x = create_tmp_var (ptype);
3705 t = build2 (MODIFY_EXPR, ptype, x, t);
3706 gimplify_and_add (t, ilist);
3707 t = build_simple_mem_ref_loc (clause_loc, x);
3708 SET_DECL_VALUE_EXPR (new_var, t);
3709 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3711 continue;
3712 default:
3713 continue;
3716 new_var = var = OMP_CLAUSE_DECL (c);
3717 if (c_kind != OMP_CLAUSE_COPYIN)
3718 new_var = lookup_decl (var, ctx);
3720 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3722 if (pass != 0)
3723 continue;
3725 else if (is_variable_sized (var))
3727 /* For variable sized types, we need to allocate the
3728 actual storage here. Call alloca and store the
3729 result in the pointer decl that we created elsewhere. */
3730 if (pass == 0)
3731 continue;
3733 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3735 gcall *stmt;
3736 tree tmp, atmp;
3738 ptr = DECL_VALUE_EXPR (new_var);
3739 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3740 ptr = TREE_OPERAND (ptr, 0);
3741 gcc_assert (DECL_P (ptr));
3742 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3744 /* void *tmp = __builtin_alloca */
3745 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3746 stmt = gimple_build_call (atmp, 1, x);
3747 tmp = create_tmp_var_raw (ptr_type_node);
3748 gimple_add_tmp_var (tmp);
3749 gimple_call_set_lhs (stmt, tmp);
3751 gimple_seq_add_stmt (ilist, stmt);
3753 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3754 gimplify_assign (ptr, x, ilist);
3757 else if (is_reference (var))
3759 /* For references that are being privatized for Fortran,
3760 allocate new backing storage for the new pointer
3761 variable. This allows us to avoid changing all the
3762 code that expects a pointer to something that expects
3763 a direct variable. */
3764 if (pass == 0)
3765 continue;
3767 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3768 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3770 x = build_receiver_ref (var, false, ctx);
3771 x = build_fold_addr_expr_loc (clause_loc, x);
3773 else if (TREE_CONSTANT (x))
3775 /* For reduction in SIMD loop, defer adding the
3776 initialization of the reference, because if we decide
3777 to use SIMD array for it, the initilization could cause
3778 expansion ICE. */
3779 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3780 x = NULL_TREE;
3781 else
3783 const char *name = NULL;
3784 if (DECL_NAME (var))
3785 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3787 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3788 name);
3789 gimple_add_tmp_var (x);
3790 TREE_ADDRESSABLE (x) = 1;
3791 x = build_fold_addr_expr_loc (clause_loc, x);
3794 else
3796 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3797 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3800 if (x)
3802 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3803 gimplify_assign (new_var, x, ilist);
3806 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3808 else if (c_kind == OMP_CLAUSE_REDUCTION
3809 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3811 if (pass == 0)
3812 continue;
3814 else if (pass != 0)
3815 continue;
3817 switch (OMP_CLAUSE_CODE (c))
3819 case OMP_CLAUSE_SHARED:
3820 /* Ignore shared directives in teams construct. */
3821 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3822 continue;
3823 /* Shared global vars are just accessed directly. */
3824 if (is_global_var (new_var))
3825 break;
3826 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3827 needs to be delayed until after fixup_child_record_type so
3828 that we get the correct type during the dereference. */
3829 by_ref = use_pointer_for_field (var, ctx);
3830 x = build_receiver_ref (var, by_ref, ctx);
3831 SET_DECL_VALUE_EXPR (new_var, x);
3832 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3834 /* ??? If VAR is not passed by reference, and the variable
3835 hasn't been initialized yet, then we'll get a warning for
3836 the store into the omp_data_s structure. Ideally, we'd be
3837 able to notice this and not store anything at all, but
3838 we're generating code too early. Suppress the warning. */
3839 if (!by_ref)
3840 TREE_NO_WARNING (var) = 1;
3841 break;
3843 case OMP_CLAUSE_LASTPRIVATE:
3844 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3845 break;
3846 /* FALLTHRU */
3848 case OMP_CLAUSE_PRIVATE:
3849 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3850 x = build_outer_var_ref (var, ctx);
3851 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3853 if (is_task_ctx (ctx))
3854 x = build_receiver_ref (var, false, ctx);
3855 else
3856 x = build_outer_var_ref (var, ctx);
3858 else
3859 x = NULL;
3860 do_private:
3861 tree nx;
3862 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3863 if (is_simd)
3865 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3866 if ((TREE_ADDRESSABLE (new_var) || nx || y
3867 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3868 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3869 idx, lane, ivar, lvar))
3871 if (nx)
3872 x = lang_hooks.decls.omp_clause_default_ctor
3873 (c, unshare_expr (ivar), x);
3874 if (nx && x)
3875 gimplify_and_add (x, &llist[0]);
3876 if (y)
3878 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3879 if (y)
3881 gimple_seq tseq = NULL;
3883 dtor = y;
3884 gimplify_stmt (&dtor, &tseq);
3885 gimple_seq_add_seq (&llist[1], tseq);
3888 break;
3891 if (nx)
3892 gimplify_and_add (nx, ilist);
3893 /* FALLTHRU */
3895 do_dtor:
3896 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3897 if (x)
3899 gimple_seq tseq = NULL;
3901 dtor = x;
3902 gimplify_stmt (&dtor, &tseq);
3903 gimple_seq_add_seq (dlist, tseq);
3905 break;
3907 case OMP_CLAUSE_LINEAR:
3908 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3909 goto do_firstprivate;
3910 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3911 x = NULL;
3912 else
3913 x = build_outer_var_ref (var, ctx);
3914 goto do_private;
3916 case OMP_CLAUSE_FIRSTPRIVATE:
3917 if (is_task_ctx (ctx))
3919 if (is_reference (var) || is_variable_sized (var))
3920 goto do_dtor;
3921 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3922 ctx))
3923 || use_pointer_for_field (var, NULL))
3925 x = build_receiver_ref (var, false, ctx);
3926 SET_DECL_VALUE_EXPR (new_var, x);
3927 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3928 goto do_dtor;
3931 do_firstprivate:
3932 x = build_outer_var_ref (var, ctx);
3933 if (is_simd)
3935 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3936 && gimple_omp_for_combined_into_p (ctx->stmt))
3938 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3939 tree stept = TREE_TYPE (t);
3940 tree ct = find_omp_clause (clauses,
3941 OMP_CLAUSE__LOOPTEMP_);
3942 gcc_assert (ct);
3943 tree l = OMP_CLAUSE_DECL (ct);
3944 tree n1 = fd->loop.n1;
3945 tree step = fd->loop.step;
3946 tree itype = TREE_TYPE (l);
3947 if (POINTER_TYPE_P (itype))
3948 itype = signed_type_for (itype);
3949 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3950 if (TYPE_UNSIGNED (itype)
3951 && fd->loop.cond_code == GT_EXPR)
3952 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3953 fold_build1 (NEGATE_EXPR, itype, l),
3954 fold_build1 (NEGATE_EXPR,
3955 itype, step));
3956 else
3957 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3958 t = fold_build2 (MULT_EXPR, stept,
3959 fold_convert (stept, l), t);
3961 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3963 x = lang_hooks.decls.omp_clause_linear_ctor
3964 (c, new_var, x, t);
3965 gimplify_and_add (x, ilist);
3966 goto do_dtor;
3969 if (POINTER_TYPE_P (TREE_TYPE (x)))
3970 x = fold_build2 (POINTER_PLUS_EXPR,
3971 TREE_TYPE (x), x, t);
3972 else
3973 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3976 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3977 || TREE_ADDRESSABLE (new_var))
3978 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3979 idx, lane, ivar, lvar))
3981 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3983 tree iv = create_tmp_var (TREE_TYPE (new_var));
3984 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3985 gimplify_and_add (x, ilist);
3986 gimple_stmt_iterator gsi
3987 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3988 gassign *g
3989 = gimple_build_assign (unshare_expr (lvar), iv);
3990 gsi_insert_before_without_update (&gsi, g,
3991 GSI_SAME_STMT);
3992 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3993 enum tree_code code = PLUS_EXPR;
3994 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3995 code = POINTER_PLUS_EXPR;
3996 g = gimple_build_assign (iv, code, iv, t);
3997 gsi_insert_before_without_update (&gsi, g,
3998 GSI_SAME_STMT);
3999 break;
4001 x = lang_hooks.decls.omp_clause_copy_ctor
4002 (c, unshare_expr (ivar), x);
4003 gimplify_and_add (x, &llist[0]);
4004 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4005 if (x)
4007 gimple_seq tseq = NULL;
4009 dtor = x;
4010 gimplify_stmt (&dtor, &tseq);
4011 gimple_seq_add_seq (&llist[1], tseq);
4013 break;
4016 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4017 gimplify_and_add (x, ilist);
4018 goto do_dtor;
4020 case OMP_CLAUSE__LOOPTEMP_:
4021 gcc_assert (is_parallel_ctx (ctx));
4022 x = build_outer_var_ref (var, ctx);
4023 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4024 gimplify_and_add (x, ilist);
4025 break;
4027 case OMP_CLAUSE_COPYIN:
4028 by_ref = use_pointer_for_field (var, NULL);
4029 x = build_receiver_ref (var, by_ref, ctx);
4030 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4031 append_to_statement_list (x, &copyin_seq);
4032 copyin_by_ref |= by_ref;
4033 break;
4035 case OMP_CLAUSE_REDUCTION:
4036 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4038 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4039 gimple tseq;
4040 x = build_outer_var_ref (var, ctx);
4042 if (is_reference (var)
4043 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4044 TREE_TYPE (x)))
4045 x = build_fold_addr_expr_loc (clause_loc, x);
4046 SET_DECL_VALUE_EXPR (placeholder, x);
4047 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4048 tree new_vard = new_var;
4049 if (is_reference (var))
4051 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4052 new_vard = TREE_OPERAND (new_var, 0);
4053 gcc_assert (DECL_P (new_vard));
4055 if (is_simd
4056 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4057 idx, lane, ivar, lvar))
4059 if (new_vard == new_var)
4061 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4062 SET_DECL_VALUE_EXPR (new_var, ivar);
4064 else
4066 SET_DECL_VALUE_EXPR (new_vard,
4067 build_fold_addr_expr (ivar));
4068 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4070 x = lang_hooks.decls.omp_clause_default_ctor
4071 (c, unshare_expr (ivar),
4072 build_outer_var_ref (var, ctx));
4073 if (x)
4074 gimplify_and_add (x, &llist[0]);
4075 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4077 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4078 lower_omp (&tseq, ctx);
4079 gimple_seq_add_seq (&llist[0], tseq);
4081 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4082 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4083 lower_omp (&tseq, ctx);
4084 gimple_seq_add_seq (&llist[1], tseq);
4085 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4086 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4087 if (new_vard == new_var)
4088 SET_DECL_VALUE_EXPR (new_var, lvar);
4089 else
4090 SET_DECL_VALUE_EXPR (new_vard,
4091 build_fold_addr_expr (lvar));
4092 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4093 if (x)
4095 tseq = NULL;
4096 dtor = x;
4097 gimplify_stmt (&dtor, &tseq);
4098 gimple_seq_add_seq (&llist[1], tseq);
4100 break;
4102 /* If this is a reference to constant size reduction var
4103 with placeholder, we haven't emitted the initializer
4104 for it because it is undesirable if SIMD arrays are used.
4105 But if they aren't used, we need to emit the deferred
4106 initialization now. */
4107 else if (is_reference (var) && is_simd)
4108 handle_simd_reference (clause_loc, new_vard, ilist);
4109 x = lang_hooks.decls.omp_clause_default_ctor
4110 (c, unshare_expr (new_var),
4111 build_outer_var_ref (var, ctx));
4112 if (x)
4113 gimplify_and_add (x, ilist);
4114 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4116 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4117 lower_omp (&tseq, ctx);
4118 gimple_seq_add_seq (ilist, tseq);
4120 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4121 if (is_simd)
4123 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4124 lower_omp (&tseq, ctx);
4125 gimple_seq_add_seq (dlist, tseq);
4126 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4128 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4129 goto do_dtor;
4131 else
4133 x = omp_reduction_init (c, TREE_TYPE (new_var));
4134 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4135 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4137 /* reduction(-:var) sums up the partial results, so it
4138 acts identically to reduction(+:var). */
4139 if (code == MINUS_EXPR)
4140 code = PLUS_EXPR;
4142 tree new_vard = new_var;
4143 if (is_simd && is_reference (var))
4145 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4146 new_vard = TREE_OPERAND (new_var, 0);
4147 gcc_assert (DECL_P (new_vard));
4149 if (is_simd
4150 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4151 idx, lane, ivar, lvar))
4153 tree ref = build_outer_var_ref (var, ctx);
4155 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4157 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4158 ref = build_outer_var_ref (var, ctx);
4159 gimplify_assign (ref, x, &llist[1]);
4161 if (new_vard != new_var)
4163 SET_DECL_VALUE_EXPR (new_vard,
4164 build_fold_addr_expr (lvar));
4165 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4168 else
4170 if (is_reference (var) && is_simd)
4171 handle_simd_reference (clause_loc, new_vard, ilist);
4172 gimplify_assign (new_var, x, ilist);
4173 if (is_simd)
4175 tree ref = build_outer_var_ref (var, ctx);
4177 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4178 ref = build_outer_var_ref (var, ctx);
4179 gimplify_assign (ref, x, dlist);
4183 break;
4185 default:
4186 gcc_unreachable ();
4191 if (lane)
4193 tree uid = create_tmp_var (ptr_type_node, "simduid");
4194 /* Don't want uninit warnings on simduid, it is always uninitialized,
4195 but we use it not for the value, but for the DECL_UID only. */
4196 TREE_NO_WARNING (uid) = 1;
4197 gimple g
4198 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4199 gimple_call_set_lhs (g, lane);
4200 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4201 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4202 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4203 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4204 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4205 gimple_omp_for_set_clauses (ctx->stmt, c);
4206 g = gimple_build_assign (lane, INTEGER_CST,
4207 build_int_cst (unsigned_type_node, 0));
4208 gimple_seq_add_stmt (ilist, g);
4209 for (int i = 0; i < 2; i++)
4210 if (llist[i])
4212 tree vf = create_tmp_var (unsigned_type_node);
4213 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4214 gimple_call_set_lhs (g, vf);
4215 gimple_seq *seq = i == 0 ? ilist : dlist;
4216 gimple_seq_add_stmt (seq, g);
4217 tree t = build_int_cst (unsigned_type_node, 0);
4218 g = gimple_build_assign (idx, INTEGER_CST, t);
4219 gimple_seq_add_stmt (seq, g);
4220 tree body = create_artificial_label (UNKNOWN_LOCATION);
4221 tree header = create_artificial_label (UNKNOWN_LOCATION);
4222 tree end = create_artificial_label (UNKNOWN_LOCATION);
4223 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4224 gimple_seq_add_stmt (seq, gimple_build_label (body));
4225 gimple_seq_add_seq (seq, llist[i]);
4226 t = build_int_cst (unsigned_type_node, 1);
4227 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4228 gimple_seq_add_stmt (seq, g);
4229 gimple_seq_add_stmt (seq, gimple_build_label (header));
4230 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4231 gimple_seq_add_stmt (seq, g);
4232 gimple_seq_add_stmt (seq, gimple_build_label (end));
4236 /* The copyin sequence is not to be executed by the main thread, since
4237 that would result in self-copies. Perhaps not visible to scalars,
4238 but it certainly is to C++ operator=. */
4239 if (copyin_seq)
4241 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4243 x = build2 (NE_EXPR, boolean_type_node, x,
4244 build_int_cst (TREE_TYPE (x), 0));
4245 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4246 gimplify_and_add (x, ilist);
4249 /* If any copyin variable is passed by reference, we must ensure the
4250 master thread doesn't modify it before it is copied over in all
4251 threads. Similarly for variables in both firstprivate and
4252 lastprivate clauses we need to ensure the lastprivate copying
4253 happens after firstprivate copying in all threads. And similarly
4254 for UDRs if initializer expression refers to omp_orig. */
4255 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4257 /* Don't add any barrier for #pragma omp simd or
4258 #pragma omp distribute. */
4259 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4260 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4261 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4264 /* If max_vf is non-zero, then we can use only a vectorization factor
4265 up to the max_vf we chose. So stick it into the safelen clause. */
4266 if (max_vf)
4268 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4269 OMP_CLAUSE_SAFELEN);
4270 if (c == NULL_TREE
4271 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4272 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4273 max_vf) == 1))
4275 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4276 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4277 max_vf);
4278 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4279 gimple_omp_for_set_clauses (ctx->stmt, c);
4285 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4286 both parallel and workshare constructs. PREDICATE may be NULL if it's
4287 always true. */
4289 static void
4290 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4291 omp_context *ctx)
4293 tree x, c, label = NULL, orig_clauses = clauses;
4294 bool par_clauses = false;
4295 tree simduid = NULL, lastlane = NULL;
4297 /* Early exit if there are no lastprivate or linear clauses. */
4298 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4299 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4300 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4301 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4302 break;
4303 if (clauses == NULL)
4305 /* If this was a workshare clause, see if it had been combined
4306 with its parallel. In that case, look for the clauses on the
4307 parallel statement itself. */
4308 if (is_parallel_ctx (ctx))
4309 return;
4311 ctx = ctx->outer;
4312 if (ctx == NULL || !is_parallel_ctx (ctx))
4313 return;
4315 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4316 OMP_CLAUSE_LASTPRIVATE);
4317 if (clauses == NULL)
4318 return;
4319 par_clauses = true;
4322 if (predicate)
4324 gcond *stmt;
4325 tree label_true, arm1, arm2;
4327 label = create_artificial_label (UNKNOWN_LOCATION);
4328 label_true = create_artificial_label (UNKNOWN_LOCATION);
4329 arm1 = TREE_OPERAND (predicate, 0);
4330 arm2 = TREE_OPERAND (predicate, 1);
4331 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4332 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4333 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4334 label_true, label);
4335 gimple_seq_add_stmt (stmt_list, stmt);
4336 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4339 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4340 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4342 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4343 if (simduid)
4344 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4347 for (c = clauses; c ;)
4349 tree var, new_var;
4350 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4352 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4353 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4354 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4356 var = OMP_CLAUSE_DECL (c);
4357 new_var = lookup_decl (var, ctx);
4359 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4361 tree val = DECL_VALUE_EXPR (new_var);
4362 if (TREE_CODE (val) == ARRAY_REF
4363 && VAR_P (TREE_OPERAND (val, 0))
4364 && lookup_attribute ("omp simd array",
4365 DECL_ATTRIBUTES (TREE_OPERAND (val,
4366 0))))
4368 if (lastlane == NULL)
4370 lastlane = create_tmp_var (unsigned_type_node);
4371 gcall *g
4372 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4373 2, simduid,
4374 TREE_OPERAND (val, 1));
4375 gimple_call_set_lhs (g, lastlane);
4376 gimple_seq_add_stmt (stmt_list, g);
4378 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4379 TREE_OPERAND (val, 0), lastlane,
4380 NULL_TREE, NULL_TREE);
4384 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4385 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4387 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4388 gimple_seq_add_seq (stmt_list,
4389 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4390 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4392 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4393 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4395 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4396 gimple_seq_add_seq (stmt_list,
4397 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4398 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4401 x = build_outer_var_ref (var, ctx);
4402 if (is_reference (var))
4403 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4404 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4405 gimplify_and_add (x, stmt_list);
4407 c = OMP_CLAUSE_CHAIN (c);
4408 if (c == NULL && !par_clauses)
4410 /* If this was a workshare clause, see if it had been combined
4411 with its parallel. In that case, continue looking for the
4412 clauses also on the parallel statement itself. */
4413 if (is_parallel_ctx (ctx))
4414 break;
4416 ctx = ctx->outer;
4417 if (ctx == NULL || !is_parallel_ctx (ctx))
4418 break;
4420 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4421 OMP_CLAUSE_LASTPRIVATE);
4422 par_clauses = true;
4426 if (label)
4427 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4430 static void
4431 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4432 tree tid, tree var, tree new_var)
4434 /* The atomic add at the end of the sum creates unnecessary
4435 write contention on accelerators. To work around this,
4436 create an array to store the partial reductions. Later, in
4437 lower_omp_for (for openacc), the values of array will be
4438 combined. */
4440 tree t = NULL_TREE, array, x;
4441 tree type = get_base_type (var);
4442 gimple stmt;
4444 /* Now insert the partial reductions into the array. */
4446 /* Find the reduction array. */
4448 tree ptype = build_pointer_type (type);
4450 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4451 t = build_receiver_ref (t, false, ctx->outer);
4453 array = create_tmp_var (ptype);
4454 gimplify_assign (array, t, stmt_seqp);
4456 tree ptr = create_tmp_var (TREE_TYPE (array));
4458 /* Find the reduction array. */
4460 /* testing a unary conversion. */
4461 tree offset = create_tmp_var (sizetype);
4462 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4463 stmt_seqp);
4464 t = create_tmp_var (sizetype);
4465 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4466 stmt_seqp);
4467 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4468 gimple_seq_add_stmt (stmt_seqp, stmt);
4470 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4471 of adding sizeof(var) to the array? */
4472 ptr = create_tmp_var (ptype);
4473 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4474 offset);
4475 gimple_seq_add_stmt (stmt_seqp, stmt);
4477 /* Move the local sum to gfc$sum[i]. */
4478 x = unshare_expr (build_simple_mem_ref (ptr));
4479 stmt = gimplify_assign (x, new_var, stmt_seqp);
4482 /* Generate code to implement the REDUCTION clauses. */
4484 static void
4485 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4487 gimple_seq sub_seq = NULL;
4488 gimple stmt;
4489 tree x, c, tid = NULL_TREE;
4490 int count = 0;
4492 /* SIMD reductions are handled in lower_rec_input_clauses. */
4493 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4494 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4495 return;
4497 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4498 update in that case, otherwise use a lock. */
4499 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4500 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4502 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4504 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4505 count = -1;
4506 break;
4508 count++;
4511 if (count == 0)
4512 return;
4514 /* Initialize thread info for OpenACC. */
4515 if (is_gimple_omp_oacc_specifically (ctx->stmt))
4517 /* Get the current thread id. */
4518 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4519 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4520 gimple stmt = gimple_build_call (call, 0);
4521 gimple_call_set_lhs (stmt, tid);
4522 gimple_seq_add_stmt (stmt_seqp, stmt);
4525 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4527 tree var, ref, new_var;
4528 enum tree_code code;
4529 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4531 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4532 continue;
4534 var = OMP_CLAUSE_DECL (c);
4535 new_var = lookup_decl (var, ctx);
4536 if (is_reference (var))
4537 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4538 ref = build_outer_var_ref (var, ctx);
4539 code = OMP_CLAUSE_REDUCTION_CODE (c);
4541 /* reduction(-:var) sums up the partial results, so it acts
4542 identically to reduction(+:var). */
4543 if (code == MINUS_EXPR)
4544 code = PLUS_EXPR;
4546 if (count == 1)
4548 if (!is_gimple_omp_oacc_specifically (ctx->stmt))
4550 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4552 addr = save_expr (addr);
4553 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4554 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4555 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4556 gimplify_and_add (x, stmt_seqp);
4557 return;
4559 else
4561 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var,
4562 new_var);
4563 return;
4567 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4569 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4571 if (is_reference (var)
4572 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4573 TREE_TYPE (ref)))
4574 ref = build_fold_addr_expr_loc (clause_loc, ref);
4575 SET_DECL_VALUE_EXPR (placeholder, ref);
4576 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4577 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4578 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4579 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4580 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4582 else
4584 if (is_gimple_omp_oacc_specifically (ctx->stmt))
4586 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var,
4587 new_var);
4589 else
4591 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4592 ref = build_outer_var_ref (var, ctx);
4593 gimplify_assign (ref, x, &sub_seq);
4598 if (is_gimple_omp_oacc_specifically (ctx->stmt))
4599 return;
4601 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4603 gimple_seq_add_stmt (stmt_seqp, stmt);
4605 gimple_seq_add_seq (stmt_seqp, sub_seq);
4607 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4609 gimple_seq_add_stmt (stmt_seqp, stmt);
4613 /* Generate code to implement the COPYPRIVATE clauses. */
4615 static void
4616 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4617 omp_context *ctx)
4619 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
4621 tree c;
4623 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4625 tree var, new_var, ref, x;
4626 bool by_ref;
4627 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4629 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4630 continue;
4632 var = OMP_CLAUSE_DECL (c);
4633 by_ref = use_pointer_for_field (var, NULL);
4635 ref = build_sender_ref (var, ctx);
4636 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4637 if (by_ref)
4639 x = build_fold_addr_expr_loc (clause_loc, new_var);
4640 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4642 gimplify_assign (ref, x, slist);
4644 ref = build_receiver_ref (var, false, ctx);
4645 if (by_ref)
4647 ref = fold_convert_loc (clause_loc,
4648 build_pointer_type (TREE_TYPE (new_var)),
4649 ref);
4650 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4652 if (is_reference (var))
4654 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4655 ref = build_simple_mem_ref_loc (clause_loc, ref);
4656 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4658 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4659 gimplify_and_add (x, rlist);
4664 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4665 and REDUCTION from the sender (aka parent) side. */
4667 static void
4668 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4669 omp_context *ctx)
4671 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
4673 tree c;
4675 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4677 tree val, ref, x, var;
4678 bool by_ref, do_in = false, do_out = false;
4679 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4681 switch (OMP_CLAUSE_CODE (c))
4683 case OMP_CLAUSE_PRIVATE:
4684 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4685 break;
4686 continue;
4687 case OMP_CLAUSE_FIRSTPRIVATE:
4688 case OMP_CLAUSE_COPYIN:
4689 case OMP_CLAUSE_LASTPRIVATE:
4690 case OMP_CLAUSE_REDUCTION:
4691 case OMP_CLAUSE__LOOPTEMP_:
4692 break;
4693 default:
4694 continue;
4697 val = OMP_CLAUSE_DECL (c);
4698 var = lookup_decl_in_outer_ctx (val, ctx);
4700 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4701 && is_global_var (var))
4702 continue;
4703 if (is_variable_sized (val))
4704 continue;
4705 by_ref = use_pointer_for_field (val, NULL);
4707 switch (OMP_CLAUSE_CODE (c))
4709 case OMP_CLAUSE_PRIVATE:
4710 case OMP_CLAUSE_FIRSTPRIVATE:
4711 case OMP_CLAUSE_COPYIN:
4712 case OMP_CLAUSE__LOOPTEMP_:
4713 do_in = true;
4714 break;
4716 case OMP_CLAUSE_LASTPRIVATE:
4717 if (by_ref || is_reference (val))
4719 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4720 continue;
4721 do_in = true;
4723 else
4725 do_out = true;
4726 if (lang_hooks.decls.omp_private_outer_ref (val))
4727 do_in = true;
4729 break;
4731 case OMP_CLAUSE_REDUCTION:
4732 do_in = true;
4733 do_out = !(by_ref || is_reference (val));
4734 break;
4736 default:
4737 gcc_unreachable ();
4740 if (do_in)
4742 ref = build_sender_ref (val, ctx);
4743 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4744 gimplify_assign (ref, x, ilist);
4745 if (is_task_ctx (ctx))
4746 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4749 if (do_out)
4751 ref = build_sender_ref (val, ctx);
4752 gimplify_assign (var, ref, olist);
4757 /* Generate code to implement SHARED from the sender (aka parent)
4758 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4759 list things that got automatically shared. */
4761 static void
4762 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4764 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
4766 tree var, ovar, nvar, f, x, record_type;
4768 if (ctx->record_type == NULL)
4769 return;
4771 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4772 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4774 ovar = DECL_ABSTRACT_ORIGIN (f);
4775 nvar = maybe_lookup_decl (ovar, ctx);
4776 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4777 continue;
4779 /* If CTX is a nested parallel directive. Find the immediately
4780 enclosing parallel or workshare construct that contains a
4781 mapping for OVAR. */
4782 var = lookup_decl_in_outer_ctx (ovar, ctx);
4784 if (use_pointer_for_field (ovar, ctx))
4786 x = build_sender_ref (ovar, ctx);
4787 var = build_fold_addr_expr (var);
4788 gimplify_assign (x, var, ilist);
4790 else
4792 x = build_sender_ref (ovar, ctx);
4793 gimplify_assign (x, var, ilist);
4795 if (!TREE_READONLY (var)
4796 /* We don't need to receive a new reference to a result
4797 or parm decl. In fact we may not store to it as we will
4798 invalidate any pending RSO and generate wrong gimple
4799 during inlining. */
4800 && !((TREE_CODE (var) == RESULT_DECL
4801 || TREE_CODE (var) == PARM_DECL)
4802 && DECL_BY_REFERENCE (var)))
4804 x = build_sender_ref (ovar, ctx);
4805 gimplify_assign (var, x, olist);
4812 /* A convenience function to build an empty GIMPLE_COND with just the
4813 condition. */
4815 static gcond *
4816 gimple_build_cond_empty (tree cond)
4818 enum tree_code pred_code;
4819 tree lhs, rhs;
4821 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4822 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4826 /* Build the function calls to GOMP_parallel_start etc to actually
4827 generate the parallel operation. REGION is the parallel region
4828 being expanded. BB is the block where to insert the code. WS_ARGS
4829 will be set if this is a call to a combined parallel+workshare
4830 construct, it contains the list of additional arguments needed by
4831 the workshare construct. */
4833 static void
4834 expand_parallel_call (struct omp_region *region, basic_block bb,
4835 gomp_parallel *entry_stmt,
4836 vec<tree, va_gc> *ws_args)
4838 tree t, t1, t2, val, cond, c, clauses, flags;
4839 gimple_stmt_iterator gsi;
4840 gimple stmt;
4841 enum built_in_function start_ix;
4842 int start_ix2;
4843 location_t clause_loc;
4844 vec<tree, va_gc> *args;
4846 clauses = gimple_omp_parallel_clauses (entry_stmt);
4848 /* Determine what flavor of GOMP_parallel we will be
4849 emitting. */
4850 start_ix = BUILT_IN_GOMP_PARALLEL;
4851 if (is_combined_parallel (region))
4853 switch (region->inner->type)
4855 case GIMPLE_OMP_FOR:
4856 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4857 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4858 + (region->inner->sched_kind
4859 == OMP_CLAUSE_SCHEDULE_RUNTIME
4860 ? 3 : region->inner->sched_kind));
4861 start_ix = (enum built_in_function)start_ix2;
4862 break;
4863 case GIMPLE_OMP_SECTIONS:
4864 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4865 break;
4866 default:
4867 gcc_unreachable ();
4871 /* By default, the value of NUM_THREADS is zero (selected at run time)
4872 and there is no conditional. */
4873 cond = NULL_TREE;
4874 val = build_int_cst (unsigned_type_node, 0);
4875 flags = build_int_cst (unsigned_type_node, 0);
4877 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4878 if (c)
4879 cond = OMP_CLAUSE_IF_EXPR (c);
4881 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4882 if (c)
4884 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4885 clause_loc = OMP_CLAUSE_LOCATION (c);
4887 else
4888 clause_loc = gimple_location (entry_stmt);
4890 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4891 if (c)
4892 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4894 /* Ensure 'val' is of the correct type. */
4895 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4897 /* If we found the clause 'if (cond)', build either
4898 (cond != 0) or (cond ? val : 1u). */
4899 if (cond)
4901 cond = gimple_boolify (cond);
4903 if (integer_zerop (val))
4904 val = fold_build2_loc (clause_loc,
4905 EQ_EXPR, unsigned_type_node, cond,
4906 build_int_cst (TREE_TYPE (cond), 0));
4907 else
4909 basic_block cond_bb, then_bb, else_bb;
4910 edge e, e_then, e_else;
4911 tree tmp_then, tmp_else, tmp_join, tmp_var;
4913 tmp_var = create_tmp_var (TREE_TYPE (val));
4914 if (gimple_in_ssa_p (cfun))
4916 tmp_then = make_ssa_name (tmp_var);
4917 tmp_else = make_ssa_name (tmp_var);
4918 tmp_join = make_ssa_name (tmp_var);
4920 else
4922 tmp_then = tmp_var;
4923 tmp_else = tmp_var;
4924 tmp_join = tmp_var;
4927 e = split_block (bb, NULL);
4928 cond_bb = e->src;
4929 bb = e->dest;
4930 remove_edge (e);
4932 then_bb = create_empty_bb (cond_bb);
4933 else_bb = create_empty_bb (then_bb);
4934 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4935 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4937 stmt = gimple_build_cond_empty (cond);
4938 gsi = gsi_start_bb (cond_bb);
4939 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4941 gsi = gsi_start_bb (then_bb);
4942 stmt = gimple_build_assign (tmp_then, val);
4943 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4945 gsi = gsi_start_bb (else_bb);
4946 stmt = gimple_build_assign
4947 (tmp_else, build_int_cst (unsigned_type_node, 1));
4948 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4950 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4951 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4952 add_bb_to_loop (then_bb, cond_bb->loop_father);
4953 add_bb_to_loop (else_bb, cond_bb->loop_father);
4954 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4955 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4957 if (gimple_in_ssa_p (cfun))
4959 gphi *phi = create_phi_node (tmp_join, bb);
4960 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4961 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4964 val = tmp_join;
4967 gsi = gsi_start_bb (bb);
4968 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4969 false, GSI_CONTINUE_LINKING);
4972 gsi = gsi_last_bb (bb);
4973 t = gimple_omp_parallel_data_arg (entry_stmt);
4974 if (t == NULL)
4975 t1 = null_pointer_node;
4976 else
4977 t1 = build_fold_addr_expr (t);
4978 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4980 vec_alloc (args, 4 + vec_safe_length (ws_args));
4981 args->quick_push (t2);
4982 args->quick_push (t1);
4983 args->quick_push (val);
4984 if (ws_args)
4985 args->splice (*ws_args);
4986 args->quick_push (flags);
4988 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4989 builtin_decl_explicit (start_ix), args);
4991 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4992 false, GSI_CONTINUE_LINKING);
4995 /* Insert a function call whose name is FUNC_NAME with the information from
4996 ENTRY_STMT into the basic_block BB. */
4998 static void
4999 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
5000 vec <tree, va_gc> *ws_args)
5002 tree t, t1, t2;
5003 gimple_stmt_iterator gsi;
5004 vec <tree, va_gc> *args;
5006 gcc_assert (vec_safe_length (ws_args) == 2);
5007 tree func_name = (*ws_args)[0];
5008 tree grain = (*ws_args)[1];
5010 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5011 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5012 gcc_assert (count != NULL_TREE);
5013 count = OMP_CLAUSE_OPERAND (count, 0);
5015 gsi = gsi_last_bb (bb);
5016 t = gimple_omp_parallel_data_arg (entry_stmt);
5017 if (t == NULL)
5018 t1 = null_pointer_node;
5019 else
5020 t1 = build_fold_addr_expr (t);
5021 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5023 vec_alloc (args, 4);
5024 args->quick_push (t2);
5025 args->quick_push (t1);
5026 args->quick_push (count);
5027 args->quick_push (grain);
5028 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5030 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5031 GSI_CONTINUE_LINKING);
5034 /* Build the function call to GOMP_task to actually
5035 generate the task operation. BB is the block where to insert the code. */
5037 static void
5038 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5040 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5041 gimple_stmt_iterator gsi;
5042 location_t loc = gimple_location (entry_stmt);
5044 clauses = gimple_omp_task_clauses (entry_stmt);
5046 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5047 if (c)
5048 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5049 else
5050 cond = boolean_true_node;
5052 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5053 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5054 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5055 flags = build_int_cst (unsigned_type_node,
5056 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5058 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5059 if (c)
5061 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5062 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5063 build_int_cst (unsigned_type_node, 2),
5064 build_int_cst (unsigned_type_node, 0));
5065 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5067 if (depend)
5068 depend = OMP_CLAUSE_DECL (depend);
5069 else
5070 depend = build_int_cst (ptr_type_node, 0);
5072 gsi = gsi_last_bb (bb);
5073 t = gimple_omp_task_data_arg (entry_stmt);
5074 if (t == NULL)
5075 t2 = null_pointer_node;
5076 else
5077 t2 = build_fold_addr_expr_loc (loc, t);
5078 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5079 t = gimple_omp_task_copy_fn (entry_stmt);
5080 if (t == NULL)
5081 t3 = null_pointer_node;
5082 else
5083 t3 = build_fold_addr_expr_loc (loc, t);
5085 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5086 8, t1, t2, t3,
5087 gimple_omp_task_arg_size (entry_stmt),
5088 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5089 depend);
5091 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5092 false, GSI_CONTINUE_LINKING);
5096 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5097 catch handler and return it. This prevents programs from violating the
5098 structured block semantics with throws. */
5100 static gimple_seq
5101 maybe_catch_exception (gimple_seq body)
5103 gimple g;
5104 tree decl;
5106 if (!flag_exceptions)
5107 return body;
5109 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5110 decl = lang_hooks.eh_protect_cleanup_actions ();
5111 else
5112 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5114 g = gimple_build_eh_must_not_throw (decl);
5115 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5116 GIMPLE_TRY_CATCH);
5118 return gimple_seq_alloc_with_stmt (g);
5121 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5123 static tree
5124 vec2chain (vec<tree, va_gc> *v)
5126 tree chain = NULL_TREE, t;
5127 unsigned ix;
5129 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5131 DECL_CHAIN (t) = chain;
5132 chain = t;
5135 return chain;
5139 /* Remove barriers in REGION->EXIT's block. Note that this is only
5140 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5141 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5142 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5143 removed. */
5145 static void
5146 remove_exit_barrier (struct omp_region *region)
5148 gimple_stmt_iterator gsi;
5149 basic_block exit_bb;
5150 edge_iterator ei;
5151 edge e;
5152 gimple stmt;
5153 int any_addressable_vars = -1;
5155 exit_bb = region->exit;
5157 /* If the parallel region doesn't return, we don't have REGION->EXIT
5158 block at all. */
5159 if (! exit_bb)
5160 return;
5162 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5163 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5164 statements that can appear in between are extremely limited -- no
5165 memory operations at all. Here, we allow nothing at all, so the
5166 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5167 gsi = gsi_last_bb (exit_bb);
5168 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5169 gsi_prev (&gsi);
5170 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5171 return;
5173 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5175 gsi = gsi_last_bb (e->src);
5176 if (gsi_end_p (gsi))
5177 continue;
5178 stmt = gsi_stmt (gsi);
5179 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5180 && !gimple_omp_return_nowait_p (stmt))
5182 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5183 in many cases. If there could be tasks queued, the barrier
5184 might be needed to let the tasks run before some local
5185 variable of the parallel that the task uses as shared
5186 runs out of scope. The task can be spawned either
5187 from within current function (this would be easy to check)
5188 or from some function it calls and gets passed an address
5189 of such a variable. */
5190 if (any_addressable_vars < 0)
5192 gomp_parallel *parallel_stmt
5193 = as_a <gomp_parallel *> (last_stmt (region->entry));
5194 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5195 tree local_decls, block, decl;
5196 unsigned ix;
5198 any_addressable_vars = 0;
5199 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5200 if (TREE_ADDRESSABLE (decl))
5202 any_addressable_vars = 1;
5203 break;
5205 for (block = gimple_block (stmt);
5206 !any_addressable_vars
5207 && block
5208 && TREE_CODE (block) == BLOCK;
5209 block = BLOCK_SUPERCONTEXT (block))
5211 for (local_decls = BLOCK_VARS (block);
5212 local_decls;
5213 local_decls = DECL_CHAIN (local_decls))
5214 if (TREE_ADDRESSABLE (local_decls))
5216 any_addressable_vars = 1;
5217 break;
5219 if (block == gimple_block (parallel_stmt))
5220 break;
5223 if (!any_addressable_vars)
5224 gimple_omp_return_set_nowait (stmt);
5229 static void
5230 remove_exit_barriers (struct omp_region *region)
5232 if (region->type == GIMPLE_OMP_PARALLEL)
5233 remove_exit_barrier (region);
5235 if (region->inner)
5237 region = region->inner;
5238 remove_exit_barriers (region);
5239 while (region->next)
5241 region = region->next;
5242 remove_exit_barriers (region);
5247 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5248 calls. These can't be declared as const functions, but
5249 within one parallel body they are constant, so they can be
5250 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5251 which are declared const. Similarly for task body, except
5252 that in untied task omp_get_thread_num () can change at any task
5253 scheduling point. */
5255 static void
5256 optimize_omp_library_calls (gimple entry_stmt)
5258 basic_block bb;
5259 gimple_stmt_iterator gsi;
5260 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5261 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5262 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5263 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5264 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5265 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5266 OMP_CLAUSE_UNTIED) != NULL);
5268 FOR_EACH_BB_FN (bb, cfun)
5269 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5271 gimple call = gsi_stmt (gsi);
5272 tree decl;
5274 if (is_gimple_call (call)
5275 && (decl = gimple_call_fndecl (call))
5276 && DECL_EXTERNAL (decl)
5277 && TREE_PUBLIC (decl)
5278 && DECL_INITIAL (decl) == NULL)
5280 tree built_in;
5282 if (DECL_NAME (decl) == thr_num_id)
5284 /* In #pragma omp task untied omp_get_thread_num () can change
5285 during the execution of the task region. */
5286 if (untied_task)
5287 continue;
5288 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5290 else if (DECL_NAME (decl) == num_thr_id)
5291 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5292 else
5293 continue;
5295 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5296 || gimple_call_num_args (call) != 0)
5297 continue;
5299 if (flag_exceptions && !TREE_NOTHROW (decl))
5300 continue;
5302 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5303 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5304 TREE_TYPE (TREE_TYPE (built_in))))
5305 continue;
5307 gimple_call_set_fndecl (call, built_in);
5312 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5313 regimplified. */
5315 static tree
5316 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5318 tree t = *tp;
5320 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5321 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5322 return t;
5324 if (TREE_CODE (t) == ADDR_EXPR)
5325 recompute_tree_invariant_for_addr_expr (t);
5327 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5328 return NULL_TREE;
5331 /* Prepend TO = FROM assignment before *GSI_P. */
5333 static void
5334 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5336 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5337 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5338 true, GSI_SAME_STMT);
5339 gimple stmt = gimple_build_assign (to, from);
5340 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5341 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5342 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5344 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5345 gimple_regimplify_operands (stmt, &gsi);
5349 /* Expand the OpenMP parallel or task directive starting at REGION. */
5351 static void
5352 expand_omp_taskreg (struct omp_region *region)
5354 basic_block entry_bb, exit_bb, new_bb;
5355 struct function *child_cfun;
5356 tree child_fn, block, t;
5357 gimple_stmt_iterator gsi;
5358 gimple entry_stmt, stmt;
5359 edge e;
5360 vec<tree, va_gc> *ws_args;
5362 entry_stmt = last_stmt (region->entry);
5363 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5364 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5366 entry_bb = region->entry;
5367 exit_bb = region->exit;
5369 bool is_cilk_for
5370 = (flag_cilkplus
5371 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5372 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5373 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5375 if (is_cilk_for)
5376 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5377 and the inner statement contains the name of the built-in function
5378 and grain. */
5379 ws_args = region->inner->ws_args;
5380 else if (is_combined_parallel (region))
5381 ws_args = region->ws_args;
5382 else
5383 ws_args = NULL;
5385 if (child_cfun->cfg)
5387 /* Due to inlining, it may happen that we have already outlined
5388 the region, in which case all we need to do is make the
5389 sub-graph unreachable and emit the parallel call. */
5390 edge entry_succ_e, exit_succ_e;
5392 entry_succ_e = single_succ_edge (entry_bb);
5394 gsi = gsi_last_bb (entry_bb);
5395 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5396 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5397 gsi_remove (&gsi, true);
5399 new_bb = entry_bb;
5400 if (exit_bb)
5402 exit_succ_e = single_succ_edge (exit_bb);
5403 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5405 remove_edge_and_dominated_blocks (entry_succ_e);
5407 else
5409 unsigned srcidx, dstidx, num;
5411 /* If the parallel region needs data sent from the parent
5412 function, then the very first statement (except possible
5413 tree profile counter updates) of the parallel body
5414 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5415 &.OMP_DATA_O is passed as an argument to the child function,
5416 we need to replace it with the argument as seen by the child
5417 function.
5419 In most cases, this will end up being the identity assignment
5420 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5421 a function call that has been inlined, the original PARM_DECL
5422 .OMP_DATA_I may have been converted into a different local
5423 variable. In which case, we need to keep the assignment. */
5424 if (gimple_omp_taskreg_data_arg (entry_stmt))
5426 basic_block entry_succ_bb = single_succ (entry_bb);
5427 tree arg, narg;
5428 gimple parcopy_stmt = NULL;
5430 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5432 gimple stmt;
5434 gcc_assert (!gsi_end_p (gsi));
5435 stmt = gsi_stmt (gsi);
5436 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5437 continue;
5439 if (gimple_num_ops (stmt) == 2)
5441 tree arg = gimple_assign_rhs1 (stmt);
5443 /* We're ignore the subcode because we're
5444 effectively doing a STRIP_NOPS. */
5446 if (TREE_CODE (arg) == ADDR_EXPR
5447 && TREE_OPERAND (arg, 0)
5448 == gimple_omp_taskreg_data_arg (entry_stmt))
5450 parcopy_stmt = stmt;
5451 break;
5456 gcc_assert (parcopy_stmt != NULL);
5457 arg = DECL_ARGUMENTS (child_fn);
5459 if (!gimple_in_ssa_p (cfun))
5461 if (gimple_assign_lhs (parcopy_stmt) == arg)
5462 gsi_remove (&gsi, true);
5463 else
5465 /* ?? Is setting the subcode really necessary ?? */
5466 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5467 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5470 else
5472 /* If we are in ssa form, we must load the value from the default
5473 definition of the argument. That should not be defined now,
5474 since the argument is not used uninitialized. */
5475 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5476 narg = make_ssa_name (arg, gimple_build_nop ());
5477 set_ssa_default_def (cfun, arg, narg);
5478 /* ?? Is setting the subcode really necessary ?? */
5479 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5480 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5481 update_stmt (parcopy_stmt);
5485 /* Declare local variables needed in CHILD_CFUN. */
5486 block = DECL_INITIAL (child_fn);
5487 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5488 /* The gimplifier could record temporaries in parallel/task block
5489 rather than in containing function's local_decls chain,
5490 which would mean cgraph missed finalizing them. Do it now. */
5491 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5492 if (TREE_CODE (t) == VAR_DECL
5493 && TREE_STATIC (t)
5494 && !DECL_EXTERNAL (t))
5495 varpool_node::finalize_decl (t);
5496 DECL_SAVED_TREE (child_fn) = NULL;
5497 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5498 gimple_set_body (child_fn, NULL);
5499 TREE_USED (block) = 1;
5501 /* Reset DECL_CONTEXT on function arguments. */
5502 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5503 DECL_CONTEXT (t) = child_fn;
5505 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5506 so that it can be moved to the child function. */
5507 gsi = gsi_last_bb (entry_bb);
5508 stmt = gsi_stmt (gsi);
5509 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5510 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5511 gsi_remove (&gsi, true);
5512 e = split_block (entry_bb, stmt);
5513 entry_bb = e->dest;
5514 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5516 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5517 if (exit_bb)
5519 gsi = gsi_last_bb (exit_bb);
5520 gcc_assert (!gsi_end_p (gsi)
5521 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5522 stmt = gimple_build_return (NULL);
5523 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5524 gsi_remove (&gsi, true);
5527 /* Move the parallel region into CHILD_CFUN. */
5529 if (gimple_in_ssa_p (cfun))
5531 init_tree_ssa (child_cfun);
5532 init_ssa_operands (child_cfun);
5533 child_cfun->gimple_df->in_ssa_p = true;
5534 block = NULL_TREE;
5536 else
5537 block = gimple_block (entry_stmt);
5539 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5540 if (exit_bb)
5541 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5542 /* When the OMP expansion process cannot guarantee an up-to-date
5543 loop tree arrange for the child function to fixup loops. */
5544 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5545 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5547 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5548 num = vec_safe_length (child_cfun->local_decls);
5549 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5551 t = (*child_cfun->local_decls)[srcidx];
5552 if (DECL_CONTEXT (t) == cfun->decl)
5553 continue;
5554 if (srcidx != dstidx)
5555 (*child_cfun->local_decls)[dstidx] = t;
5556 dstidx++;
5558 if (dstidx != num)
5559 vec_safe_truncate (child_cfun->local_decls, dstidx);
5561 /* Inform the callgraph about the new function. */
5562 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5563 cgraph_node::add_new_function (child_fn, true);
5565 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5566 fixed in a following pass. */
5567 push_cfun (child_cfun);
5568 if (optimize)
5569 optimize_omp_library_calls (entry_stmt);
5570 cgraph_edge::rebuild_edges ();
5572 /* Some EH regions might become dead, see PR34608. If
5573 pass_cleanup_cfg isn't the first pass to happen with the
5574 new child, these dead EH edges might cause problems.
5575 Clean them up now. */
5576 if (flag_exceptions)
5578 basic_block bb;
5579 bool changed = false;
5581 FOR_EACH_BB_FN (bb, cfun)
5582 changed |= gimple_purge_dead_eh_edges (bb);
5583 if (changed)
5584 cleanup_tree_cfg ();
5586 if (gimple_in_ssa_p (cfun))
5587 update_ssa (TODO_update_ssa);
5588 pop_cfun ();
5591 /* Emit a library call to launch the children threads. */
5592 if (is_cilk_for)
5593 expand_cilk_for_call (new_bb,
5594 as_a <gomp_parallel *> (entry_stmt), ws_args);
5595 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5596 expand_parallel_call (region, new_bb,
5597 as_a <gomp_parallel *> (entry_stmt), ws_args);
5598 else
5599 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5600 if (gimple_in_ssa_p (cfun))
5601 update_ssa (TODO_update_ssa_only_virtuals);
5605 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5606 of the combined collapse > 1 loop constructs, generate code like:
5607 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5608 if (cond3 is <)
5609 adj = STEP3 - 1;
5610 else
5611 adj = STEP3 + 1;
5612 count3 = (adj + N32 - N31) / STEP3;
5613 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5614 if (cond2 is <)
5615 adj = STEP2 - 1;
5616 else
5617 adj = STEP2 + 1;
5618 count2 = (adj + N22 - N21) / STEP2;
5619 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5620 if (cond1 is <)
5621 adj = STEP1 - 1;
5622 else
5623 adj = STEP1 + 1;
5624 count1 = (adj + N12 - N11) / STEP1;
5625 count = count1 * count2 * count3;
5626 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5627 count = 0;
5628 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5629 of the combined loop constructs, just initialize COUNTS array
5630 from the _looptemp_ clauses. */
5632 /* NOTE: It *could* be better to moosh all of the BBs together,
5633 creating one larger BB with all the computation and the unexpected
5634 jump at the end. I.e.
5636 bool zero3, zero2, zero1, zero;
5638 zero3 = N32 c3 N31;
5639 count3 = (N32 - N31) /[cl] STEP3;
5640 zero2 = N22 c2 N21;
5641 count2 = (N22 - N21) /[cl] STEP2;
5642 zero1 = N12 c1 N11;
5643 count1 = (N12 - N11) /[cl] STEP1;
5644 zero = zero3 || zero2 || zero1;
5645 count = count1 * count2 * count3;
5646 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5648 After all, we expect the zero=false, and thus we expect to have to
5649 evaluate all of the comparison expressions, so short-circuiting
5650 oughtn't be a win. Since the condition isn't protecting a
5651 denominator, we're not concerned about divide-by-zero, so we can
5652 fully evaluate count even if a numerator turned out to be wrong.
5654 It seems like putting this all together would create much better
5655 scheduling opportunities, and less pressure on the chip's branch
5656 predictor. */
5658 static void
5659 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5660 basic_block &entry_bb, tree *counts,
5661 basic_block &zero_iter_bb, int &first_zero_iter,
5662 basic_block &l2_dom_bb)
5664 tree t, type = TREE_TYPE (fd->loop.v);
5665 edge e, ne;
5666 int i;
5668 /* Collapsed loops need work for expansion into SSA form. */
5669 gcc_assert (!gimple_in_ssa_p (cfun));
5671 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5672 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5674 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5675 isn't supposed to be handled, as the inner loop doesn't
5676 use it. */
5677 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5678 OMP_CLAUSE__LOOPTEMP_);
5679 gcc_assert (innerc);
5680 for (i = 0; i < fd->collapse; i++)
5682 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5683 OMP_CLAUSE__LOOPTEMP_);
5684 gcc_assert (innerc);
5685 if (i)
5686 counts[i] = OMP_CLAUSE_DECL (innerc);
5687 else
5688 counts[0] = NULL_TREE;
5690 return;
5693 for (i = 0; i < fd->collapse; i++)
5695 tree itype = TREE_TYPE (fd->loops[i].v);
5697 if (SSA_VAR_P (fd->loop.n2)
5698 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5699 fold_convert (itype, fd->loops[i].n1),
5700 fold_convert (itype, fd->loops[i].n2)))
5701 == NULL_TREE || !integer_onep (t)))
5703 gcond *cond_stmt;
5704 tree n1, n2;
5705 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5706 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5707 true, GSI_SAME_STMT);
5708 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5709 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5710 true, GSI_SAME_STMT);
5711 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5712 NULL_TREE, NULL_TREE);
5713 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5714 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5715 expand_omp_regimplify_p, NULL, NULL)
5716 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5717 expand_omp_regimplify_p, NULL, NULL))
5719 *gsi = gsi_for_stmt (cond_stmt);
5720 gimple_regimplify_operands (cond_stmt, gsi);
5722 e = split_block (entry_bb, cond_stmt);
5723 if (zero_iter_bb == NULL)
5725 gassign *assign_stmt;
5726 first_zero_iter = i;
5727 zero_iter_bb = create_empty_bb (entry_bb);
5728 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5729 *gsi = gsi_after_labels (zero_iter_bb);
5730 assign_stmt = gimple_build_assign (fd->loop.n2,
5731 build_zero_cst (type));
5732 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5733 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5734 entry_bb);
5736 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5737 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5738 e->flags = EDGE_TRUE_VALUE;
5739 e->probability = REG_BR_PROB_BASE - ne->probability;
5740 if (l2_dom_bb == NULL)
5741 l2_dom_bb = entry_bb;
5742 entry_bb = e->dest;
5743 *gsi = gsi_last_bb (entry_bb);
5746 if (POINTER_TYPE_P (itype))
5747 itype = signed_type_for (itype);
5748 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5749 ? -1 : 1));
5750 t = fold_build2 (PLUS_EXPR, itype,
5751 fold_convert (itype, fd->loops[i].step), t);
5752 t = fold_build2 (PLUS_EXPR, itype, t,
5753 fold_convert (itype, fd->loops[i].n2));
5754 t = fold_build2 (MINUS_EXPR, itype, t,
5755 fold_convert (itype, fd->loops[i].n1));
5756 /* ?? We could probably use CEIL_DIV_EXPR instead of
5757 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5758 generate the same code in the end because generically we
5759 don't know that the values involved must be negative for
5760 GT?? */
5761 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5762 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5763 fold_build1 (NEGATE_EXPR, itype, t),
5764 fold_build1 (NEGATE_EXPR, itype,
5765 fold_convert (itype,
5766 fd->loops[i].step)));
5767 else
5768 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5769 fold_convert (itype, fd->loops[i].step));
5770 t = fold_convert (type, t);
5771 if (TREE_CODE (t) == INTEGER_CST)
5772 counts[i] = t;
5773 else
5775 counts[i] = create_tmp_reg (type, ".count");
5776 expand_omp_build_assign (gsi, counts[i], t);
5778 if (SSA_VAR_P (fd->loop.n2))
5780 if (i == 0)
5781 t = counts[0];
5782 else
5783 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5784 expand_omp_build_assign (gsi, fd->loop.n2, t);
5790 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5791 T = V;
5792 V3 = N31 + (T % count3) * STEP3;
5793 T = T / count3;
5794 V2 = N21 + (T % count2) * STEP2;
5795 T = T / count2;
5796 V1 = N11 + T * STEP1;
5797 if this loop doesn't have an inner loop construct combined with it.
5798 If it does have an inner loop construct combined with it and the
5799 iteration count isn't known constant, store values from counts array
5800 into its _looptemp_ temporaries instead. */
5802 static void
5803 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5804 tree *counts, gimple inner_stmt, tree startvar)
5806 int i;
5807 if (gimple_omp_for_combined_p (fd->for_stmt))
5809 /* If fd->loop.n2 is constant, then no propagation of the counts
5810 is needed, they are constant. */
5811 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5812 return;
5814 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5815 ? gimple_omp_parallel_clauses (inner_stmt)
5816 : gimple_omp_for_clauses (inner_stmt);
5817 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5818 isn't supposed to be handled, as the inner loop doesn't
5819 use it. */
5820 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5821 gcc_assert (innerc);
5822 for (i = 0; i < fd->collapse; i++)
5824 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5825 OMP_CLAUSE__LOOPTEMP_);
5826 gcc_assert (innerc);
5827 if (i)
5829 tree tem = OMP_CLAUSE_DECL (innerc);
5830 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5831 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5832 false, GSI_CONTINUE_LINKING);
5833 gassign *stmt = gimple_build_assign (tem, t);
5834 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5837 return;
5840 tree type = TREE_TYPE (fd->loop.v);
5841 tree tem = create_tmp_reg (type, ".tem");
5842 gassign *stmt = gimple_build_assign (tem, startvar);
5843 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5845 for (i = fd->collapse - 1; i >= 0; i--)
5847 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5848 itype = vtype;
5849 if (POINTER_TYPE_P (vtype))
5850 itype = signed_type_for (vtype);
5851 if (i != 0)
5852 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5853 else
5854 t = tem;
5855 t = fold_convert (itype, t);
5856 t = fold_build2 (MULT_EXPR, itype, t,
5857 fold_convert (itype, fd->loops[i].step));
5858 if (POINTER_TYPE_P (vtype))
5859 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5860 else
5861 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5862 t = force_gimple_operand_gsi (gsi, t,
5863 DECL_P (fd->loops[i].v)
5864 && TREE_ADDRESSABLE (fd->loops[i].v),
5865 NULL_TREE, false,
5866 GSI_CONTINUE_LINKING);
5867 stmt = gimple_build_assign (fd->loops[i].v, t);
5868 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5869 if (i != 0)
5871 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5872 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5873 false, GSI_CONTINUE_LINKING);
5874 stmt = gimple_build_assign (tem, t);
5875 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5881 /* Helper function for expand_omp_for_*. Generate code like:
5882 L10:
5883 V3 += STEP3;
5884 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5885 L11:
5886 V3 = N31;
5887 V2 += STEP2;
5888 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5889 L12:
5890 V2 = N21;
5891 V1 += STEP1;
5892 goto BODY_BB; */
5894 static basic_block
5895 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5896 basic_block body_bb)
5898 basic_block last_bb, bb, collapse_bb = NULL;
5899 int i;
5900 gimple_stmt_iterator gsi;
5901 edge e;
5902 tree t;
5903 gimple stmt;
5905 last_bb = cont_bb;
5906 for (i = fd->collapse - 1; i >= 0; i--)
5908 tree vtype = TREE_TYPE (fd->loops[i].v);
5910 bb = create_empty_bb (last_bb);
5911 add_bb_to_loop (bb, last_bb->loop_father);
5912 gsi = gsi_start_bb (bb);
5914 if (i < fd->collapse - 1)
5916 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5917 e->probability = REG_BR_PROB_BASE / 8;
5919 t = fd->loops[i + 1].n1;
5920 t = force_gimple_operand_gsi (&gsi, t,
5921 DECL_P (fd->loops[i + 1].v)
5922 && TREE_ADDRESSABLE (fd->loops[i
5923 + 1].v),
5924 NULL_TREE, false,
5925 GSI_CONTINUE_LINKING);
5926 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5927 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5929 else
5930 collapse_bb = bb;
5932 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5934 if (POINTER_TYPE_P (vtype))
5935 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5936 else
5937 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5938 t = force_gimple_operand_gsi (&gsi, t,
5939 DECL_P (fd->loops[i].v)
5940 && TREE_ADDRESSABLE (fd->loops[i].v),
5941 NULL_TREE, false, GSI_CONTINUE_LINKING);
5942 stmt = gimple_build_assign (fd->loops[i].v, t);
5943 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5945 if (i > 0)
5947 t = fd->loops[i].n2;
5948 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5949 false, GSI_CONTINUE_LINKING);
5950 tree v = fd->loops[i].v;
5951 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5952 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5953 false, GSI_CONTINUE_LINKING);
5954 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5955 stmt = gimple_build_cond_empty (t);
5956 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5957 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5958 e->probability = REG_BR_PROB_BASE * 7 / 8;
5960 else
5961 make_edge (bb, body_bb, EDGE_FALLTHRU);
5962 last_bb = bb;
5965 return collapse_bb;
5969 /* A subroutine of expand_omp_for. Generate code for a parallel
5970 loop with any schedule. Given parameters:
5972 for (V = N1; V cond N2; V += STEP) BODY;
5974 where COND is "<" or ">", we generate pseudocode
5976 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5977 if (more) goto L0; else goto L3;
5979 V = istart0;
5980 iend = iend0;
5982 BODY;
5983 V += STEP;
5984 if (V cond iend) goto L1; else goto L2;
5986 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5989 If this is a combined omp parallel loop, instead of the call to
5990 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5991 If this is gimple_omp_for_combined_p loop, then instead of assigning
5992 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5993 inner GIMPLE_OMP_FOR and V += STEP; and
5994 if (V cond iend) goto L1; else goto L2; are removed.
5996 For collapsed loops, given parameters:
5997 collapse(3)
5998 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5999 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6000 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6001 BODY;
6003 we generate pseudocode
6005 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6006 if (cond3 is <)
6007 adj = STEP3 - 1;
6008 else
6009 adj = STEP3 + 1;
6010 count3 = (adj + N32 - N31) / STEP3;
6011 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6012 if (cond2 is <)
6013 adj = STEP2 - 1;
6014 else
6015 adj = STEP2 + 1;
6016 count2 = (adj + N22 - N21) / STEP2;
6017 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6018 if (cond1 is <)
6019 adj = STEP1 - 1;
6020 else
6021 adj = STEP1 + 1;
6022 count1 = (adj + N12 - N11) / STEP1;
6023 count = count1 * count2 * count3;
6024 goto Z1;
6026 count = 0;
6028 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6029 if (more) goto L0; else goto L3;
6031 V = istart0;
6032 T = V;
6033 V3 = N31 + (T % count3) * STEP3;
6034 T = T / count3;
6035 V2 = N21 + (T % count2) * STEP2;
6036 T = T / count2;
6037 V1 = N11 + T * STEP1;
6038 iend = iend0;
6040 BODY;
6041 V += 1;
6042 if (V < iend) goto L10; else goto L2;
6043 L10:
6044 V3 += STEP3;
6045 if (V3 cond3 N32) goto L1; else goto L11;
6046 L11:
6047 V3 = N31;
6048 V2 += STEP2;
6049 if (V2 cond2 N22) goto L1; else goto L12;
6050 L12:
6051 V2 = N21;
6052 V1 += STEP1;
6053 goto L1;
6055 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6060 static void
6061 expand_omp_for_generic (struct omp_region *region,
6062 struct omp_for_data *fd,
6063 enum built_in_function start_fn,
6064 enum built_in_function next_fn,
6065 gimple inner_stmt)
6067 gcc_assert (gimple_omp_for_kind (fd->for_stmt) != GF_OMP_FOR_KIND_OACC_LOOP);
6069 tree type, istart0, iend0, iend;
6070 tree t, vmain, vback, bias = NULL_TREE;
6071 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6072 basic_block l2_bb = NULL, l3_bb = NULL;
6073 gimple_stmt_iterator gsi;
6074 gassign *assign_stmt;
6075 bool in_combined_parallel = is_combined_parallel (region);
6076 bool broken_loop = region->cont == NULL;
6077 edge e, ne;
6078 tree *counts = NULL;
6079 int i;
6081 gcc_assert (!broken_loop || !in_combined_parallel);
6082 gcc_assert (fd->iter_type == long_integer_type_node
6083 || !in_combined_parallel);
6085 type = TREE_TYPE (fd->loop.v);
6086 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6087 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6088 TREE_ADDRESSABLE (istart0) = 1;
6089 TREE_ADDRESSABLE (iend0) = 1;
6091 /* See if we need to bias by LLONG_MIN. */
6092 if (fd->iter_type == long_long_unsigned_type_node
6093 && TREE_CODE (type) == INTEGER_TYPE
6094 && !TYPE_UNSIGNED (type))
6096 tree n1, n2;
6098 if (fd->loop.cond_code == LT_EXPR)
6100 n1 = fd->loop.n1;
6101 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6103 else
6105 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6106 n2 = fd->loop.n1;
6108 if (TREE_CODE (n1) != INTEGER_CST
6109 || TREE_CODE (n2) != INTEGER_CST
6110 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6111 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6114 entry_bb = region->entry;
6115 cont_bb = region->cont;
6116 collapse_bb = NULL;
6117 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6118 gcc_assert (broken_loop
6119 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6120 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6121 l1_bb = single_succ (l0_bb);
6122 if (!broken_loop)
6124 l2_bb = create_empty_bb (cont_bb);
6125 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6126 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6128 else
6129 l2_bb = NULL;
6130 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6131 exit_bb = region->exit;
6133 gsi = gsi_last_bb (entry_bb);
6135 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6136 if (fd->collapse > 1)
6138 gcc_assert (gimple_omp_for_kind (gsi_stmt (gsi))
6139 != GF_OMP_FOR_KIND_OACC_LOOP);
6141 int first_zero_iter = -1;
6142 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6144 counts = XALLOCAVEC (tree, fd->collapse);
6145 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6146 zero_iter_bb, first_zero_iter,
6147 l2_dom_bb);
6149 if (zero_iter_bb)
6151 /* Some counts[i] vars might be uninitialized if
6152 some loop has zero iterations. But the body shouldn't
6153 be executed in that case, so just avoid uninit warnings. */
6154 for (i = first_zero_iter; i < fd->collapse; i++)
6155 if (SSA_VAR_P (counts[i]))
6156 TREE_NO_WARNING (counts[i]) = 1;
6157 gsi_prev (&gsi);
6158 e = split_block (entry_bb, gsi_stmt (gsi));
6159 entry_bb = e->dest;
6160 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6161 gsi = gsi_last_bb (entry_bb);
6162 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6163 get_immediate_dominator (CDI_DOMINATORS,
6164 zero_iter_bb));
6167 if (in_combined_parallel)
6169 gcc_assert (gimple_omp_for_kind (gsi_stmt (gsi))
6170 != GF_OMP_FOR_KIND_OACC_LOOP);
6172 /* In a combined parallel loop, emit a call to
6173 GOMP_loop_foo_next. */
6174 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6175 build_fold_addr_expr (istart0),
6176 build_fold_addr_expr (iend0));
6178 else
6180 tree t0, t1, t2, t3, t4;
6181 /* If this is not a combined parallel loop, emit a call to
6182 GOMP_loop_foo_start in ENTRY_BB. */
6183 t4 = build_fold_addr_expr (iend0);
6184 t3 = build_fold_addr_expr (istart0);
6185 t2 = fold_convert (fd->iter_type, fd->loop.step);
6186 t1 = fd->loop.n2;
6187 t0 = fd->loop.n1;
6188 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6190 gcc_assert (gimple_omp_for_kind (gsi_stmt (gsi))
6191 != GF_OMP_FOR_KIND_OACC_LOOP);
6193 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6194 OMP_CLAUSE__LOOPTEMP_);
6195 gcc_assert (innerc);
6196 t0 = OMP_CLAUSE_DECL (innerc);
6197 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6198 OMP_CLAUSE__LOOPTEMP_);
6199 gcc_assert (innerc);
6200 t1 = OMP_CLAUSE_DECL (innerc);
6202 if (POINTER_TYPE_P (TREE_TYPE (t0))
6203 && TYPE_PRECISION (TREE_TYPE (t0))
6204 != TYPE_PRECISION (fd->iter_type))
6206 /* Avoid casting pointers to integer of a different size. */
6207 tree itype = signed_type_for (type);
6208 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6209 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6211 else
6213 t1 = fold_convert (fd->iter_type, t1);
6214 t0 = fold_convert (fd->iter_type, t0);
6216 if (bias)
6218 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6219 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6221 if (fd->iter_type == long_integer_type_node)
6223 if (fd->chunk_size)
6225 t = fold_convert (fd->iter_type, fd->chunk_size);
6226 t = build_call_expr (builtin_decl_explicit (start_fn),
6227 6, t0, t1, t2, t, t3, t4);
6229 else
6230 t = build_call_expr (builtin_decl_explicit (start_fn),
6231 5, t0, t1, t2, t3, t4);
6233 else
6235 tree t5;
6236 tree c_bool_type;
6237 tree bfn_decl;
6239 /* The GOMP_loop_ull_*start functions have additional boolean
6240 argument, true for < loops and false for > loops.
6241 In Fortran, the C bool type can be different from
6242 boolean_type_node. */
6243 bfn_decl = builtin_decl_explicit (start_fn);
6244 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6245 t5 = build_int_cst (c_bool_type,
6246 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6247 if (fd->chunk_size)
6249 tree bfn_decl = builtin_decl_explicit (start_fn);
6250 t = fold_convert (fd->iter_type, fd->chunk_size);
6251 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6253 else
6254 t = build_call_expr (builtin_decl_explicit (start_fn),
6255 6, t5, t0, t1, t2, t3, t4);
6258 if (TREE_TYPE (t) != boolean_type_node)
6259 t = fold_build2 (NE_EXPR, boolean_type_node,
6260 t, build_int_cst (TREE_TYPE (t), 0));
6261 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6262 true, GSI_SAME_STMT);
6263 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6265 /* Remove the GIMPLE_OMP_FOR statement. */
6266 gsi_remove (&gsi, true);
6268 /* Iteration setup for sequential loop goes in L0_BB. */
6269 tree startvar = fd->loop.v;
6270 tree endvar = NULL_TREE;
6272 if (gimple_omp_for_combined_p (fd->for_stmt))
6274 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6275 && gimple_omp_for_kind (inner_stmt)
6276 == GF_OMP_FOR_KIND_SIMD);
6277 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6278 OMP_CLAUSE__LOOPTEMP_);
6279 gcc_assert (innerc);
6280 startvar = OMP_CLAUSE_DECL (innerc);
6281 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6282 OMP_CLAUSE__LOOPTEMP_);
6283 gcc_assert (innerc);
6284 endvar = OMP_CLAUSE_DECL (innerc);
6287 gsi = gsi_start_bb (l0_bb);
6288 t = istart0;
6289 if (bias)
6290 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6291 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6292 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6293 t = fold_convert (TREE_TYPE (startvar), t);
6294 t = force_gimple_operand_gsi (&gsi, t,
6295 DECL_P (startvar)
6296 && TREE_ADDRESSABLE (startvar),
6297 NULL_TREE, false, GSI_CONTINUE_LINKING);
6298 assign_stmt = gimple_build_assign (startvar, t);
6299 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6301 t = iend0;
6302 if (bias)
6303 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6304 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6305 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6306 t = fold_convert (TREE_TYPE (startvar), t);
6307 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6308 false, GSI_CONTINUE_LINKING);
6309 if (endvar)
6311 assign_stmt = gimple_build_assign (endvar, iend);
6312 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6313 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6314 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6315 else
6316 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6317 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6319 if (fd->collapse > 1)
6320 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6322 if (!broken_loop)
6324 /* Code to control the increment and predicate for the sequential
6325 loop goes in the CONT_BB. */
6326 gsi = gsi_last_bb (cont_bb);
6327 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6328 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6329 vmain = gimple_omp_continue_control_use (cont_stmt);
6330 vback = gimple_omp_continue_control_def (cont_stmt);
6332 if (!gimple_omp_for_combined_p (fd->for_stmt))
6334 if (POINTER_TYPE_P (type))
6335 t = fold_build_pointer_plus (vmain, fd->loop.step);
6336 else
6337 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6338 t = force_gimple_operand_gsi (&gsi, t,
6339 DECL_P (vback)
6340 && TREE_ADDRESSABLE (vback),
6341 NULL_TREE, true, GSI_SAME_STMT);
6342 assign_stmt = gimple_build_assign (vback, t);
6343 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6345 t = build2 (fd->loop.cond_code, boolean_type_node,
6346 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6347 iend);
6348 gcond *cond_stmt = gimple_build_cond_empty (t);
6349 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6352 /* Remove GIMPLE_OMP_CONTINUE. */
6353 gsi_remove (&gsi, true);
6355 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6356 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6358 /* Emit code to get the next parallel iteration in L2_BB. */
6359 gsi = gsi_start_bb (l2_bb);
6361 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6362 build_fold_addr_expr (istart0),
6363 build_fold_addr_expr (iend0));
6364 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6365 false, GSI_CONTINUE_LINKING);
6366 if (TREE_TYPE (t) != boolean_type_node)
6367 t = fold_build2 (NE_EXPR, boolean_type_node,
6368 t, build_int_cst (TREE_TYPE (t), 0));
6369 gcond *cond_stmt = gimple_build_cond_empty (t);
6370 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6373 /* Add the loop cleanup function. */
6374 gsi = gsi_last_bb (exit_bb);
6375 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6376 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6377 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6378 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6379 else
6380 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6381 gcall *call_stmt = gimple_build_call (t, 0);
6382 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6383 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6384 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6385 gsi_remove (&gsi, true);
6387 /* Connect the new blocks. */
6388 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6389 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6391 if (!broken_loop)
6393 gimple_seq phis;
6395 e = find_edge (cont_bb, l3_bb);
6396 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6398 phis = phi_nodes (l3_bb);
6399 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6401 gimple phi = gsi_stmt (gsi);
6402 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6403 PHI_ARG_DEF_FROM_EDGE (phi, e));
6405 remove_edge (e);
6407 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6408 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6409 e = find_edge (cont_bb, l1_bb);
6410 if (gimple_omp_for_combined_p (fd->for_stmt))
6412 remove_edge (e);
6413 e = NULL;
6415 else if (fd->collapse > 1)
6417 remove_edge (e);
6418 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6420 else
6421 e->flags = EDGE_TRUE_VALUE;
6422 if (e)
6424 e->probability = REG_BR_PROB_BASE * 7 / 8;
6425 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6427 else
6429 e = find_edge (cont_bb, l2_bb);
6430 e->flags = EDGE_FALLTHRU;
6432 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6434 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6435 recompute_dominator (CDI_DOMINATORS, l2_bb));
6436 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6437 recompute_dominator (CDI_DOMINATORS, l3_bb));
6438 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6439 recompute_dominator (CDI_DOMINATORS, l0_bb));
6440 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6441 recompute_dominator (CDI_DOMINATORS, l1_bb));
6443 struct loop *outer_loop = alloc_loop ();
6444 outer_loop->header = l0_bb;
6445 outer_loop->latch = l2_bb;
6446 add_loop (outer_loop, l0_bb->loop_father);
6448 if (!gimple_omp_for_combined_p (fd->for_stmt))
6450 struct loop *loop = alloc_loop ();
6451 loop->header = l1_bb;
6452 /* The loop may have multiple latches. */
6453 add_loop (loop, outer_loop);
6459 /* A subroutine of expand_omp_for. Generate code for a parallel
6460 loop with static schedule and no specified chunk size. Given
6461 parameters:
6463 for (V = N1; V cond N2; V += STEP) BODY;
6465 where COND is "<" or ">", we generate pseudocode
6467 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6468 if (cond is <)
6469 adj = STEP - 1;
6470 else
6471 adj = STEP + 1;
6472 if ((__typeof (V)) -1 > 0 && cond is >)
6473 n = -(adj + N2 - N1) / -STEP;
6474 else
6475 n = (adj + N2 - N1) / STEP;
6476 q = n / nthreads;
6477 tt = n % nthreads;
6478 if (threadid < tt) goto L3; else goto L4;
6480 tt = 0;
6481 q = q + 1;
6483 s0 = q * threadid + tt;
6484 e0 = s0 + q;
6485 V = s0 * STEP + N1;
6486 if (s0 >= e0) goto L2; else goto L0;
6488 e = e0 * STEP + N1;
6490 BODY;
6491 V += STEP;
6492 if (V cond e) goto L1;
6496 static void
6497 expand_omp_for_static_nochunk (struct omp_region *region,
6498 struct omp_for_data *fd,
6499 gimple inner_stmt)
6501 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6502 tree type, itype, vmain, vback;
6503 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6504 basic_block body_bb, cont_bb, collapse_bb = NULL;
6505 basic_block fin_bb;
6506 gimple_stmt_iterator gsi;
6507 edge ep;
6508 bool broken_loop = region->cont == NULL;
6509 tree *counts = NULL;
6510 tree n1, n2, step;
6512 gcc_assert ((gimple_omp_for_kind (fd->for_stmt)
6513 != GF_OMP_FOR_KIND_OACC_LOOP)
6514 || !inner_stmt);
6516 itype = type = TREE_TYPE (fd->loop.v);
6517 if (POINTER_TYPE_P (type))
6518 itype = signed_type_for (type);
6520 entry_bb = region->entry;
6521 cont_bb = region->cont;
6522 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6523 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6524 gcc_assert (broken_loop
6525 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6526 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6527 body_bb = single_succ (seq_start_bb);
6528 if (!broken_loop)
6530 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6531 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6533 exit_bb = region->exit;
6535 /* Iteration space partitioning goes in ENTRY_BB. */
6536 gsi = gsi_last_bb (entry_bb);
6537 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6539 if (fd->collapse > 1)
6541 int first_zero_iter = -1;
6542 basic_block l2_dom_bb = NULL;
6544 counts = XALLOCAVEC (tree, fd->collapse);
6545 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6546 fin_bb, first_zero_iter,
6547 l2_dom_bb);
6548 t = NULL_TREE;
6550 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6551 t = integer_one_node;
6552 else
6553 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6554 fold_convert (type, fd->loop.n1),
6555 fold_convert (type, fd->loop.n2));
6556 if (fd->collapse == 1
6557 && TYPE_UNSIGNED (type)
6558 && (t == NULL_TREE || !integer_onep (t)))
6560 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6561 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6562 true, GSI_SAME_STMT);
6563 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6564 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6565 true, GSI_SAME_STMT);
6566 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6567 NULL_TREE, NULL_TREE);
6568 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6569 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6570 expand_omp_regimplify_p, NULL, NULL)
6571 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6572 expand_omp_regimplify_p, NULL, NULL))
6574 gsi = gsi_for_stmt (cond_stmt);
6575 gimple_regimplify_operands (cond_stmt, &gsi);
6577 ep = split_block (entry_bb, cond_stmt);
6578 ep->flags = EDGE_TRUE_VALUE;
6579 entry_bb = ep->dest;
6580 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6581 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6582 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6583 if (gimple_in_ssa_p (cfun))
6585 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6586 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6587 !gsi_end_p (gpi); gsi_next (&gpi))
6589 gphi *phi = gpi.phi ();
6590 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6591 ep, UNKNOWN_LOCATION);
6594 gsi = gsi_last_bb (entry_bb);
6597 switch (gimple_omp_for_kind (fd->for_stmt))
6599 case GF_OMP_FOR_KIND_FOR:
6600 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6601 nthreads = build_call_expr (nthreads, 0);
6602 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6603 threadid = build_call_expr (threadid, 0);
6604 break;
6605 case GF_OMP_FOR_KIND_DISTRIBUTE:
6606 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6607 nthreads = build_call_expr (nthreads, 0);
6608 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6609 threadid = build_call_expr (threadid, 0);
6610 break;
6611 case GF_OMP_FOR_KIND_OACC_LOOP:
6612 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6613 nthreads = build_call_expr (nthreads, 0);
6614 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6615 threadid = build_call_expr (threadid, 0);
6616 break;
6617 default:
6618 gcc_unreachable ();
6620 nthreads = fold_convert (itype, nthreads);
6621 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6622 true, GSI_SAME_STMT);
6623 threadid = fold_convert (itype, threadid);
6624 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6625 true, GSI_SAME_STMT);
6627 n1 = fd->loop.n1;
6628 n2 = fd->loop.n2;
6629 step = fd->loop.step;
6630 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6632 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
6633 != GF_OMP_FOR_KIND_OACC_LOOP);
6635 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6636 OMP_CLAUSE__LOOPTEMP_);
6637 gcc_assert (innerc);
6638 n1 = OMP_CLAUSE_DECL (innerc);
6639 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6640 OMP_CLAUSE__LOOPTEMP_);
6641 gcc_assert (innerc);
6642 n2 = OMP_CLAUSE_DECL (innerc);
6644 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6645 true, NULL_TREE, true, GSI_SAME_STMT);
6646 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6647 true, NULL_TREE, true, GSI_SAME_STMT);
6648 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6649 true, NULL_TREE, true, GSI_SAME_STMT);
6651 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6652 t = fold_build2 (PLUS_EXPR, itype, step, t);
6653 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6654 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6655 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6656 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6657 fold_build1 (NEGATE_EXPR, itype, t),
6658 fold_build1 (NEGATE_EXPR, itype, step));
6659 else
6660 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6661 t = fold_convert (itype, t);
6662 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6664 q = create_tmp_reg (itype, "q");
6665 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6666 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6667 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6669 tt = create_tmp_reg (itype, "tt");
6670 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6671 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6672 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6674 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6675 gcond *cond_stmt = gimple_build_cond_empty (t);
6676 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6678 second_bb = split_block (entry_bb, cond_stmt)->dest;
6679 gsi = gsi_last_bb (second_bb);
6680 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6682 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6683 GSI_SAME_STMT);
6684 gassign *assign_stmt
6685 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6686 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6688 third_bb = split_block (second_bb, assign_stmt)->dest;
6689 gsi = gsi_last_bb (third_bb);
6690 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6692 t = build2 (MULT_EXPR, itype, q, threadid);
6693 t = build2 (PLUS_EXPR, itype, t, tt);
6694 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6696 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6697 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6699 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6700 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6702 /* Remove the GIMPLE_OMP_FOR statement. */
6703 gsi_remove (&gsi, true);
6705 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6706 gsi = gsi_start_bb (seq_start_bb);
6708 tree startvar = fd->loop.v;
6709 tree endvar = NULL_TREE;
6711 if (gimple_omp_for_combined_p (fd->for_stmt))
6713 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6714 ? gimple_omp_parallel_clauses (inner_stmt)
6715 : gimple_omp_for_clauses (inner_stmt);
6716 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6717 gcc_assert (innerc);
6718 startvar = OMP_CLAUSE_DECL (innerc);
6719 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6720 OMP_CLAUSE__LOOPTEMP_);
6721 gcc_assert (innerc);
6722 endvar = OMP_CLAUSE_DECL (innerc);
6724 t = fold_convert (itype, s0);
6725 t = fold_build2 (MULT_EXPR, itype, t, step);
6726 if (POINTER_TYPE_P (type))
6727 t = fold_build_pointer_plus (n1, t);
6728 else
6729 t = fold_build2 (PLUS_EXPR, type, t, n1);
6730 t = fold_convert (TREE_TYPE (startvar), t);
6731 t = force_gimple_operand_gsi (&gsi, t,
6732 DECL_P (startvar)
6733 && TREE_ADDRESSABLE (startvar),
6734 NULL_TREE, false, GSI_CONTINUE_LINKING);
6735 assign_stmt = gimple_build_assign (startvar, t);
6736 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6738 t = fold_convert (itype, e0);
6739 t = fold_build2 (MULT_EXPR, itype, t, step);
6740 if (POINTER_TYPE_P (type))
6741 t = fold_build_pointer_plus (n1, t);
6742 else
6743 t = fold_build2 (PLUS_EXPR, type, t, n1);
6744 t = fold_convert (TREE_TYPE (startvar), t);
6745 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6746 false, GSI_CONTINUE_LINKING);
6747 if (endvar)
6749 assign_stmt = gimple_build_assign (endvar, e);
6750 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6751 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6752 assign_stmt = gimple_build_assign (fd->loop.v, e);
6753 else
6754 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6755 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6757 if (fd->collapse > 1)
6758 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6760 if (!broken_loop)
6762 /* The code controlling the sequential loop replaces the
6763 GIMPLE_OMP_CONTINUE. */
6764 gsi = gsi_last_bb (cont_bb);
6765 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6766 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6767 vmain = gimple_omp_continue_control_use (cont_stmt);
6768 vback = gimple_omp_continue_control_def (cont_stmt);
6770 if (!gimple_omp_for_combined_p (fd->for_stmt))
6772 if (POINTER_TYPE_P (type))
6773 t = fold_build_pointer_plus (vmain, step);
6774 else
6775 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6776 t = force_gimple_operand_gsi (&gsi, t,
6777 DECL_P (vback)
6778 && TREE_ADDRESSABLE (vback),
6779 NULL_TREE, true, GSI_SAME_STMT);
6780 assign_stmt = gimple_build_assign (vback, t);
6781 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6783 t = build2 (fd->loop.cond_code, boolean_type_node,
6784 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6785 ? t : vback, e);
6786 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6789 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6790 gsi_remove (&gsi, true);
6792 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6793 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6796 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6797 gsi = gsi_last_bb (exit_bb);
6798 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6800 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
6801 != GF_OMP_FOR_KIND_OACC_LOOP);
6803 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6804 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6806 gsi_remove (&gsi, true);
6808 /* Connect all the blocks. */
6809 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6810 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6811 ep = find_edge (entry_bb, second_bb);
6812 ep->flags = EDGE_TRUE_VALUE;
6813 ep->probability = REG_BR_PROB_BASE / 4;
6814 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6815 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6817 if (!broken_loop)
6819 ep = find_edge (cont_bb, body_bb);
6820 if (gimple_omp_for_combined_p (fd->for_stmt))
6822 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
6823 != GF_OMP_FOR_KIND_OACC_LOOP);
6825 remove_edge (ep);
6826 ep = NULL;
6828 else if (fd->collapse > 1)
6830 remove_edge (ep);
6831 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6833 else
6834 ep->flags = EDGE_TRUE_VALUE;
6835 find_edge (cont_bb, fin_bb)->flags
6836 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6839 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6840 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6841 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6843 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6844 recompute_dominator (CDI_DOMINATORS, body_bb));
6845 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6846 recompute_dominator (CDI_DOMINATORS, fin_bb));
6848 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6850 struct loop *loop = alloc_loop ();
6851 loop->header = body_bb;
6852 if (collapse_bb == NULL)
6853 loop->latch = cont_bb;
6854 add_loop (loop, body_bb->loop_father);
6859 /* A subroutine of expand_omp_for. Generate code for a parallel
6860 loop with static schedule and a specified chunk size. Given
6861 parameters:
6863 for (V = N1; V cond N2; V += STEP) BODY;
6865 where COND is "<" or ">", we generate pseudocode
6867 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6868 if (cond is <)
6869 adj = STEP - 1;
6870 else
6871 adj = STEP + 1;
6872 if ((__typeof (V)) -1 > 0 && cond is >)
6873 n = -(adj + N2 - N1) / -STEP;
6874 else
6875 n = (adj + N2 - N1) / STEP;
6876 trip = 0;
6877 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6878 here so that V is defined
6879 if the loop is not entered
6881 s0 = (trip * nthreads + threadid) * CHUNK;
6882 e0 = min(s0 + CHUNK, n);
6883 if (s0 < n) goto L1; else goto L4;
6885 V = s0 * STEP + N1;
6886 e = e0 * STEP + N1;
6888 BODY;
6889 V += STEP;
6890 if (V cond e) goto L2; else goto L3;
6892 trip += 1;
6893 goto L0;
6897 static void
6898 expand_omp_for_static_chunk (struct omp_region *region,
6899 struct omp_for_data *fd, gimple inner_stmt)
6901 tree n, s0, e0, e, t;
6902 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6903 tree type, itype, vmain, vback, vextra;
6904 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6905 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6906 gimple_stmt_iterator gsi;
6907 edge se;
6908 bool broken_loop = region->cont == NULL;
6909 tree *counts = NULL;
6910 tree n1, n2, step;
6912 gcc_assert ((gimple_omp_for_kind (fd->for_stmt)
6913 != GF_OMP_FOR_KIND_OACC_LOOP)
6914 || !inner_stmt);
6916 itype = type = TREE_TYPE (fd->loop.v);
6917 if (POINTER_TYPE_P (type))
6918 itype = signed_type_for (type);
6920 entry_bb = region->entry;
6921 se = split_block (entry_bb, last_stmt (entry_bb));
6922 entry_bb = se->src;
6923 iter_part_bb = se->dest;
6924 cont_bb = region->cont;
6925 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6926 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6927 gcc_assert (broken_loop
6928 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6929 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6930 body_bb = single_succ (seq_start_bb);
6931 if (!broken_loop)
6933 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6934 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6935 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6937 exit_bb = region->exit;
6939 /* Trip and adjustment setup goes in ENTRY_BB. */
6940 gsi = gsi_last_bb (entry_bb);
6941 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6943 if (fd->collapse > 1)
6945 int first_zero_iter = -1;
6946 basic_block l2_dom_bb = NULL;
6948 counts = XALLOCAVEC (tree, fd->collapse);
6949 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6950 fin_bb, first_zero_iter,
6951 l2_dom_bb);
6952 t = NULL_TREE;
6954 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6955 t = integer_one_node;
6956 else
6957 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6958 fold_convert (type, fd->loop.n1),
6959 fold_convert (type, fd->loop.n2));
6960 if (fd->collapse == 1
6961 && TYPE_UNSIGNED (type)
6962 && (t == NULL_TREE || !integer_onep (t)))
6964 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6965 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6966 true, GSI_SAME_STMT);
6967 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6968 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6969 true, GSI_SAME_STMT);
6970 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6971 NULL_TREE, NULL_TREE);
6972 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6973 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6974 expand_omp_regimplify_p, NULL, NULL)
6975 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6976 expand_omp_regimplify_p, NULL, NULL))
6978 gsi = gsi_for_stmt (cond_stmt);
6979 gimple_regimplify_operands (cond_stmt, &gsi);
6981 se = split_block (entry_bb, cond_stmt);
6982 se->flags = EDGE_TRUE_VALUE;
6983 entry_bb = se->dest;
6984 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6985 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6986 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6987 if (gimple_in_ssa_p (cfun))
6989 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6990 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6991 !gsi_end_p (gpi); gsi_next (&gpi))
6993 gphi *phi = gpi.phi ();
6994 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6995 se, UNKNOWN_LOCATION);
6998 gsi = gsi_last_bb (entry_bb);
7001 switch (gimple_omp_for_kind (fd->for_stmt))
7003 case GF_OMP_FOR_KIND_FOR:
7004 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7005 nthreads = build_call_expr (nthreads, 0);
7006 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7007 threadid = build_call_expr (threadid, 0);
7008 break;
7009 case GF_OMP_FOR_KIND_DISTRIBUTE:
7010 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7011 nthreads = build_call_expr (nthreads, 0);
7012 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7013 threadid = build_call_expr (threadid, 0);
7014 break;
7015 case GF_OMP_FOR_KIND_OACC_LOOP:
7016 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7017 nthreads = build_call_expr (nthreads, 0);
7018 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7019 threadid = build_call_expr (threadid, 0);
7020 break;
7021 default:
7022 gcc_unreachable ();
7024 nthreads = fold_convert (itype, nthreads);
7025 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7026 true, GSI_SAME_STMT);
7027 threadid = fold_convert (itype, threadid);
7028 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7029 true, GSI_SAME_STMT);
7031 n1 = fd->loop.n1;
7032 n2 = fd->loop.n2;
7033 step = fd->loop.step;
7034 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7036 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
7037 != GF_OMP_FOR_KIND_OACC_LOOP);
7039 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7040 OMP_CLAUSE__LOOPTEMP_);
7041 gcc_assert (innerc);
7042 n1 = OMP_CLAUSE_DECL (innerc);
7043 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7044 OMP_CLAUSE__LOOPTEMP_);
7045 gcc_assert (innerc);
7046 n2 = OMP_CLAUSE_DECL (innerc);
7048 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7049 true, NULL_TREE, true, GSI_SAME_STMT);
7050 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7051 true, NULL_TREE, true, GSI_SAME_STMT);
7052 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7053 true, NULL_TREE, true, GSI_SAME_STMT);
7054 fd->chunk_size
7055 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7056 true, NULL_TREE, true, GSI_SAME_STMT);
7058 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7059 t = fold_build2 (PLUS_EXPR, itype, step, t);
7060 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7061 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7062 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7063 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7064 fold_build1 (NEGATE_EXPR, itype, t),
7065 fold_build1 (NEGATE_EXPR, itype, step));
7066 else
7067 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7068 t = fold_convert (itype, t);
7069 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7070 true, GSI_SAME_STMT);
7072 trip_var = create_tmp_reg (itype, ".trip");
7073 if (gimple_in_ssa_p (cfun))
7075 trip_init = make_ssa_name (trip_var);
7076 trip_main = make_ssa_name (trip_var);
7077 trip_back = make_ssa_name (trip_var);
7079 else
7081 trip_init = trip_var;
7082 trip_main = trip_var;
7083 trip_back = trip_var;
7086 gassign *assign_stmt
7087 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7088 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7090 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7091 t = fold_build2 (MULT_EXPR, itype, t, step);
7092 if (POINTER_TYPE_P (type))
7093 t = fold_build_pointer_plus (n1, t);
7094 else
7095 t = fold_build2 (PLUS_EXPR, type, t, n1);
7096 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7097 true, GSI_SAME_STMT);
7099 /* Remove the GIMPLE_OMP_FOR. */
7100 gsi_remove (&gsi, true);
7102 /* Iteration space partitioning goes in ITER_PART_BB. */
7103 gsi = gsi_last_bb (iter_part_bb);
7105 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7106 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7107 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7108 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7109 false, GSI_CONTINUE_LINKING);
7111 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7112 t = fold_build2 (MIN_EXPR, itype, t, n);
7113 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7114 false, GSI_CONTINUE_LINKING);
7116 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7117 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7119 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7120 gsi = gsi_start_bb (seq_start_bb);
7122 tree startvar = fd->loop.v;
7123 tree endvar = NULL_TREE;
7125 if (gimple_omp_for_combined_p (fd->for_stmt))
7127 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7128 ? gimple_omp_parallel_clauses (inner_stmt)
7129 : gimple_omp_for_clauses (inner_stmt);
7130 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7131 gcc_assert (innerc);
7132 startvar = OMP_CLAUSE_DECL (innerc);
7133 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7134 OMP_CLAUSE__LOOPTEMP_);
7135 gcc_assert (innerc);
7136 endvar = OMP_CLAUSE_DECL (innerc);
7139 t = fold_convert (itype, s0);
7140 t = fold_build2 (MULT_EXPR, itype, t, step);
7141 if (POINTER_TYPE_P (type))
7142 t = fold_build_pointer_plus (n1, t);
7143 else
7144 t = fold_build2 (PLUS_EXPR, type, t, n1);
7145 t = fold_convert (TREE_TYPE (startvar), t);
7146 t = force_gimple_operand_gsi (&gsi, t,
7147 DECL_P (startvar)
7148 && TREE_ADDRESSABLE (startvar),
7149 NULL_TREE, false, GSI_CONTINUE_LINKING);
7150 assign_stmt = gimple_build_assign (startvar, t);
7151 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7153 t = fold_convert (itype, e0);
7154 t = fold_build2 (MULT_EXPR, itype, t, step);
7155 if (POINTER_TYPE_P (type))
7156 t = fold_build_pointer_plus (n1, t);
7157 else
7158 t = fold_build2 (PLUS_EXPR, type, t, n1);
7159 t = fold_convert (TREE_TYPE (startvar), t);
7160 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7161 false, GSI_CONTINUE_LINKING);
7162 if (endvar)
7164 assign_stmt = gimple_build_assign (endvar, e);
7165 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7166 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7167 assign_stmt = gimple_build_assign (fd->loop.v, e);
7168 else
7169 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7170 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7172 if (fd->collapse > 1)
7173 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7175 if (!broken_loop)
7177 /* The code controlling the sequential loop goes in CONT_BB,
7178 replacing the GIMPLE_OMP_CONTINUE. */
7179 gsi = gsi_last_bb (cont_bb);
7180 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7181 vmain = gimple_omp_continue_control_use (cont_stmt);
7182 vback = gimple_omp_continue_control_def (cont_stmt);
7184 if (!gimple_omp_for_combined_p (fd->for_stmt))
7186 if (POINTER_TYPE_P (type))
7187 t = fold_build_pointer_plus (vmain, step);
7188 else
7189 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7190 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7191 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7192 true, GSI_SAME_STMT);
7193 assign_stmt = gimple_build_assign (vback, t);
7194 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7196 t = build2 (fd->loop.cond_code, boolean_type_node,
7197 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7198 ? t : vback, e);
7199 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7202 /* Remove GIMPLE_OMP_CONTINUE. */
7203 gsi_remove (&gsi, true);
7205 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7206 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7208 /* Trip update code goes into TRIP_UPDATE_BB. */
7209 gsi = gsi_start_bb (trip_update_bb);
7211 t = build_int_cst (itype, 1);
7212 t = build2 (PLUS_EXPR, itype, trip_main, t);
7213 assign_stmt = gimple_build_assign (trip_back, t);
7214 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7217 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7218 gsi = gsi_last_bb (exit_bb);
7219 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7221 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
7222 != GF_OMP_FOR_KIND_OACC_LOOP);
7224 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7225 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7227 gsi_remove (&gsi, true);
7229 /* Connect the new blocks. */
7230 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7231 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7233 if (!broken_loop)
7235 se = find_edge (cont_bb, body_bb);
7236 if (gimple_omp_for_combined_p (fd->for_stmt))
7238 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
7239 != GF_OMP_FOR_KIND_OACC_LOOP);
7241 remove_edge (se);
7242 se = NULL;
7244 else if (fd->collapse > 1)
7246 remove_edge (se);
7247 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7249 else
7250 se->flags = EDGE_TRUE_VALUE;
7251 find_edge (cont_bb, trip_update_bb)->flags
7252 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7254 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7257 if (gimple_in_ssa_p (cfun))
7259 gphi_iterator psi;
7260 gphi *phi;
7261 edge re, ene;
7262 edge_var_map *vm;
7263 size_t i;
7265 gcc_assert (fd->collapse == 1 && !broken_loop);
7267 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7268 remove arguments of the phi nodes in fin_bb. We need to create
7269 appropriate phi nodes in iter_part_bb instead. */
7270 se = single_pred_edge (fin_bb);
7271 re = single_succ_edge (trip_update_bb);
7272 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7273 ene = single_succ_edge (entry_bb);
7275 psi = gsi_start_phis (fin_bb);
7276 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7277 gsi_next (&psi), ++i)
7279 gphi *nphi;
7280 source_location locus;
7282 phi = psi.phi ();
7283 t = gimple_phi_result (phi);
7284 gcc_assert (t == redirect_edge_var_map_result (vm));
7285 nphi = create_phi_node (t, iter_part_bb);
7287 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7288 locus = gimple_phi_arg_location_from_edge (phi, se);
7290 /* A special case -- fd->loop.v is not yet computed in
7291 iter_part_bb, we need to use vextra instead. */
7292 if (t == fd->loop.v)
7293 t = vextra;
7294 add_phi_arg (nphi, t, ene, locus);
7295 locus = redirect_edge_var_map_location (vm);
7296 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7298 gcc_assert (!gsi_end_p (psi) && i == head->length ());
7299 redirect_edge_var_map_clear (re);
7300 while (1)
7302 psi = gsi_start_phis (fin_bb);
7303 if (gsi_end_p (psi))
7304 break;
7305 remove_phi_node (&psi, false);
7308 /* Make phi node for trip. */
7309 phi = create_phi_node (trip_main, iter_part_bb);
7310 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7311 UNKNOWN_LOCATION);
7312 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7313 UNKNOWN_LOCATION);
7316 if (!broken_loop)
7317 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7318 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7319 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7320 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7321 recompute_dominator (CDI_DOMINATORS, fin_bb));
7322 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7323 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7324 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7325 recompute_dominator (CDI_DOMINATORS, body_bb));
7327 if (!broken_loop)
7329 struct loop *trip_loop = alloc_loop ();
7330 trip_loop->header = iter_part_bb;
7331 trip_loop->latch = trip_update_bb;
7332 add_loop (trip_loop, iter_part_bb->loop_father);
7334 if (!gimple_omp_for_combined_p (fd->for_stmt))
7336 struct loop *loop = alloc_loop ();
7337 loop->header = body_bb;
7338 if (collapse_bb == NULL)
7339 loop->latch = cont_bb;
7340 add_loop (loop, trip_loop);
7345 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7346 Given parameters:
7347 for (V = N1; V cond N2; V += STEP) BODY;
7349 where COND is "<" or ">" or "!=", we generate pseudocode
7351 for (ind_var = low; ind_var < high; ind_var++)
7353 V = n1 + (ind_var * STEP)
7355 <BODY>
7358 In the above pseudocode, low and high are function parameters of the
7359 child function. In the function below, we are inserting a temp.
7360 variable that will be making a call to two OMP functions that will not be
7361 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7362 with _Cilk_for). These functions are replaced with low and high
7363 by the function that handles taskreg. */
7366 static void
7367 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7369 bool broken_loop = region->cont == NULL;
7370 basic_block entry_bb = region->entry;
7371 basic_block cont_bb = region->cont;
7373 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7374 gcc_assert (broken_loop
7375 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7376 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7377 basic_block l1_bb, l2_bb;
7379 if (!broken_loop)
7381 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7382 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7383 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7384 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7386 else
7388 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7389 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7390 l2_bb = single_succ (l1_bb);
7392 basic_block exit_bb = region->exit;
7393 basic_block l2_dom_bb = NULL;
7395 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7397 /* Below statements until the "tree high_val = ..." are pseudo statements
7398 used to pass information to be used by expand_omp_taskreg.
7399 low_val and high_val will be replaced by the __low and __high
7400 parameter from the child function.
7402 The call_exprs part is a place-holder, it is mainly used
7403 to distinctly identify to the top-level part that this is
7404 where we should put low and high (reasoning given in header
7405 comment). */
7407 tree child_fndecl
7408 = gimple_omp_parallel_child_fn (
7409 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7410 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7411 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7413 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7414 high_val = t;
7415 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7416 low_val = t;
7418 gcc_assert (low_val && high_val);
7420 tree type = TREE_TYPE (low_val);
7421 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7422 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7424 /* Not needed in SSA form right now. */
7425 gcc_assert (!gimple_in_ssa_p (cfun));
7426 if (l2_dom_bb == NULL)
7427 l2_dom_bb = l1_bb;
7429 tree n1 = low_val;
7430 tree n2 = high_val;
7432 gimple stmt = gimple_build_assign (ind_var, n1);
7434 /* Replace the GIMPLE_OMP_FOR statement. */
7435 gsi_replace (&gsi, stmt, true);
7437 if (!broken_loop)
7439 /* Code to control the increment goes in the CONT_BB. */
7440 gsi = gsi_last_bb (cont_bb);
7441 stmt = gsi_stmt (gsi);
7442 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7443 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7444 build_one_cst (type));
7446 /* Replace GIMPLE_OMP_CONTINUE. */
7447 gsi_replace (&gsi, stmt, true);
7450 /* Emit the condition in L1_BB. */
7451 gsi = gsi_after_labels (l1_bb);
7452 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7453 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7454 fd->loop.step);
7455 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7456 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7457 fd->loop.n1, fold_convert (sizetype, t));
7458 else
7459 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7460 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7461 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7462 expand_omp_build_assign (&gsi, fd->loop.v, t);
7464 /* The condition is always '<' since the runtime will fill in the low
7465 and high values. */
7466 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7467 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7469 /* Remove GIMPLE_OMP_RETURN. */
7470 gsi = gsi_last_bb (exit_bb);
7471 gsi_remove (&gsi, true);
7473 /* Connect the new blocks. */
7474 remove_edge (FALLTHRU_EDGE (entry_bb));
7476 edge e, ne;
7477 if (!broken_loop)
7479 remove_edge (BRANCH_EDGE (entry_bb));
7480 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7482 e = BRANCH_EDGE (l1_bb);
7483 ne = FALLTHRU_EDGE (l1_bb);
7484 e->flags = EDGE_TRUE_VALUE;
7486 else
7488 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7490 ne = single_succ_edge (l1_bb);
7491 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7494 ne->flags = EDGE_FALSE_VALUE;
7495 e->probability = REG_BR_PROB_BASE * 7 / 8;
7496 ne->probability = REG_BR_PROB_BASE / 8;
7498 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7499 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7500 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7502 if (!broken_loop)
7504 struct loop *loop = alloc_loop ();
7505 loop->header = l1_bb;
7506 loop->latch = cont_bb;
7507 add_loop (loop, l1_bb->loop_father);
7508 loop->safelen = INT_MAX;
7511 /* Pick the correct library function based on the precision of the
7512 induction variable type. */
7513 tree lib_fun = NULL_TREE;
7514 if (TYPE_PRECISION (type) == 32)
7515 lib_fun = cilk_for_32_fndecl;
7516 else if (TYPE_PRECISION (type) == 64)
7517 lib_fun = cilk_for_64_fndecl;
7518 else
7519 gcc_unreachable ();
7521 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7523 /* WS_ARGS contains the library function flavor to call:
7524 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7525 user-defined grain value. If the user does not define one, then zero
7526 is passed in by the parser. */
7527 vec_alloc (region->ws_args, 2);
7528 region->ws_args->quick_push (lib_fun);
7529 region->ws_args->quick_push (fd->chunk_size);
7532 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7533 loop. Given parameters:
7535 for (V = N1; V cond N2; V += STEP) BODY;
7537 where COND is "<" or ">", we generate pseudocode
7539 V = N1;
7540 goto L1;
7542 BODY;
7543 V += STEP;
7545 if (V cond N2) goto L0; else goto L2;
7548 For collapsed loops, given parameters:
7549 collapse(3)
7550 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7551 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7552 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7553 BODY;
7555 we generate pseudocode
7557 if (cond3 is <)
7558 adj = STEP3 - 1;
7559 else
7560 adj = STEP3 + 1;
7561 count3 = (adj + N32 - N31) / STEP3;
7562 if (cond2 is <)
7563 adj = STEP2 - 1;
7564 else
7565 adj = STEP2 + 1;
7566 count2 = (adj + N22 - N21) / STEP2;
7567 if (cond1 is <)
7568 adj = STEP1 - 1;
7569 else
7570 adj = STEP1 + 1;
7571 count1 = (adj + N12 - N11) / STEP1;
7572 count = count1 * count2 * count3;
7573 V = 0;
7574 V1 = N11;
7575 V2 = N21;
7576 V3 = N31;
7577 goto L1;
7579 BODY;
7580 V += 1;
7581 V3 += STEP3;
7582 V2 += (V3 cond3 N32) ? 0 : STEP2;
7583 V3 = (V3 cond3 N32) ? V3 : N31;
7584 V1 += (V2 cond2 N22) ? 0 : STEP1;
7585 V2 = (V2 cond2 N22) ? V2 : N21;
7587 if (V < count) goto L0; else goto L2;
7592 static void
7593 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7595 tree type, t;
7596 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7597 gimple_stmt_iterator gsi;
7598 gimple stmt;
7599 gcond *cond_stmt;
7600 bool broken_loop = region->cont == NULL;
7601 edge e, ne;
7602 tree *counts = NULL;
7603 int i;
7604 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7605 OMP_CLAUSE_SAFELEN);
7606 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7607 OMP_CLAUSE__SIMDUID_);
7608 tree n1, n2;
7610 type = TREE_TYPE (fd->loop.v);
7611 entry_bb = region->entry;
7612 cont_bb = region->cont;
7613 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7614 gcc_assert (broken_loop
7615 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7616 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7617 if (!broken_loop)
7619 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7620 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7621 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7622 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7624 else
7626 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7627 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7628 l2_bb = single_succ (l1_bb);
7630 exit_bb = region->exit;
7631 l2_dom_bb = NULL;
7633 gsi = gsi_last_bb (entry_bb);
7635 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7636 /* Not needed in SSA form right now. */
7637 gcc_assert (!gimple_in_ssa_p (cfun));
7638 if (fd->collapse > 1)
7640 int first_zero_iter = -1;
7641 basic_block zero_iter_bb = l2_bb;
7643 counts = XALLOCAVEC (tree, fd->collapse);
7644 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7645 zero_iter_bb, first_zero_iter,
7646 l2_dom_bb);
7648 if (l2_dom_bb == NULL)
7649 l2_dom_bb = l1_bb;
7651 n1 = fd->loop.n1;
7652 n2 = fd->loop.n2;
7653 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7655 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7656 OMP_CLAUSE__LOOPTEMP_);
7657 gcc_assert (innerc);
7658 n1 = OMP_CLAUSE_DECL (innerc);
7659 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7660 OMP_CLAUSE__LOOPTEMP_);
7661 gcc_assert (innerc);
7662 n2 = OMP_CLAUSE_DECL (innerc);
7663 expand_omp_build_assign (&gsi, fd->loop.v,
7664 fold_convert (type, n1));
7665 if (fd->collapse > 1)
7667 gsi_prev (&gsi);
7668 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7669 gsi_next (&gsi);
7672 else
7674 expand_omp_build_assign (&gsi, fd->loop.v,
7675 fold_convert (type, fd->loop.n1));
7676 if (fd->collapse > 1)
7677 for (i = 0; i < fd->collapse; i++)
7679 tree itype = TREE_TYPE (fd->loops[i].v);
7680 if (POINTER_TYPE_P (itype))
7681 itype = signed_type_for (itype);
7682 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7683 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7687 /* Remove the GIMPLE_OMP_FOR statement. */
7688 gsi_remove (&gsi, true);
7690 if (!broken_loop)
7692 /* Code to control the increment goes in the CONT_BB. */
7693 gsi = gsi_last_bb (cont_bb);
7694 stmt = gsi_stmt (gsi);
7695 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7697 if (POINTER_TYPE_P (type))
7698 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7699 else
7700 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7701 expand_omp_build_assign (&gsi, fd->loop.v, t);
7703 if (fd->collapse > 1)
7705 i = fd->collapse - 1;
7706 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7708 t = fold_convert (sizetype, fd->loops[i].step);
7709 t = fold_build_pointer_plus (fd->loops[i].v, t);
7711 else
7713 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7714 fd->loops[i].step);
7715 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7716 fd->loops[i].v, t);
7718 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7720 for (i = fd->collapse - 1; i > 0; i--)
7722 tree itype = TREE_TYPE (fd->loops[i].v);
7723 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7724 if (POINTER_TYPE_P (itype2))
7725 itype2 = signed_type_for (itype2);
7726 t = build3 (COND_EXPR, itype2,
7727 build2 (fd->loops[i].cond_code, boolean_type_node,
7728 fd->loops[i].v,
7729 fold_convert (itype, fd->loops[i].n2)),
7730 build_int_cst (itype2, 0),
7731 fold_convert (itype2, fd->loops[i - 1].step));
7732 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7733 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7734 else
7735 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7736 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7738 t = build3 (COND_EXPR, itype,
7739 build2 (fd->loops[i].cond_code, boolean_type_node,
7740 fd->loops[i].v,
7741 fold_convert (itype, fd->loops[i].n2)),
7742 fd->loops[i].v,
7743 fold_convert (itype, fd->loops[i].n1));
7744 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7748 /* Remove GIMPLE_OMP_CONTINUE. */
7749 gsi_remove (&gsi, true);
7752 /* Emit the condition in L1_BB. */
7753 gsi = gsi_start_bb (l1_bb);
7755 t = fold_convert (type, n2);
7756 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7757 false, GSI_CONTINUE_LINKING);
7758 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7759 cond_stmt = gimple_build_cond_empty (t);
7760 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7761 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7762 NULL, NULL)
7763 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7764 NULL, NULL))
7766 gsi = gsi_for_stmt (cond_stmt);
7767 gimple_regimplify_operands (cond_stmt, &gsi);
7770 /* Remove GIMPLE_OMP_RETURN. */
7771 gsi = gsi_last_bb (exit_bb);
7772 gsi_remove (&gsi, true);
7774 /* Connect the new blocks. */
7775 remove_edge (FALLTHRU_EDGE (entry_bb));
7777 if (!broken_loop)
7779 remove_edge (BRANCH_EDGE (entry_bb));
7780 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7782 e = BRANCH_EDGE (l1_bb);
7783 ne = FALLTHRU_EDGE (l1_bb);
7784 e->flags = EDGE_TRUE_VALUE;
7786 else
7788 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7790 ne = single_succ_edge (l1_bb);
7791 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7794 ne->flags = EDGE_FALSE_VALUE;
7795 e->probability = REG_BR_PROB_BASE * 7 / 8;
7796 ne->probability = REG_BR_PROB_BASE / 8;
7798 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7799 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7800 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7802 if (!broken_loop)
7804 struct loop *loop = alloc_loop ();
7805 loop->header = l1_bb;
7806 loop->latch = cont_bb;
7807 add_loop (loop, l1_bb->loop_father);
7808 if (safelen == NULL_TREE)
7809 loop->safelen = INT_MAX;
7810 else
7812 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7813 if (TREE_CODE (safelen) != INTEGER_CST)
7814 loop->safelen = 0;
7815 else if (!tree_fits_uhwi_p (safelen)
7816 || tree_to_uhwi (safelen) > INT_MAX)
7817 loop->safelen = INT_MAX;
7818 else
7819 loop->safelen = tree_to_uhwi (safelen);
7820 if (loop->safelen == 1)
7821 loop->safelen = 0;
7823 if (simduid)
7825 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7826 cfun->has_simduid_loops = true;
7828 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7829 the loop. */
7830 if ((flag_tree_loop_vectorize
7831 || (!global_options_set.x_flag_tree_loop_vectorize
7832 && !global_options_set.x_flag_tree_vectorize))
7833 && flag_tree_loop_optimize
7834 && loop->safelen > 1)
7836 loop->force_vectorize = true;
7837 cfun->has_force_vectorize_loops = true;
7843 /* Expand the OpenMP loop defined by REGION. */
7845 static void
7846 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7848 struct omp_for_data fd;
7849 struct omp_for_data_loop *loops;
7851 loops
7852 = (struct omp_for_data_loop *)
7853 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7854 * sizeof (struct omp_for_data_loop));
7855 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7856 &fd, loops);
7857 region->sched_kind = fd.sched_kind;
7859 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7860 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7861 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7862 if (region->cont)
7864 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7865 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7866 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7868 else
7869 /* If there isn't a continue then this is a degerate case where
7870 the introduction of abnormal edges during lowering will prevent
7871 original loops from being detected. Fix that up. */
7872 loops_state_set (LOOPS_NEED_FIXUP);
7874 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7875 expand_omp_simd (region, &fd);
7876 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7877 expand_cilk_for (region, &fd);
7878 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7879 && !fd.have_ordered)
7881 if (fd.chunk_size == NULL)
7882 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7883 else
7884 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7886 else
7888 int fn_index, start_ix, next_ix;
7890 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7891 == GF_OMP_FOR_KIND_FOR);
7892 if (fd.chunk_size == NULL
7893 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7894 fd.chunk_size = integer_zero_node;
7895 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7896 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7897 ? 3 : fd.sched_kind;
7898 fn_index += fd.have_ordered * 4;
7899 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7900 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7901 if (fd.iter_type == long_long_unsigned_type_node)
7903 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7904 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7905 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7906 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7908 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7909 (enum built_in_function) next_ix, inner_stmt);
7912 if (gimple_in_ssa_p (cfun))
7913 update_ssa (TODO_update_ssa_only_virtuals);
7917 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7919 v = GOMP_sections_start (n);
7921 switch (v)
7923 case 0:
7924 goto L2;
7925 case 1:
7926 section 1;
7927 goto L1;
7928 case 2:
7930 case n:
7932 default:
7933 abort ();
7936 v = GOMP_sections_next ();
7937 goto L0;
7939 reduction;
7941 If this is a combined parallel sections, replace the call to
7942 GOMP_sections_start with call to GOMP_sections_next. */
7944 static void
7945 expand_omp_sections (struct omp_region *region)
7947 tree t, u, vin = NULL, vmain, vnext, l2;
7948 unsigned len;
7949 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7950 gimple_stmt_iterator si, switch_si;
7951 gomp_sections *sections_stmt;
7952 gimple stmt;
7953 gomp_continue *cont;
7954 edge_iterator ei;
7955 edge e;
7956 struct omp_region *inner;
7957 unsigned i, casei;
7958 bool exit_reachable = region->cont != NULL;
7960 gcc_assert (region->exit != NULL);
7961 entry_bb = region->entry;
7962 l0_bb = single_succ (entry_bb);
7963 l1_bb = region->cont;
7964 l2_bb = region->exit;
7965 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7966 l2 = gimple_block_label (l2_bb);
7967 else
7969 /* This can happen if there are reductions. */
7970 len = EDGE_COUNT (l0_bb->succs);
7971 gcc_assert (len > 0);
7972 e = EDGE_SUCC (l0_bb, len - 1);
7973 si = gsi_last_bb (e->dest);
7974 l2 = NULL_TREE;
7975 if (gsi_end_p (si)
7976 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7977 l2 = gimple_block_label (e->dest);
7978 else
7979 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7981 si = gsi_last_bb (e->dest);
7982 if (gsi_end_p (si)
7983 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7985 l2 = gimple_block_label (e->dest);
7986 break;
7990 if (exit_reachable)
7991 default_bb = create_empty_bb (l1_bb->prev_bb);
7992 else
7993 default_bb = create_empty_bb (l0_bb);
7995 /* We will build a switch() with enough cases for all the
7996 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7997 and a default case to abort if something goes wrong. */
7998 len = EDGE_COUNT (l0_bb->succs);
8000 /* Use vec::quick_push on label_vec throughout, since we know the size
8001 in advance. */
8002 auto_vec<tree> label_vec (len);
8004 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
8005 GIMPLE_OMP_SECTIONS statement. */
8006 si = gsi_last_bb (entry_bb);
8007 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
8008 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8009 vin = gimple_omp_sections_control (sections_stmt);
8010 if (!is_combined_parallel (region))
8012 /* If we are not inside a combined parallel+sections region,
8013 call GOMP_sections_start. */
8014 t = build_int_cst (unsigned_type_node, len - 1);
8015 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8016 stmt = gimple_build_call (u, 1, t);
8018 else
8020 /* Otherwise, call GOMP_sections_next. */
8021 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8022 stmt = gimple_build_call (u, 0);
8024 gimple_call_set_lhs (stmt, vin);
8025 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8026 gsi_remove (&si, true);
8028 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8029 L0_BB. */
8030 switch_si = gsi_last_bb (l0_bb);
8031 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8032 if (exit_reachable)
8034 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8035 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8036 vmain = gimple_omp_continue_control_use (cont);
8037 vnext = gimple_omp_continue_control_def (cont);
8039 else
8041 vmain = vin;
8042 vnext = NULL_TREE;
8045 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8046 label_vec.quick_push (t);
8047 i = 1;
8049 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8050 for (inner = region->inner, casei = 1;
8051 inner;
8052 inner = inner->next, i++, casei++)
8054 basic_block s_entry_bb, s_exit_bb;
8056 /* Skip optional reduction region. */
8057 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8059 --i;
8060 --casei;
8061 continue;
8064 s_entry_bb = inner->entry;
8065 s_exit_bb = inner->exit;
8067 t = gimple_block_label (s_entry_bb);
8068 u = build_int_cst (unsigned_type_node, casei);
8069 u = build_case_label (u, NULL, t);
8070 label_vec.quick_push (u);
8072 si = gsi_last_bb (s_entry_bb);
8073 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8074 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8075 gsi_remove (&si, true);
8076 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8078 if (s_exit_bb == NULL)
8079 continue;
8081 si = gsi_last_bb (s_exit_bb);
8082 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8083 gsi_remove (&si, true);
8085 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8088 /* Error handling code goes in DEFAULT_BB. */
8089 t = gimple_block_label (default_bb);
8090 u = build_case_label (NULL, NULL, t);
8091 make_edge (l0_bb, default_bb, 0);
8092 add_bb_to_loop (default_bb, current_loops->tree_root);
8094 stmt = gimple_build_switch (vmain, u, label_vec);
8095 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8096 gsi_remove (&switch_si, true);
8098 si = gsi_start_bb (default_bb);
8099 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8100 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8102 if (exit_reachable)
8104 tree bfn_decl;
8106 /* Code to get the next section goes in L1_BB. */
8107 si = gsi_last_bb (l1_bb);
8108 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8110 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8111 stmt = gimple_build_call (bfn_decl, 0);
8112 gimple_call_set_lhs (stmt, vnext);
8113 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8114 gsi_remove (&si, true);
8116 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8119 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8120 si = gsi_last_bb (l2_bb);
8121 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8122 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8123 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8124 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8125 else
8126 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8127 stmt = gimple_build_call (t, 0);
8128 if (gimple_omp_return_lhs (gsi_stmt (si)))
8129 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8130 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8131 gsi_remove (&si, true);
8133 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8137 /* Expand code for an OpenMP single directive. We've already expanded
8138 much of the code, here we simply place the GOMP_barrier call. */
8140 static void
8141 expand_omp_single (struct omp_region *region)
8143 basic_block entry_bb, exit_bb;
8144 gimple_stmt_iterator si;
8146 entry_bb = region->entry;
8147 exit_bb = region->exit;
8149 si = gsi_last_bb (entry_bb);
8150 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8151 gsi_remove (&si, true);
8152 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8154 si = gsi_last_bb (exit_bb);
8155 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8157 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8158 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8160 gsi_remove (&si, true);
8161 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8165 /* Generic expansion for OpenMP synchronization directives: master,
8166 ordered and critical. All we need to do here is remove the entry
8167 and exit markers for REGION. */
8169 static void
8170 expand_omp_synch (struct omp_region *region)
8172 basic_block entry_bb, exit_bb;
8173 gimple_stmt_iterator si;
8175 entry_bb = region->entry;
8176 exit_bb = region->exit;
8178 si = gsi_last_bb (entry_bb);
8179 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8180 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8181 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8182 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8183 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8184 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8185 gsi_remove (&si, true);
8186 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8188 if (exit_bb)
8190 si = gsi_last_bb (exit_bb);
8191 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8192 gsi_remove (&si, true);
8193 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8197 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8198 operation as a normal volatile load. */
8200 static bool
8201 expand_omp_atomic_load (basic_block load_bb, tree addr,
8202 tree loaded_val, int index)
8204 enum built_in_function tmpbase;
8205 gimple_stmt_iterator gsi;
8206 basic_block store_bb;
8207 location_t loc;
8208 gimple stmt;
8209 tree decl, call, type, itype;
8211 gsi = gsi_last_bb (load_bb);
8212 stmt = gsi_stmt (gsi);
8213 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8214 loc = gimple_location (stmt);
8216 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8217 is smaller than word size, then expand_atomic_load assumes that the load
8218 is atomic. We could avoid the builtin entirely in this case. */
8220 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8221 decl = builtin_decl_explicit (tmpbase);
8222 if (decl == NULL_TREE)
8223 return false;
8225 type = TREE_TYPE (loaded_val);
8226 itype = TREE_TYPE (TREE_TYPE (decl));
8228 call = build_call_expr_loc (loc, decl, 2, addr,
8229 build_int_cst (NULL,
8230 gimple_omp_atomic_seq_cst_p (stmt)
8231 ? MEMMODEL_SEQ_CST
8232 : MEMMODEL_RELAXED));
8233 if (!useless_type_conversion_p (type, itype))
8234 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8235 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8237 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8238 gsi_remove (&gsi, true);
8240 store_bb = single_succ (load_bb);
8241 gsi = gsi_last_bb (store_bb);
8242 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8243 gsi_remove (&gsi, true);
8245 if (gimple_in_ssa_p (cfun))
8246 update_ssa (TODO_update_ssa_no_phi);
8248 return true;
8251 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8252 operation as a normal volatile store. */
8254 static bool
8255 expand_omp_atomic_store (basic_block load_bb, tree addr,
8256 tree loaded_val, tree stored_val, int index)
8258 enum built_in_function tmpbase;
8259 gimple_stmt_iterator gsi;
8260 basic_block store_bb = single_succ (load_bb);
8261 location_t loc;
8262 gimple stmt;
8263 tree decl, call, type, itype;
8264 machine_mode imode;
8265 bool exchange;
8267 gsi = gsi_last_bb (load_bb);
8268 stmt = gsi_stmt (gsi);
8269 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8271 /* If the load value is needed, then this isn't a store but an exchange. */
8272 exchange = gimple_omp_atomic_need_value_p (stmt);
8274 gsi = gsi_last_bb (store_bb);
8275 stmt = gsi_stmt (gsi);
8276 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8277 loc = gimple_location (stmt);
8279 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8280 is smaller than word size, then expand_atomic_store assumes that the store
8281 is atomic. We could avoid the builtin entirely in this case. */
8283 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8284 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8285 decl = builtin_decl_explicit (tmpbase);
8286 if (decl == NULL_TREE)
8287 return false;
8289 type = TREE_TYPE (stored_val);
8291 /* Dig out the type of the function's second argument. */
8292 itype = TREE_TYPE (decl);
8293 itype = TYPE_ARG_TYPES (itype);
8294 itype = TREE_CHAIN (itype);
8295 itype = TREE_VALUE (itype);
8296 imode = TYPE_MODE (itype);
8298 if (exchange && !can_atomic_exchange_p (imode, true))
8299 return false;
8301 if (!useless_type_conversion_p (itype, type))
8302 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8303 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8304 build_int_cst (NULL,
8305 gimple_omp_atomic_seq_cst_p (stmt)
8306 ? MEMMODEL_SEQ_CST
8307 : MEMMODEL_RELAXED));
8308 if (exchange)
8310 if (!useless_type_conversion_p (type, itype))
8311 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8312 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8315 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8316 gsi_remove (&gsi, true);
8318 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8319 gsi = gsi_last_bb (load_bb);
8320 gsi_remove (&gsi, true);
8322 if (gimple_in_ssa_p (cfun))
8323 update_ssa (TODO_update_ssa_no_phi);
8325 return true;
8328 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8329 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8330 size of the data type, and thus usable to find the index of the builtin
8331 decl. Returns false if the expression is not of the proper form. */
8333 static bool
8334 expand_omp_atomic_fetch_op (basic_block load_bb,
8335 tree addr, tree loaded_val,
8336 tree stored_val, int index)
8338 enum built_in_function oldbase, newbase, tmpbase;
8339 tree decl, itype, call;
8340 tree lhs, rhs;
8341 basic_block store_bb = single_succ (load_bb);
8342 gimple_stmt_iterator gsi;
8343 gimple stmt;
8344 location_t loc;
8345 enum tree_code code;
8346 bool need_old, need_new;
8347 machine_mode imode;
8348 bool seq_cst;
8350 /* We expect to find the following sequences:
8352 load_bb:
8353 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8355 store_bb:
8356 val = tmp OP something; (or: something OP tmp)
8357 GIMPLE_OMP_STORE (val)
8359 ???FIXME: Allow a more flexible sequence.
8360 Perhaps use data flow to pick the statements.
8364 gsi = gsi_after_labels (store_bb);
8365 stmt = gsi_stmt (gsi);
8366 loc = gimple_location (stmt);
8367 if (!is_gimple_assign (stmt))
8368 return false;
8369 gsi_next (&gsi);
8370 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8371 return false;
8372 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8373 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8374 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8375 gcc_checking_assert (!need_old || !need_new);
8377 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8378 return false;
8380 /* Check for one of the supported fetch-op operations. */
8381 code = gimple_assign_rhs_code (stmt);
8382 switch (code)
8384 case PLUS_EXPR:
8385 case POINTER_PLUS_EXPR:
8386 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8387 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8388 break;
8389 case MINUS_EXPR:
8390 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8391 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8392 break;
8393 case BIT_AND_EXPR:
8394 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8395 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8396 break;
8397 case BIT_IOR_EXPR:
8398 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8399 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8400 break;
8401 case BIT_XOR_EXPR:
8402 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8403 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8404 break;
8405 default:
8406 return false;
8409 /* Make sure the expression is of the proper form. */
8410 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8411 rhs = gimple_assign_rhs2 (stmt);
8412 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8413 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8414 rhs = gimple_assign_rhs1 (stmt);
8415 else
8416 return false;
8418 tmpbase = ((enum built_in_function)
8419 ((need_new ? newbase : oldbase) + index + 1));
8420 decl = builtin_decl_explicit (tmpbase);
8421 if (decl == NULL_TREE)
8422 return false;
8423 itype = TREE_TYPE (TREE_TYPE (decl));
8424 imode = TYPE_MODE (itype);
8426 /* We could test all of the various optabs involved, but the fact of the
8427 matter is that (with the exception of i486 vs i586 and xadd) all targets
8428 that support any atomic operaton optab also implements compare-and-swap.
8429 Let optabs.c take care of expanding any compare-and-swap loop. */
8430 if (!can_compare_and_swap_p (imode, true))
8431 return false;
8433 gsi = gsi_last_bb (load_bb);
8434 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8436 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8437 It only requires that the operation happen atomically. Thus we can
8438 use the RELAXED memory model. */
8439 call = build_call_expr_loc (loc, decl, 3, addr,
8440 fold_convert_loc (loc, itype, rhs),
8441 build_int_cst (NULL,
8442 seq_cst ? MEMMODEL_SEQ_CST
8443 : MEMMODEL_RELAXED));
8445 if (need_old || need_new)
8447 lhs = need_old ? loaded_val : stored_val;
8448 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8449 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8451 else
8452 call = fold_convert_loc (loc, void_type_node, call);
8453 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8454 gsi_remove (&gsi, true);
8456 gsi = gsi_last_bb (store_bb);
8457 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8458 gsi_remove (&gsi, true);
8459 gsi = gsi_last_bb (store_bb);
8460 gsi_remove (&gsi, true);
8462 if (gimple_in_ssa_p (cfun))
8463 update_ssa (TODO_update_ssa_no_phi);
8465 return true;
8468 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8470 oldval = *addr;
8471 repeat:
8472 newval = rhs; // with oldval replacing *addr in rhs
8473 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8474 if (oldval != newval)
8475 goto repeat;
8477 INDEX is log2 of the size of the data type, and thus usable to find the
8478 index of the builtin decl. */
8480 static bool
8481 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8482 tree addr, tree loaded_val, tree stored_val,
8483 int index)
8485 tree loadedi, storedi, initial, new_storedi, old_vali;
8486 tree type, itype, cmpxchg, iaddr;
8487 gimple_stmt_iterator si;
8488 basic_block loop_header = single_succ (load_bb);
8489 gimple phi, stmt;
8490 edge e;
8491 enum built_in_function fncode;
8493 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8494 order to use the RELAXED memory model effectively. */
8495 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8496 + index + 1);
8497 cmpxchg = builtin_decl_explicit (fncode);
8498 if (cmpxchg == NULL_TREE)
8499 return false;
8500 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8501 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8503 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8504 return false;
8506 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8507 si = gsi_last_bb (load_bb);
8508 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8510 /* For floating-point values, we'll need to view-convert them to integers
8511 so that we can perform the atomic compare and swap. Simplify the
8512 following code by always setting up the "i"ntegral variables. */
8513 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8515 tree iaddr_val;
8517 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8518 true));
8519 iaddr_val
8520 = force_gimple_operand_gsi (&si,
8521 fold_convert (TREE_TYPE (iaddr), addr),
8522 false, NULL_TREE, true, GSI_SAME_STMT);
8523 stmt = gimple_build_assign (iaddr, iaddr_val);
8524 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8525 loadedi = create_tmp_var (itype);
8526 if (gimple_in_ssa_p (cfun))
8527 loadedi = make_ssa_name (loadedi);
8529 else
8531 iaddr = addr;
8532 loadedi = loaded_val;
8535 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8536 tree loaddecl = builtin_decl_explicit (fncode);
8537 if (loaddecl)
8538 initial
8539 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8540 build_call_expr (loaddecl, 2, iaddr,
8541 build_int_cst (NULL_TREE,
8542 MEMMODEL_RELAXED)));
8543 else
8544 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8545 build_int_cst (TREE_TYPE (iaddr), 0));
8547 initial
8548 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8549 GSI_SAME_STMT);
8551 /* Move the value to the LOADEDI temporary. */
8552 if (gimple_in_ssa_p (cfun))
8554 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8555 phi = create_phi_node (loadedi, loop_header);
8556 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8557 initial);
8559 else
8560 gsi_insert_before (&si,
8561 gimple_build_assign (loadedi, initial),
8562 GSI_SAME_STMT);
8563 if (loadedi != loaded_val)
8565 gimple_stmt_iterator gsi2;
8566 tree x;
8568 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8569 gsi2 = gsi_start_bb (loop_header);
8570 if (gimple_in_ssa_p (cfun))
8572 gassign *stmt;
8573 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8574 true, GSI_SAME_STMT);
8575 stmt = gimple_build_assign (loaded_val, x);
8576 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8578 else
8580 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8581 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8582 true, GSI_SAME_STMT);
8585 gsi_remove (&si, true);
8587 si = gsi_last_bb (store_bb);
8588 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8590 if (iaddr == addr)
8591 storedi = stored_val;
8592 else
8593 storedi =
8594 force_gimple_operand_gsi (&si,
8595 build1 (VIEW_CONVERT_EXPR, itype,
8596 stored_val), true, NULL_TREE, true,
8597 GSI_SAME_STMT);
8599 /* Build the compare&swap statement. */
8600 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8601 new_storedi = force_gimple_operand_gsi (&si,
8602 fold_convert (TREE_TYPE (loadedi),
8603 new_storedi),
8604 true, NULL_TREE,
8605 true, GSI_SAME_STMT);
8607 if (gimple_in_ssa_p (cfun))
8608 old_vali = loadedi;
8609 else
8611 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8612 stmt = gimple_build_assign (old_vali, loadedi);
8613 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8615 stmt = gimple_build_assign (loadedi, new_storedi);
8616 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8619 /* Note that we always perform the comparison as an integer, even for
8620 floating point. This allows the atomic operation to properly
8621 succeed even with NaNs and -0.0. */
8622 stmt = gimple_build_cond_empty
8623 (build2 (NE_EXPR, boolean_type_node,
8624 new_storedi, old_vali));
8625 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8627 /* Update cfg. */
8628 e = single_succ_edge (store_bb);
8629 e->flags &= ~EDGE_FALLTHRU;
8630 e->flags |= EDGE_FALSE_VALUE;
8632 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8634 /* Copy the new value to loadedi (we already did that before the condition
8635 if we are not in SSA). */
8636 if (gimple_in_ssa_p (cfun))
8638 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8639 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8642 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8643 gsi_remove (&si, true);
8645 struct loop *loop = alloc_loop ();
8646 loop->header = loop_header;
8647 loop->latch = store_bb;
8648 add_loop (loop, loop_header->loop_father);
8650 if (gimple_in_ssa_p (cfun))
8651 update_ssa (TODO_update_ssa_no_phi);
8653 return true;
8656 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8658 GOMP_atomic_start ();
8659 *addr = rhs;
8660 GOMP_atomic_end ();
8662 The result is not globally atomic, but works so long as all parallel
8663 references are within #pragma omp atomic directives. According to
8664 responses received from omp@openmp.org, appears to be within spec.
8665 Which makes sense, since that's how several other compilers handle
8666 this situation as well.
8667 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8668 expanding. STORED_VAL is the operand of the matching
8669 GIMPLE_OMP_ATOMIC_STORE.
8671 We replace
8672 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8673 loaded_val = *addr;
8675 and replace
8676 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8677 *addr = stored_val;
8680 static bool
8681 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8682 tree addr, tree loaded_val, tree stored_val)
8684 gimple_stmt_iterator si;
8685 gassign *stmt;
8686 tree t;
8688 si = gsi_last_bb (load_bb);
8689 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8691 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8692 t = build_call_expr (t, 0);
8693 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8695 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8696 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8697 gsi_remove (&si, true);
8699 si = gsi_last_bb (store_bb);
8700 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8702 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8703 stored_val);
8704 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8706 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8707 t = build_call_expr (t, 0);
8708 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8709 gsi_remove (&si, true);
8711 if (gimple_in_ssa_p (cfun))
8712 update_ssa (TODO_update_ssa_no_phi);
8713 return true;
8716 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8717 using expand_omp_atomic_fetch_op. If it failed, we try to
8718 call expand_omp_atomic_pipeline, and if it fails too, the
8719 ultimate fallback is wrapping the operation in a mutex
8720 (expand_omp_atomic_mutex). REGION is the atomic region built
8721 by build_omp_regions_1(). */
8723 static void
8724 expand_omp_atomic (struct omp_region *region)
8726 basic_block load_bb = region->entry, store_bb = region->exit;
8727 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8728 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8729 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8730 tree addr = gimple_omp_atomic_load_rhs (load);
8731 tree stored_val = gimple_omp_atomic_store_val (store);
8732 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8733 HOST_WIDE_INT index;
8735 /* Make sure the type is one of the supported sizes. */
8736 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8737 index = exact_log2 (index);
8738 if (index >= 0 && index <= 4)
8740 unsigned int align = TYPE_ALIGN_UNIT (type);
8742 /* __sync builtins require strict data alignment. */
8743 if (exact_log2 (align) >= index)
8745 /* Atomic load. */
8746 if (loaded_val == stored_val
8747 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8748 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8749 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8750 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8751 return;
8753 /* Atomic store. */
8754 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8755 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8756 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8757 && store_bb == single_succ (load_bb)
8758 && first_stmt (store_bb) == store
8759 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8760 stored_val, index))
8761 return;
8763 /* When possible, use specialized atomic update functions. */
8764 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8765 && store_bb == single_succ (load_bb)
8766 && expand_omp_atomic_fetch_op (load_bb, addr,
8767 loaded_val, stored_val, index))
8768 return;
8770 /* If we don't have specialized __sync builtins, try and implement
8771 as a compare and swap loop. */
8772 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8773 loaded_val, stored_val, index))
8774 return;
8778 /* The ultimate fallback is wrapping the operation in a mutex. */
8779 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8783 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8785 static void
8786 expand_omp_target (struct omp_region *region)
8788 basic_block entry_bb, exit_bb, new_bb;
8789 struct function *child_cfun;
8790 tree child_fn, block, t;
8791 gimple_stmt_iterator gsi;
8792 gomp_target *entry_stmt;
8793 gimple stmt;
8794 edge e;
8795 bool offloaded, data_region;
8797 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8798 new_bb = region->entry;
8800 offloaded = is_gimple_omp_offloaded (entry_stmt);
8801 switch (gimple_omp_target_kind (entry_stmt))
8803 case GF_OMP_TARGET_KIND_REGION:
8804 case GF_OMP_TARGET_KIND_UPDATE:
8805 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8806 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8807 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8808 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8809 data_region = false;
8810 break;
8811 case GF_OMP_TARGET_KIND_DATA:
8812 case GF_OMP_TARGET_KIND_OACC_DATA:
8813 data_region = true;
8814 break;
8815 default:
8816 gcc_unreachable ();
8819 child_fn = NULL_TREE;
8820 child_cfun = NULL;
8821 if (offloaded)
8823 child_fn = gimple_omp_target_child_fn (entry_stmt);
8824 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8827 /* Supported by expand_omp_taskreg, but not here. */
8828 if (child_cfun != NULL)
8829 gcc_assert (!child_cfun->cfg);
8830 gcc_assert (!gimple_in_ssa_p (cfun));
8832 entry_bb = region->entry;
8833 exit_bb = region->exit;
8835 if (offloaded)
8837 unsigned srcidx, dstidx, num;
8839 /* If the offloading region needs data sent from the parent
8840 function, then the very first statement (except possible
8841 tree profile counter updates) of the offloading body
8842 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8843 &.OMP_DATA_O is passed as an argument to the child function,
8844 we need to replace it with the argument as seen by the child
8845 function.
8847 In most cases, this will end up being the identity assignment
8848 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8849 a function call that has been inlined, the original PARM_DECL
8850 .OMP_DATA_I may have been converted into a different local
8851 variable. In which case, we need to keep the assignment. */
8852 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8853 if (data_arg)
8855 basic_block entry_succ_bb = single_succ (entry_bb);
8856 gimple_stmt_iterator gsi;
8857 tree arg;
8858 gimple tgtcopy_stmt = NULL;
8859 tree sender = TREE_VEC_ELT (data_arg, 0);
8861 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8863 gcc_assert (!gsi_end_p (gsi));
8864 stmt = gsi_stmt (gsi);
8865 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8866 continue;
8868 if (gimple_num_ops (stmt) == 2)
8870 tree arg = gimple_assign_rhs1 (stmt);
8872 /* We're ignoring the subcode because we're
8873 effectively doing a STRIP_NOPS. */
8875 if (TREE_CODE (arg) == ADDR_EXPR
8876 && TREE_OPERAND (arg, 0) == sender)
8878 tgtcopy_stmt = stmt;
8879 break;
8884 gcc_assert (tgtcopy_stmt != NULL);
8885 arg = DECL_ARGUMENTS (child_fn);
8887 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8888 gsi_remove (&gsi, true);
8891 /* Declare local variables needed in CHILD_CFUN. */
8892 block = DECL_INITIAL (child_fn);
8893 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8894 /* The gimplifier could record temporaries in the offloading block
8895 rather than in containing function's local_decls chain,
8896 which would mean cgraph missed finalizing them. Do it now. */
8897 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8898 if (TREE_CODE (t) == VAR_DECL
8899 && TREE_STATIC (t)
8900 && !DECL_EXTERNAL (t))
8901 varpool_node::finalize_decl (t);
8902 DECL_SAVED_TREE (child_fn) = NULL;
8903 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8904 gimple_set_body (child_fn, NULL);
8905 TREE_USED (block) = 1;
8907 /* Reset DECL_CONTEXT on function arguments. */
8908 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8909 DECL_CONTEXT (t) = child_fn;
8911 /* Split ENTRY_BB at GIMPLE_*,
8912 so that it can be moved to the child function. */
8913 gsi = gsi_last_bb (entry_bb);
8914 stmt = gsi_stmt (gsi);
8915 gcc_assert (stmt &&
8916 gimple_code (stmt) == gimple_code (entry_stmt));
8917 gsi_remove (&gsi, true);
8918 e = split_block (entry_bb, stmt);
8919 entry_bb = e->dest;
8920 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8922 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8923 if (exit_bb)
8925 gsi = gsi_last_bb (exit_bb);
8926 gcc_assert (!gsi_end_p (gsi)
8927 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8928 stmt = gimple_build_return (NULL);
8929 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8930 gsi_remove (&gsi, true);
8933 /* Move the offloading region into CHILD_CFUN. */
8935 block = gimple_block (entry_stmt);
8937 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8938 if (exit_bb)
8939 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8940 /* When the OMP expansion process cannot guarantee an up-to-date
8941 loop tree arrange for the child function to fixup loops. */
8942 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8943 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8945 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8946 num = vec_safe_length (child_cfun->local_decls);
8947 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8949 t = (*child_cfun->local_decls)[srcidx];
8950 if (DECL_CONTEXT (t) == cfun->decl)
8951 continue;
8952 if (srcidx != dstidx)
8953 (*child_cfun->local_decls)[dstidx] = t;
8954 dstidx++;
8956 if (dstidx != num)
8957 vec_safe_truncate (child_cfun->local_decls, dstidx);
8959 /* Inform the callgraph about the new function. */
8960 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8961 cgraph_node::add_new_function (child_fn, true);
8963 #ifdef ENABLE_OFFLOADING
8964 /* Add the new function to the offload table. */
8965 vec_safe_push (offload_funcs, child_fn);
8966 #endif
8968 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8969 fixed in a following pass. */
8970 push_cfun (child_cfun);
8971 cgraph_edge::rebuild_edges ();
8973 #ifdef ENABLE_OFFLOADING
8974 /* Prevent IPA from removing child_fn as unreachable, since there are no
8975 refs from the parent function to child_fn in offload LTO mode. */
8976 struct cgraph_node *node = cgraph_node::get (child_fn);
8977 node->mark_force_output ();
8978 #endif
8980 /* Some EH regions might become dead, see PR34608. If
8981 pass_cleanup_cfg isn't the first pass to happen with the
8982 new child, these dead EH edges might cause problems.
8983 Clean them up now. */
8984 if (flag_exceptions)
8986 basic_block bb;
8987 bool changed = false;
8989 FOR_EACH_BB_FN (bb, cfun)
8990 changed |= gimple_purge_dead_eh_edges (bb);
8991 if (changed)
8992 cleanup_tree_cfg ();
8994 pop_cfun ();
8997 /* Emit a library call to launch the offloading region, or do data
8998 transfers. */
8999 tree t1, t2, t3, t4, device, cond, c, clauses;
9000 enum built_in_function start_ix;
9001 location_t clause_loc;
9003 switch (gimple_omp_target_kind (entry_stmt))
9005 case GF_OMP_TARGET_KIND_REGION:
9006 start_ix = BUILT_IN_GOMP_TARGET;
9007 break;
9008 case GF_OMP_TARGET_KIND_DATA:
9009 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9010 break;
9011 case GF_OMP_TARGET_KIND_UPDATE:
9012 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9013 break;
9014 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9015 start_ix = BUILT_IN_GOACC_PARALLEL;
9016 break;
9017 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9018 start_ix = BUILT_IN_GOACC_KERNELS;
9019 break;
9020 case GF_OMP_TARGET_KIND_OACC_DATA:
9021 start_ix = BUILT_IN_GOACC_DATA_START;
9022 break;
9023 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9024 start_ix = BUILT_IN_GOACC_UPDATE;
9025 break;
9026 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9027 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9028 break;
9029 default:
9030 gcc_unreachable ();
9033 clauses = gimple_omp_target_clauses (entry_stmt);
9035 /* By default, the value of DEVICE is -1 (let runtime library choose)
9036 and there is no conditional. */
9037 cond = NULL_TREE;
9038 device = build_int_cst (integer_type_node, -1);
9040 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9041 if (c)
9042 cond = OMP_CLAUSE_IF_EXPR (c);
9044 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9045 if (c)
9047 /* Even if we pass it to all library function calls, it is currently only
9048 defined/used for the OpenMP target ones. */
9049 gcc_assert (start_ix == BUILT_IN_GOMP_TARGET
9050 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9051 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9053 device = OMP_CLAUSE_DEVICE_ID (c);
9054 clause_loc = OMP_CLAUSE_LOCATION (c);
9056 else
9057 clause_loc = gimple_location (entry_stmt);
9059 /* Ensure 'device' is of the correct type. */
9060 device = fold_convert_loc (clause_loc, integer_type_node, device);
9062 /* If we found the clause 'if (cond)', build
9063 (cond ? device : -2). */
9064 if (cond)
9066 cond = gimple_boolify (cond);
9068 basic_block cond_bb, then_bb, else_bb;
9069 edge e;
9070 tree tmp_var;
9072 tmp_var = create_tmp_var (TREE_TYPE (device));
9073 if (offloaded)
9074 e = split_block (new_bb, NULL);
9075 else
9077 gsi = gsi_last_bb (new_bb);
9078 gsi_prev (&gsi);
9079 e = split_block (new_bb, gsi_stmt (gsi));
9081 cond_bb = e->src;
9082 new_bb = e->dest;
9083 remove_edge (e);
9085 then_bb = create_empty_bb (cond_bb);
9086 else_bb = create_empty_bb (then_bb);
9087 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9088 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9090 stmt = gimple_build_cond_empty (cond);
9091 gsi = gsi_last_bb (cond_bb);
9092 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9094 gsi = gsi_start_bb (then_bb);
9095 stmt = gimple_build_assign (tmp_var, device);
9096 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9098 gsi = gsi_start_bb (else_bb);
9099 stmt = gimple_build_assign (tmp_var,
9100 build_int_cst (integer_type_node, -2));
9101 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9103 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9104 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9105 add_bb_to_loop (then_bb, cond_bb->loop_father);
9106 add_bb_to_loop (else_bb, cond_bb->loop_father);
9107 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9108 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9110 device = tmp_var;
9113 gsi = gsi_last_bb (new_bb);
9114 t = gimple_omp_target_data_arg (entry_stmt);
9115 if (t == NULL)
9117 t1 = size_zero_node;
9118 t2 = build_zero_cst (ptr_type_node);
9119 t3 = t2;
9120 t4 = t2;
9122 else
9124 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9125 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9126 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9127 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9128 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9131 gimple g;
9132 tree offload_table = get_offload_symbol_decl ();
9133 vec<tree> *args;
9134 /* The maximum number used by any start_ix, without varargs. */
9135 unsigned int argcnt = 12;
9137 vec_alloc (args, argcnt);
9138 args->quick_push (device);
9139 if (offloaded)
9140 args->quick_push (build_fold_addr_expr (child_fn));
9141 args->quick_push (build_fold_addr_expr (offload_table));
9142 args->quick_push (t1);
9143 args->quick_push (t2);
9144 args->quick_push (t3);
9145 args->quick_push (t4);
9146 switch (start_ix)
9148 case BUILT_IN_GOACC_DATA_START:
9149 case BUILT_IN_GOMP_TARGET:
9150 case BUILT_IN_GOMP_TARGET_DATA:
9151 case BUILT_IN_GOMP_TARGET_UPDATE:
9152 break;
9153 case BUILT_IN_GOACC_KERNELS:
9154 case BUILT_IN_GOACC_PARALLEL:
9156 tree t_num_gangs, t_num_workers, t_vector_length;
9158 /* Default values for num_gangs, num_workers, and vector_length. */
9159 t_num_gangs = t_num_workers = t_vector_length
9160 = fold_convert_loc (gimple_location (entry_stmt),
9161 integer_type_node, integer_one_node);
9162 /* ..., but if present, use the value specified by the respective
9163 clause, making sure that are of the correct type. */
9164 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9165 if (c)
9166 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9167 integer_type_node,
9168 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9169 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9170 if (c)
9171 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9172 integer_type_node,
9173 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9174 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9175 if (c)
9176 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9177 integer_type_node,
9178 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9179 args->quick_push (t_num_gangs);
9180 args->quick_push (t_num_workers);
9181 args->quick_push (t_vector_length);
9183 /* FALLTHRU */
9184 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9185 case BUILT_IN_GOACC_UPDATE:
9187 tree t_async;
9188 int t_wait_idx;
9190 /* Default values for t_async. */
9191 /* TODO: XXX FIX -2. */
9192 t_async = fold_convert_loc (gimple_location (entry_stmt),
9193 integer_type_node,
9194 build_int_cst (integer_type_node, -2));
9195 /* ..., but if present, use the value specified by the respective
9196 clause, making sure that is of the correct type. */
9197 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9198 if (c)
9199 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9200 integer_type_node,
9201 OMP_CLAUSE_ASYNC_EXPR (c));
9203 args->quick_push (t_async);
9204 /* Save the index, and... */
9205 t_wait_idx = args->length ();
9206 /* ... push a default value. */
9207 args->quick_push (fold_convert_loc (gimple_location (entry_stmt),
9208 integer_type_node,
9209 integer_zero_node));
9210 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9211 if (c)
9213 int n = 0;
9215 for (; c; c = OMP_CLAUSE_CHAIN (c))
9217 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9219 args->safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9220 integer_type_node,
9221 OMP_CLAUSE_WAIT_EXPR (c)));
9222 n++;
9226 /* Now that we know the number, replace the default value. */
9227 args->ordered_remove (t_wait_idx);
9228 args->quick_insert (t_wait_idx,
9229 fold_convert_loc (gimple_location (entry_stmt),
9230 integer_type_node,
9231 build_int_cst (integer_type_node, n)));
9234 break;
9235 default:
9236 gcc_unreachable ();
9239 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), *args);
9240 args->release ();
9241 gimple_set_location (g, gimple_location (entry_stmt));
9242 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9243 if (!offloaded)
9245 g = gsi_stmt (gsi);
9246 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9247 gsi_remove (&gsi, true);
9249 if (data_region
9250 && region->exit)
9252 gsi = gsi_last_bb (region->exit);
9253 g = gsi_stmt (gsi);
9254 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9255 gsi_remove (&gsi, true);
9260 /* Expand the parallel region tree rooted at REGION. Expansion
9261 proceeds in depth-first order. Innermost regions are expanded
9262 first. This way, parallel regions that require a new function to
9263 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9264 internal dependencies in their body. */
9266 static void
9267 expand_omp (struct omp_region *region)
9269 while (region)
9271 location_t saved_location;
9272 gimple inner_stmt = NULL;
9274 /* First, determine whether this is a combined parallel+workshare
9275 region. */
9276 if (region->type == GIMPLE_OMP_PARALLEL)
9277 determine_parallel_type (region);
9279 if (region->type == GIMPLE_OMP_FOR
9280 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9281 inner_stmt = last_stmt (region->inner->entry);
9283 if (region->inner)
9284 expand_omp (region->inner);
9286 saved_location = input_location;
9287 if (gimple_has_location (last_stmt (region->entry)))
9288 input_location = gimple_location (last_stmt (region->entry));
9290 switch (region->type)
9292 case GIMPLE_OMP_PARALLEL:
9293 case GIMPLE_OMP_TASK:
9294 expand_omp_taskreg (region);
9295 break;
9297 case GIMPLE_OMP_FOR:
9298 expand_omp_for (region, inner_stmt);
9299 break;
9301 case GIMPLE_OMP_SECTIONS:
9302 expand_omp_sections (region);
9303 break;
9305 case GIMPLE_OMP_SECTION:
9306 /* Individual omp sections are handled together with their
9307 parent GIMPLE_OMP_SECTIONS region. */
9308 break;
9310 case GIMPLE_OMP_SINGLE:
9311 expand_omp_single (region);
9312 break;
9314 case GIMPLE_OMP_MASTER:
9315 case GIMPLE_OMP_TASKGROUP:
9316 case GIMPLE_OMP_ORDERED:
9317 case GIMPLE_OMP_CRITICAL:
9318 case GIMPLE_OMP_TEAMS:
9319 expand_omp_synch (region);
9320 break;
9322 case GIMPLE_OMP_ATOMIC_LOAD:
9323 expand_omp_atomic (region);
9324 break;
9326 case GIMPLE_OMP_TARGET:
9327 expand_omp_target (region);
9328 break;
9330 default:
9331 gcc_unreachable ();
9334 input_location = saved_location;
9335 region = region->next;
9340 /* Helper for build_omp_regions. Scan the dominator tree starting at
9341 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9342 true, the function ends once a single tree is built (otherwise, whole
9343 forest of OMP constructs may be built). */
9345 static void
9346 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9347 bool single_tree)
9349 gimple_stmt_iterator gsi;
9350 gimple stmt;
9351 basic_block son;
9353 gsi = gsi_last_bb (bb);
9354 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9356 struct omp_region *region;
9357 enum gimple_code code;
9359 stmt = gsi_stmt (gsi);
9360 code = gimple_code (stmt);
9361 if (code == GIMPLE_OMP_RETURN)
9363 /* STMT is the return point out of region PARENT. Mark it
9364 as the exit point and make PARENT the immediately
9365 enclosing region. */
9366 gcc_assert (parent);
9367 region = parent;
9368 region->exit = bb;
9369 parent = parent->outer;
9371 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9373 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9374 GIMPLE_OMP_RETURN, but matches with
9375 GIMPLE_OMP_ATOMIC_LOAD. */
9376 gcc_assert (parent);
9377 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9378 region = parent;
9379 region->exit = bb;
9380 parent = parent->outer;
9383 else if (code == GIMPLE_OMP_CONTINUE)
9385 gcc_assert (parent);
9386 parent->cont = bb;
9388 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9390 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9391 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9394 else if (code == GIMPLE_OMP_TARGET
9395 && (gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE
9396 || (gimple_omp_target_kind (stmt)
9397 == GF_OMP_TARGET_KIND_OACC_UPDATE)
9398 || (gimple_omp_target_kind (stmt)
9399 == GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA)))
9400 new_omp_region (bb, code, parent);
9401 else
9403 /* Otherwise, this directive becomes the parent for a new
9404 region. */
9405 region = new_omp_region (bb, code, parent);
9406 parent = region;
9410 if (single_tree && !parent)
9411 return;
9413 for (son = first_dom_son (CDI_DOMINATORS, bb);
9414 son;
9415 son = next_dom_son (CDI_DOMINATORS, son))
9416 build_omp_regions_1 (son, parent, single_tree);
9419 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9420 root_omp_region. */
9422 static void
9423 build_omp_regions_root (basic_block root)
9425 gcc_assert (root_omp_region == NULL);
9426 build_omp_regions_1 (root, NULL, true);
9427 gcc_assert (root_omp_region != NULL);
9430 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9432 void
9433 omp_expand_local (basic_block head)
9435 build_omp_regions_root (head);
9436 if (dump_file && (dump_flags & TDF_DETAILS))
9438 fprintf (dump_file, "\nOMP region tree\n\n");
9439 dump_omp_region (dump_file, root_omp_region, 0);
9440 fprintf (dump_file, "\n");
9443 remove_exit_barriers (root_omp_region);
9444 expand_omp (root_omp_region);
9446 free_omp_regions ();
9449 /* Scan the CFG and build a tree of OMP regions. Return the root of
9450 the OMP region tree. */
9452 static void
9453 build_omp_regions (void)
9455 gcc_assert (root_omp_region == NULL);
9456 calculate_dominance_info (CDI_DOMINATORS);
9457 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9460 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9462 static unsigned int
9463 execute_expand_omp (void)
9465 build_omp_regions ();
9467 if (!root_omp_region)
9468 return 0;
9470 if (dump_file)
9472 fprintf (dump_file, "\nOMP region tree\n\n");
9473 dump_omp_region (dump_file, root_omp_region, 0);
9474 fprintf (dump_file, "\n");
9477 remove_exit_barriers (root_omp_region);
9479 expand_omp (root_omp_region);
9481 cleanup_tree_cfg ();
9483 free_omp_regions ();
9485 return 0;
9488 /* OMP expansion -- the default pass, run before creation of SSA form. */
9490 namespace {
9492 const pass_data pass_data_expand_omp =
9494 GIMPLE_PASS, /* type */
9495 "ompexp", /* name */
9496 OPTGROUP_NONE, /* optinfo_flags */
9497 TV_NONE, /* tv_id */
9498 PROP_gimple_any, /* properties_required */
9499 PROP_gimple_eomp, /* properties_provided */
9500 0, /* properties_destroyed */
9501 0, /* todo_flags_start */
9502 0, /* todo_flags_finish */
9505 class pass_expand_omp : public gimple_opt_pass
9507 public:
9508 pass_expand_omp (gcc::context *ctxt)
9509 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9512 /* opt_pass methods: */
9513 virtual unsigned int execute (function *)
9515 bool gate = ((flag_openacc != 0 || flag_openmp != 0
9516 || flag_openmp_simd != 0 || flag_cilkplus != 0)
9517 && !seen_error ());
9519 /* This pass always runs, to provide PROP_gimple_eomp.
9520 But there is nothing to do unless -fopenmp is given. */
9521 if (!gate)
9522 return 0;
9524 return execute_expand_omp ();
9527 }; // class pass_expand_omp
9529 } // anon namespace
9531 gimple_opt_pass *
9532 make_pass_expand_omp (gcc::context *ctxt)
9534 return new pass_expand_omp (ctxt);
9537 namespace {
9539 const pass_data pass_data_expand_omp_ssa =
9541 GIMPLE_PASS, /* type */
9542 "ompexpssa", /* name */
9543 OPTGROUP_NONE, /* optinfo_flags */
9544 TV_NONE, /* tv_id */
9545 PROP_cfg | PROP_ssa, /* properties_required */
9546 PROP_gimple_eomp, /* properties_provided */
9547 0, /* properties_destroyed */
9548 0, /* todo_flags_start */
9549 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9552 class pass_expand_omp_ssa : public gimple_opt_pass
9554 public:
9555 pass_expand_omp_ssa (gcc::context *ctxt)
9556 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9559 /* opt_pass methods: */
9560 virtual bool gate (function *fun)
9562 return !(fun->curr_properties & PROP_gimple_eomp);
9564 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9566 }; // class pass_expand_omp_ssa
9568 } // anon namespace
9570 gimple_opt_pass *
9571 make_pass_expand_omp_ssa (gcc::context *ctxt)
9573 return new pass_expand_omp_ssa (ctxt);
9576 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9577 convert it to gimple. */
9578 static void
9579 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9581 gimple stmt;
9583 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9585 stmt = gimple_build_assign (dest, op, dest, src);
9586 gimple_seq_add_stmt (seq, stmt);
9587 return;
9590 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9591 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9592 gimplify_assign (t, rdest, seq);
9593 rdest = t;
9595 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9596 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9597 gimplify_assign (t, idest, seq);
9598 idest = t;
9600 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9601 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9602 gimplify_assign (t, rsrc, seq);
9603 rsrc = t;
9605 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9606 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9607 gimplify_assign (t, isrc, seq);
9608 isrc = t;
9610 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9611 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9612 tree result;
9614 gcc_assert (op == PLUS_EXPR || op == MULT_EXPR);
9616 if (op == PLUS_EXPR)
9618 stmt = gimple_build_assign (r, op, rdest, rsrc);
9619 gimple_seq_add_stmt (seq, stmt);
9621 stmt = gimple_build_assign (i, op, idest, isrc);
9622 gimple_seq_add_stmt (seq, stmt);
9624 else if (op == MULT_EXPR)
9626 /* Let x = a + ib = dest, y = c + id = src.
9627 x * y = (ac - bd) + i(ad + bc) */
9628 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9629 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9630 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9631 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9633 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9634 gimple_seq_add_stmt (seq, stmt);
9636 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9637 gimple_seq_add_stmt (seq, stmt);
9639 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9640 gimple_seq_add_stmt (seq, stmt);
9642 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9643 gimple_seq_add_stmt (seq, stmt);
9645 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9646 gimple_seq_add_stmt (seq, stmt);
9648 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9649 gimple_seq_add_stmt (seq, stmt);
9652 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9653 gimplify_assign (dest, result, seq);
9656 /* Helper function to initialize local data for the reduction arrays.
9657 The reduction arrays need to be placed inside the calling function
9658 for accelerators, or else the host won't be able to preform the final
9659 reduction. FIXME: This function assumes that there are
9660 vector_length threads in total. */
9662 static void
9663 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9664 gimple_seq *stmt_seqp, omp_context *ctx)
9666 gcc_assert (is_gimple_omp_oacc_specifically (ctx->stmt));
9668 tree c, t, oc;
9669 gimple stmt;
9670 omp_context *octx;
9672 /* Find the innermost PARALLEL openmp context. FIXME: OpenACC kernels
9673 may require extra care unless they are converted to openmp for loops. */
9674 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9675 && (gimple_omp_target_kind (ctx->stmt)
9676 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9677 octx = ctx;
9678 else
9679 octx = ctx->outer;
9681 /* Extract the clauses. */
9682 oc = gimple_omp_target_clauses (octx->stmt);
9684 /* Find the last outer clause. */
9685 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9688 /* Allocate arrays for each reduction variable. */
9689 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9691 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9692 continue;
9694 tree var = OMP_CLAUSE_DECL (c);
9695 tree type = get_base_type (var);
9696 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9697 ctx);
9698 tree size, call;
9700 /* Calculate size of the reduction array. */
9701 t = create_tmp_var (TREE_TYPE (nthreads));
9702 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9703 fold_convert (TREE_TYPE (nthreads),
9704 TYPE_SIZE_UNIT (type)));
9705 gimple_seq_add_stmt (stmt_seqp, stmt);
9707 size = create_tmp_var (sizetype);
9708 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9710 /* Now allocate memory for it. FIXME: Allocating memory for the
9711 reduction array may be unnecessary once the final reduction is able
9712 to be preformed on the accelerator. Instead of allocating memory on
9713 the host side, it could just be allocated on the accelerator. */
9714 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9715 stmt = gimple_build_call (call, 1, size);
9716 gimple_call_set_lhs (stmt, array);
9717 gimple_seq_add_stmt (stmt_seqp, stmt);
9719 /* Map this array into the accelerator. */
9721 /* Add the reduction array to the list of clauses. */
9722 /* FIXME: Currently, these variables must be placed in the outer
9723 most clause so that copy-out works. */
9724 tree x = array;
9725 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9726 OMP_CLAUSE_MAP_KIND (t) = OMP_CLAUSE_MAP_FORCE_FROM;
9727 OMP_CLAUSE_DECL (t) = x;
9728 OMP_CLAUSE_CHAIN (t) = NULL;
9729 if (oc)
9730 OMP_CLAUSE_CHAIN (oc) = t;
9731 else
9732 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9733 OMP_CLAUSE_SIZE (t) = size;
9734 oc = t;
9738 /* Helper function to process the array of partial reductions. Nthreads
9739 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9740 cannot be used here, because nthreads on the host may be different than
9741 on the accelerator. */
9743 static void
9744 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9745 gimple_seq *stmt_seqp, omp_context *ctx)
9747 gcc_assert (is_gimple_omp_oacc_specifically (ctx->stmt));
9749 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9750 gimple stmt;
9752 /* Create for loop.
9754 let var = the original reduction variable
9755 let array = reduction variable array
9757 for (i = 0; i < nthreads; i++)
9758 var op= array[i]
9761 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9762 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9763 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9765 /* Create and initialize an index variable. */
9766 tree ix = create_tmp_var (sizetype);
9767 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9768 stmt_seqp);
9770 /* Insert the loop header label here. */
9771 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9773 /* Exit loop if ix >= nthreads. */
9774 x = create_tmp_var (sizetype);
9775 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9776 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9777 gimple_seq_add_stmt (stmt_seqp, stmt);
9779 /* Insert the loop body label here. */
9780 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9782 /* Collapse each reduction array, one element at a time. */
9783 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9785 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9786 continue;
9788 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9790 /* reduction(-:var) sums up the partial results, so it acts
9791 identically to reduction(+:var). */
9792 if (reduction_code == MINUS_EXPR)
9793 reduction_code = PLUS_EXPR;
9795 /* Set up reduction variable var. */
9796 var = OMP_CLAUSE_DECL (c);
9797 type = get_base_type (var);
9798 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9799 (OMP_CLAUSE_DECL (c)), ctx);
9801 /* Calculate the array offset. */
9802 tree offset = create_tmp_var (sizetype);
9803 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9804 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9805 gimple_seq_add_stmt (stmt_seqp, stmt);
9807 tree ptr = create_tmp_var (TREE_TYPE (array));
9808 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9809 gimple_seq_add_stmt (stmt_seqp, stmt);
9811 /* Extract array[ix] into mem. */
9812 tree mem = create_tmp_var (type);
9813 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9815 /* Find the original reduction variable. */
9816 if (is_reference (var))
9817 var = build_simple_mem_ref (var);
9819 tree t = create_tmp_var (type);
9821 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9822 gimplify_and_add (unshare_expr(x), stmt_seqp);
9824 /* var = var op mem */
9825 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9827 case TRUTH_ANDIF_EXPR:
9828 case TRUTH_ORIF_EXPR:
9829 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9830 t, mem);
9831 gimplify_and_add (t, stmt_seqp);
9832 break;
9833 default:
9834 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9835 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9836 stmt_seqp);
9839 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9840 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9841 gimplify_and_add (unshare_expr(x), stmt_seqp);
9844 /* Increment the induction variable. */
9845 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9846 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9847 gimple_seq_add_stmt (stmt_seqp, stmt);
9849 /* Go back to the top of the loop. */
9850 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9852 /* Place the loop exit label here. */
9853 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9856 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9857 scan that for reductions. */
9859 static void
9860 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9861 gimple_seq *out_stmt_seqp, omp_context *ctx)
9863 gcc_assert (is_gimple_omp_oacc_specifically (ctx->stmt));
9865 gimple_stmt_iterator gsi;
9866 gimple_seq inner = NULL;
9868 /* A collapse clause may have inserted a new bind block. */
9869 gsi = gsi_start (*body);
9870 while (!gsi_end_p (gsi))
9872 gimple stmt = gsi_stmt (gsi);
9873 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9875 inner = gimple_bind_body (bind_stmt);
9876 body = &inner;
9877 gsi = gsi_start (*body);
9879 else if (dyn_cast <gomp_for *> (stmt))
9880 break;
9881 else
9882 gsi_next (&gsi);
9885 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9887 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9888 enter, exit;
9889 bool reduction_found = false;
9891 gimple stmt = gsi_stmt (gsi);
9893 switch (gimple_code (stmt))
9895 /* FIXME: A reduction may also appear in an oacc parallel. */
9896 case GIMPLE_OMP_FOR:
9897 clauses = gimple_omp_for_clauses (stmt);
9899 /* Search for a reduction clause. */
9900 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9901 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9903 reduction_found = true;
9904 break;
9907 if (!reduction_found)
9908 break;
9910 ctx = maybe_lookup_ctx (stmt);
9911 t = NULL_TREE;
9913 /* Extract the number of threads. */
9914 nthreads = create_tmp_var (sizetype);
9915 t = oacc_max_threads (ctx);
9916 gimplify_assign (nthreads, t, in_stmt_seqp);
9918 /* Determine if this is kernel will be executed on the host. */
9919 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9920 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9921 stmt = gimple_build_call (call, 0);
9922 gimple_call_set_lhs (stmt, acc_device);
9923 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9925 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9926 acc_device_host = create_tmp_var (integer_type_node,
9927 ".acc_device_host");
9928 gimplify_assign (acc_device_host, build_int_cst (integer_type_node,
9930 in_stmt_seqp);
9932 enter = create_artificial_label (UNKNOWN_LOCATION);
9933 exit = create_artificial_label (UNKNOWN_LOCATION);
9935 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9936 enter, exit);
9937 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9938 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9939 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9940 integer_one_node),
9941 in_stmt_seqp);
9942 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9944 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9945 gimplify_assign (acc_device_host, build_int_cst (integer_type_node,
9947 in_stmt_seqp);
9949 enter = create_artificial_label (UNKNOWN_LOCATION);
9950 exit = create_artificial_label (UNKNOWN_LOCATION);
9952 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9953 enter, exit);
9954 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9955 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9956 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9957 integer_one_node),
9958 in_stmt_seqp);
9959 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9961 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9962 ctx);
9963 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9964 break;
9965 default:
9966 // Scan for other directives which support reduction here.
9967 break;
9972 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
9974 /* If ctx is a worksharing context inside of a cancellable parallel
9975 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9976 and conditional branch to parallel's cancel_label to handle
9977 cancellation in the implicit barrier. */
9979 static void
9980 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9982 gimple omp_return = gimple_seq_last_stmt (*body);
9983 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
9984 if (gimple_omp_return_nowait_p (omp_return))
9985 return;
9986 if (ctx->outer
9987 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
9988 && ctx->outer->cancellable)
9990 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
9991 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
9992 tree lhs = create_tmp_var (c_bool_type);
9993 gimple_omp_return_set_lhs (omp_return, lhs);
9994 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
9995 gimple g = gimple_build_cond (NE_EXPR, lhs,
9996 fold_convert (c_bool_type,
9997 boolean_false_node),
9998 ctx->outer->cancel_label, fallthru_label);
9999 gimple_seq_add_stmt (body, g);
10000 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10004 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10005 CTX is the enclosing OMP context for the current statement. */
10007 static void
10008 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10010 tree block, control;
10011 gimple_stmt_iterator tgsi;
10012 gomp_sections *stmt;
10013 gimple t;
10014 gbind *new_stmt, *bind;
10015 gimple_seq ilist, dlist, olist, new_body;
10017 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10019 push_gimplify_context ();
10021 dlist = NULL;
10022 ilist = NULL;
10023 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10024 &ilist, &dlist, ctx, NULL);
10026 new_body = gimple_omp_body (stmt);
10027 gimple_omp_set_body (stmt, NULL);
10028 tgsi = gsi_start (new_body);
10029 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10031 omp_context *sctx;
10032 gimple sec_start;
10034 sec_start = gsi_stmt (tgsi);
10035 sctx = maybe_lookup_ctx (sec_start);
10036 gcc_assert (sctx);
10038 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10039 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10040 GSI_CONTINUE_LINKING);
10041 gimple_omp_set_body (sec_start, NULL);
10043 if (gsi_one_before_end_p (tgsi))
10045 gimple_seq l = NULL;
10046 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10047 &l, ctx);
10048 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10049 gimple_omp_section_set_last (sec_start);
10052 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10053 GSI_CONTINUE_LINKING);
10056 block = make_node (BLOCK);
10057 bind = gimple_build_bind (NULL, new_body, block);
10059 olist = NULL;
10060 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10062 block = make_node (BLOCK);
10063 new_stmt = gimple_build_bind (NULL, NULL, block);
10064 gsi_replace (gsi_p, new_stmt, true);
10066 pop_gimplify_context (new_stmt);
10067 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10068 BLOCK_VARS (block) = gimple_bind_vars (bind);
10069 if (BLOCK_VARS (block))
10070 TREE_USED (block) = 1;
10072 new_body = NULL;
10073 gimple_seq_add_seq (&new_body, ilist);
10074 gimple_seq_add_stmt (&new_body, stmt);
10075 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10076 gimple_seq_add_stmt (&new_body, bind);
10078 control = create_tmp_var (unsigned_type_node, ".section");
10079 t = gimple_build_omp_continue (control, control);
10080 gimple_omp_sections_set_control (stmt, control);
10081 gimple_seq_add_stmt (&new_body, t);
10083 gimple_seq_add_seq (&new_body, olist);
10084 if (ctx->cancellable)
10085 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10086 gimple_seq_add_seq (&new_body, dlist);
10088 new_body = maybe_catch_exception (new_body);
10090 t = gimple_build_omp_return
10091 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10092 OMP_CLAUSE_NOWAIT));
10093 gimple_seq_add_stmt (&new_body, t);
10094 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10096 gimple_bind_set_body (new_stmt, new_body);
10100 /* A subroutine of lower_omp_single. Expand the simple form of
10101 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10103 if (GOMP_single_start ())
10104 BODY;
10105 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10107 FIXME. It may be better to delay expanding the logic of this until
10108 pass_expand_omp. The expanded logic may make the job more difficult
10109 to a synchronization analysis pass. */
10111 static void
10112 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10114 location_t loc = gimple_location (single_stmt);
10115 tree tlabel = create_artificial_label (loc);
10116 tree flabel = create_artificial_label (loc);
10117 gimple call, cond;
10118 tree lhs, decl;
10120 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10121 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10122 call = gimple_build_call (decl, 0);
10123 gimple_call_set_lhs (call, lhs);
10124 gimple_seq_add_stmt (pre_p, call);
10126 cond = gimple_build_cond (EQ_EXPR, lhs,
10127 fold_convert_loc (loc, TREE_TYPE (lhs),
10128 boolean_true_node),
10129 tlabel, flabel);
10130 gimple_seq_add_stmt (pre_p, cond);
10131 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10132 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10133 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10137 /* A subroutine of lower_omp_single. Expand the simple form of
10138 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10140 #pragma omp single copyprivate (a, b, c)
10142 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10145 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10147 BODY;
10148 copyout.a = a;
10149 copyout.b = b;
10150 copyout.c = c;
10151 GOMP_single_copy_end (&copyout);
10153 else
10155 a = copyout_p->a;
10156 b = copyout_p->b;
10157 c = copyout_p->c;
10159 GOMP_barrier ();
10162 FIXME. It may be better to delay expanding the logic of this until
10163 pass_expand_omp. The expanded logic may make the job more difficult
10164 to a synchronization analysis pass. */
10166 static void
10167 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10168 omp_context *ctx)
10170 tree ptr_type, t, l0, l1, l2, bfn_decl;
10171 gimple_seq copyin_seq;
10172 location_t loc = gimple_location (single_stmt);
10174 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10176 ptr_type = build_pointer_type (ctx->record_type);
10177 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10179 l0 = create_artificial_label (loc);
10180 l1 = create_artificial_label (loc);
10181 l2 = create_artificial_label (loc);
10183 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10184 t = build_call_expr_loc (loc, bfn_decl, 0);
10185 t = fold_convert_loc (loc, ptr_type, t);
10186 gimplify_assign (ctx->receiver_decl, t, pre_p);
10188 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10189 build_int_cst (ptr_type, 0));
10190 t = build3 (COND_EXPR, void_type_node, t,
10191 build_and_jump (&l0), build_and_jump (&l1));
10192 gimplify_and_add (t, pre_p);
10194 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10196 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10198 copyin_seq = NULL;
10199 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10200 &copyin_seq, ctx);
10202 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10203 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10204 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10205 gimplify_and_add (t, pre_p);
10207 t = build_and_jump (&l2);
10208 gimplify_and_add (t, pre_p);
10210 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10212 gimple_seq_add_seq (pre_p, copyin_seq);
10214 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10218 /* Expand code for an OpenMP single directive. */
10220 static void
10221 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10223 tree block;
10224 gimple t;
10225 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10226 gbind *bind;
10227 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10229 push_gimplify_context ();
10231 block = make_node (BLOCK);
10232 bind = gimple_build_bind (NULL, NULL, block);
10233 gsi_replace (gsi_p, bind, true);
10234 bind_body = NULL;
10235 dlist = NULL;
10236 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10237 &bind_body, &dlist, ctx, NULL);
10238 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10240 gimple_seq_add_stmt (&bind_body, single_stmt);
10242 if (ctx->record_type)
10243 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10244 else
10245 lower_omp_single_simple (single_stmt, &bind_body);
10247 gimple_omp_set_body (single_stmt, NULL);
10249 gimple_seq_add_seq (&bind_body, dlist);
10251 bind_body = maybe_catch_exception (bind_body);
10253 t = gimple_build_omp_return
10254 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10255 OMP_CLAUSE_NOWAIT));
10256 gimple_seq_add_stmt (&bind_body_tail, t);
10257 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10258 if (ctx->record_type)
10260 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10261 tree clobber = build_constructor (ctx->record_type, NULL);
10262 TREE_THIS_VOLATILE (clobber) = 1;
10263 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10264 clobber), GSI_SAME_STMT);
10266 gimple_seq_add_seq (&bind_body, bind_body_tail);
10267 gimple_bind_set_body (bind, bind_body);
10269 pop_gimplify_context (bind);
10271 gimple_bind_append_vars (bind, ctx->block_vars);
10272 BLOCK_VARS (block) = ctx->block_vars;
10273 if (BLOCK_VARS (block))
10274 TREE_USED (block) = 1;
10278 /* Expand code for an OpenMP master directive. */
10280 static void
10281 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10283 tree block, lab = NULL, x, bfn_decl;
10284 gimple stmt = gsi_stmt (*gsi_p);
10285 gbind *bind;
10286 location_t loc = gimple_location (stmt);
10287 gimple_seq tseq;
10289 push_gimplify_context ();
10291 block = make_node (BLOCK);
10292 bind = gimple_build_bind (NULL, NULL, block);
10293 gsi_replace (gsi_p, bind, true);
10294 gimple_bind_add_stmt (bind, stmt);
10296 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10297 x = build_call_expr_loc (loc, bfn_decl, 0);
10298 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10299 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10300 tseq = NULL;
10301 gimplify_and_add (x, &tseq);
10302 gimple_bind_add_seq (bind, tseq);
10304 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10305 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10306 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10307 gimple_omp_set_body (stmt, NULL);
10309 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10311 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10313 pop_gimplify_context (bind);
10315 gimple_bind_append_vars (bind, ctx->block_vars);
10316 BLOCK_VARS (block) = ctx->block_vars;
10320 /* Expand code for an OpenMP taskgroup directive. */
10322 static void
10323 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10325 gimple stmt = gsi_stmt (*gsi_p);
10326 gcall *x;
10327 gbind *bind;
10328 tree block = make_node (BLOCK);
10330 bind = gimple_build_bind (NULL, NULL, block);
10331 gsi_replace (gsi_p, bind, true);
10332 gimple_bind_add_stmt (bind, stmt);
10334 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10336 gimple_bind_add_stmt (bind, x);
10338 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10339 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10340 gimple_omp_set_body (stmt, NULL);
10342 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10344 gimple_bind_append_vars (bind, ctx->block_vars);
10345 BLOCK_VARS (block) = ctx->block_vars;
10349 /* Expand code for an OpenMP ordered directive. */
10351 static void
10352 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10354 tree block;
10355 gimple stmt = gsi_stmt (*gsi_p);
10356 gcall *x;
10357 gbind *bind;
10359 push_gimplify_context ();
10361 block = make_node (BLOCK);
10362 bind = gimple_build_bind (NULL, NULL, block);
10363 gsi_replace (gsi_p, bind, true);
10364 gimple_bind_add_stmt (bind, stmt);
10366 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10368 gimple_bind_add_stmt (bind, x);
10370 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10371 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10372 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10373 gimple_omp_set_body (stmt, NULL);
10375 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10376 gimple_bind_add_stmt (bind, x);
10378 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10380 pop_gimplify_context (bind);
10382 gimple_bind_append_vars (bind, ctx->block_vars);
10383 BLOCK_VARS (block) = gimple_bind_vars (bind);
10387 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10388 substitution of a couple of function calls. But in the NAMED case,
10389 requires that languages coordinate a symbol name. It is therefore
10390 best put here in common code. */
10392 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10394 static void
10395 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10397 tree block;
10398 tree name, lock, unlock;
10399 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10400 gbind *bind;
10401 location_t loc = gimple_location (stmt);
10402 gimple_seq tbody;
10404 name = gimple_omp_critical_name (stmt);
10405 if (name)
10407 tree decl;
10409 if (!critical_name_mutexes)
10410 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10412 tree *n = critical_name_mutexes->get (name);
10413 if (n == NULL)
10415 char *new_str;
10417 decl = create_tmp_var_raw (ptr_type_node);
10419 new_str = ACONCAT ((".gomp_critical_user_",
10420 IDENTIFIER_POINTER (name), NULL));
10421 DECL_NAME (decl) = get_identifier (new_str);
10422 TREE_PUBLIC (decl) = 1;
10423 TREE_STATIC (decl) = 1;
10424 DECL_COMMON (decl) = 1;
10425 DECL_ARTIFICIAL (decl) = 1;
10426 DECL_IGNORED_P (decl) = 1;
10428 varpool_node::finalize_decl (decl);
10430 critical_name_mutexes->put (name, decl);
10432 else
10433 decl = *n;
10435 /* If '#pragma omp critical' is inside offloaded region or
10436 inside function marked as offloadable, the symbol must be
10437 marked as offloadable too. */
10438 omp_context *octx;
10439 if (cgraph_node::get (current_function_decl)->offloadable)
10440 varpool_node::get_create (decl)->offloadable = 1;
10441 else
10442 for (octx = ctx->outer; octx; octx = octx->outer)
10443 if (is_gimple_omp_offloaded (octx->stmt))
10445 varpool_node::get_create (decl)->offloadable = 1;
10446 break;
10449 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10450 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10452 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10453 unlock = build_call_expr_loc (loc, unlock, 1,
10454 build_fold_addr_expr_loc (loc, decl));
10456 else
10458 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10459 lock = build_call_expr_loc (loc, lock, 0);
10461 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10462 unlock = build_call_expr_loc (loc, unlock, 0);
10465 push_gimplify_context ();
10467 block = make_node (BLOCK);
10468 bind = gimple_build_bind (NULL, NULL, block);
10469 gsi_replace (gsi_p, bind, true);
10470 gimple_bind_add_stmt (bind, stmt);
10472 tbody = gimple_bind_body (bind);
10473 gimplify_and_add (lock, &tbody);
10474 gimple_bind_set_body (bind, tbody);
10476 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10477 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10478 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10479 gimple_omp_set_body (stmt, NULL);
10481 tbody = gimple_bind_body (bind);
10482 gimplify_and_add (unlock, &tbody);
10483 gimple_bind_set_body (bind, tbody);
10485 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10487 pop_gimplify_context (bind);
10488 gimple_bind_append_vars (bind, ctx->block_vars);
10489 BLOCK_VARS (block) = gimple_bind_vars (bind);
10493 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10494 for a lastprivate clause. Given a loop control predicate of (V
10495 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10496 is appended to *DLIST, iterator initialization is appended to
10497 *BODY_P. */
10499 static void
10500 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10501 gimple_seq *dlist, struct omp_context *ctx)
10503 tree clauses, cond, vinit;
10504 enum tree_code cond_code;
10505 gimple_seq stmts;
10507 cond_code = fd->loop.cond_code;
10508 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10510 /* When possible, use a strict equality expression. This can let VRP
10511 type optimizations deduce the value and remove a copy. */
10512 if (tree_fits_shwi_p (fd->loop.step))
10514 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10515 if (step == 1 || step == -1)
10516 cond_code = EQ_EXPR;
10519 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
10521 clauses = gimple_omp_for_clauses (fd->for_stmt);
10522 stmts = NULL;
10523 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10524 if (!gimple_seq_empty_p (stmts))
10526 gimple_seq_add_seq (&stmts, *dlist);
10527 *dlist = stmts;
10529 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10530 vinit = fd->loop.n1;
10531 if (cond_code == EQ_EXPR
10532 && tree_fits_shwi_p (fd->loop.n2)
10533 && ! integer_zerop (fd->loop.n2))
10534 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10535 else
10536 vinit = unshare_expr (vinit);
10538 /* Initialize the iterator variable, so that threads that don't execute
10539 any iterations don't execute the lastprivate clauses by accident. */
10540 gimplify_assign (fd->loop.v, vinit, body_p);
10545 /* Lower code for an OpenMP loop directive. */
10547 static void
10548 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10550 tree *rhs_p, block;
10551 struct omp_for_data fd, *fdp = NULL;
10552 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10553 gbind *new_stmt;
10554 gimple_seq omp_for_body, body, dlist;
10555 size_t i;
10557 push_gimplify_context ();
10559 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10561 block = make_node (BLOCK);
10562 new_stmt = gimple_build_bind (NULL, NULL, block);
10563 /* Replace at gsi right away, so that 'stmt' is no member
10564 of a sequence anymore as we're going to add to to a different
10565 one below. */
10566 gsi_replace (gsi_p, new_stmt, true);
10568 /* Move declaration of temporaries in the loop body before we make
10569 it go away. */
10570 omp_for_body = gimple_omp_body (stmt);
10571 if (!gimple_seq_empty_p (omp_for_body)
10572 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10574 gbind *inner_bind
10575 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10576 tree vars = gimple_bind_vars (inner_bind);
10577 gimple_bind_append_vars (new_stmt, vars);
10578 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10579 keep them on the inner_bind and it's block. */
10580 gimple_bind_set_vars (inner_bind, NULL_TREE);
10581 if (gimple_bind_block (inner_bind))
10582 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10585 if (gimple_omp_for_combined_into_p (stmt))
10587 gcc_assert (gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_OACC_LOOP);
10589 extract_omp_for_data (stmt, &fd, NULL);
10590 fdp = &fd;
10592 /* We need two temporaries with fd.loop.v type (istart/iend)
10593 and then (fd.collapse - 1) temporaries with the same
10594 type for count2 ... countN-1 vars if not constant. */
10595 size_t count = 2;
10596 tree type = fd.iter_type;
10597 if (fd.collapse > 1
10598 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10599 count += fd.collapse - 1;
10600 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10601 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10602 tree clauses = *pc;
10603 if (parallel_for)
10604 outerc
10605 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10606 OMP_CLAUSE__LOOPTEMP_);
10607 for (i = 0; i < count; i++)
10609 tree temp;
10610 if (parallel_for)
10612 gcc_assert (outerc);
10613 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10614 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10615 OMP_CLAUSE__LOOPTEMP_);
10617 else
10619 temp = create_tmp_var (type);
10620 insert_decl_map (&ctx->outer->cb, temp, temp);
10622 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10623 OMP_CLAUSE_DECL (*pc) = temp;
10624 pc = &OMP_CLAUSE_CHAIN (*pc);
10626 *pc = clauses;
10629 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10630 dlist = NULL;
10631 body = NULL;
10632 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10633 fdp);
10634 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10636 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10638 /* Lower the header expressions. At this point, we can assume that
10639 the header is of the form:
10641 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10643 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10644 using the .omp_data_s mapping, if needed. */
10645 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10647 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10648 if (!is_gimple_min_invariant (*rhs_p))
10649 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10651 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10652 if (!is_gimple_min_invariant (*rhs_p))
10653 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10655 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10656 if (!is_gimple_min_invariant (*rhs_p))
10657 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10660 /* Once lowered, extract the bounds and clauses. */
10661 extract_omp_for_data (stmt, &fd, NULL);
10663 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10665 gimple_seq_add_stmt (&body, stmt);
10666 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10668 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10669 fd.loop.v));
10671 /* After the loop, add exit clauses. */
10672 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10674 if (ctx->cancellable)
10675 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10677 gimple_seq_add_seq (&body, dlist);
10679 body = maybe_catch_exception (body);
10681 /* Region exit marker goes at the end of the loop body. */
10682 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10683 maybe_add_implicit_barrier_cancel (ctx, &body);
10684 pop_gimplify_context (new_stmt);
10686 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10687 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10688 if (BLOCK_VARS (block))
10689 TREE_USED (block) = 1;
10691 gimple_bind_set_body (new_stmt, body);
10692 gimple_omp_set_body (stmt, NULL);
10693 gimple_omp_for_set_pre_body (stmt, NULL);
10696 /* Callback for walk_stmts. Check if the current statement only contains
10697 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10699 static tree
10700 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10701 bool *handled_ops_p,
10702 struct walk_stmt_info *wi)
10704 int *info = (int *) wi->info;
10705 gimple stmt = gsi_stmt (*gsi_p);
10707 *handled_ops_p = true;
10708 switch (gimple_code (stmt))
10710 WALK_SUBSTMTS;
10712 case GIMPLE_OMP_FOR:
10713 case GIMPLE_OMP_SECTIONS:
10714 *info = *info == 0 ? 1 : -1;
10715 break;
10716 default:
10717 *info = -1;
10718 break;
10720 return NULL;
10723 struct omp_taskcopy_context
10725 /* This field must be at the beginning, as we do "inheritance": Some
10726 callback functions for tree-inline.c (e.g., omp_copy_decl)
10727 receive a copy_body_data pointer that is up-casted to an
10728 omp_context pointer. */
10729 copy_body_data cb;
10730 omp_context *ctx;
10733 static tree
10734 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10736 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10738 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10739 return create_tmp_var (TREE_TYPE (var));
10741 return var;
10744 static tree
10745 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10747 tree name, new_fields = NULL, type, f;
10749 type = lang_hooks.types.make_type (RECORD_TYPE);
10750 name = DECL_NAME (TYPE_NAME (orig_type));
10751 name = build_decl (gimple_location (tcctx->ctx->stmt),
10752 TYPE_DECL, name, type);
10753 TYPE_NAME (type) = name;
10755 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10757 tree new_f = copy_node (f);
10758 DECL_CONTEXT (new_f) = type;
10759 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10760 TREE_CHAIN (new_f) = new_fields;
10761 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10762 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10763 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10764 &tcctx->cb, NULL);
10765 new_fields = new_f;
10766 tcctx->cb.decl_map->put (f, new_f);
10768 TYPE_FIELDS (type) = nreverse (new_fields);
10769 layout_type (type);
10770 return type;
10773 /* Create task copyfn. */
10775 static void
10776 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10778 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
10780 struct function *child_cfun;
10781 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10782 tree record_type, srecord_type, bind, list;
10783 bool record_needs_remap = false, srecord_needs_remap = false;
10784 splay_tree_node n;
10785 struct omp_taskcopy_context tcctx;
10786 location_t loc = gimple_location (task_stmt);
10788 child_fn = gimple_omp_task_copy_fn (task_stmt);
10789 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10790 gcc_assert (child_cfun->cfg == NULL);
10791 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10793 /* Reset DECL_CONTEXT on function arguments. */
10794 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10795 DECL_CONTEXT (t) = child_fn;
10797 /* Populate the function. */
10798 push_gimplify_context ();
10799 push_cfun (child_cfun);
10801 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10802 TREE_SIDE_EFFECTS (bind) = 1;
10803 list = NULL;
10804 DECL_SAVED_TREE (child_fn) = bind;
10805 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10807 /* Remap src and dst argument types if needed. */
10808 record_type = ctx->record_type;
10809 srecord_type = ctx->srecord_type;
10810 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10811 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10813 record_needs_remap = true;
10814 break;
10816 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10817 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10819 srecord_needs_remap = true;
10820 break;
10823 if (record_needs_remap || srecord_needs_remap)
10825 memset (&tcctx, '\0', sizeof (tcctx));
10826 tcctx.cb.src_fn = ctx->cb.src_fn;
10827 tcctx.cb.dst_fn = child_fn;
10828 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
10829 gcc_checking_assert (tcctx.cb.src_node);
10830 tcctx.cb.dst_node = tcctx.cb.src_node;
10831 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10832 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10833 tcctx.cb.eh_lp_nr = 0;
10834 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10835 tcctx.cb.decl_map = new hash_map<tree, tree>;
10836 tcctx.ctx = ctx;
10838 if (record_needs_remap)
10839 record_type = task_copyfn_remap_type (&tcctx, record_type);
10840 if (srecord_needs_remap)
10841 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10843 else
10844 tcctx.cb.decl_map = NULL;
10846 arg = DECL_ARGUMENTS (child_fn);
10847 TREE_TYPE (arg) = build_pointer_type (record_type);
10848 sarg = DECL_CHAIN (arg);
10849 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10851 /* First pass: initialize temporaries used in record_type and srecord_type
10852 sizes and field offsets. */
10853 if (tcctx.cb.decl_map)
10854 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10855 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10857 tree *p;
10859 decl = OMP_CLAUSE_DECL (c);
10860 p = tcctx.cb.decl_map->get (decl);
10861 if (p == NULL)
10862 continue;
10863 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10864 sf = (tree) n->value;
10865 sf = *tcctx.cb.decl_map->get (sf);
10866 src = build_simple_mem_ref_loc (loc, sarg);
10867 src = omp_build_component_ref (src, sf);
10868 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10869 append_to_statement_list (t, &list);
10872 /* Second pass: copy shared var pointers and copy construct non-VLA
10873 firstprivate vars. */
10874 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10875 switch (OMP_CLAUSE_CODE (c))
10877 case OMP_CLAUSE_SHARED:
10878 decl = OMP_CLAUSE_DECL (c);
10879 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10880 if (n == NULL)
10881 break;
10882 f = (tree) n->value;
10883 if (tcctx.cb.decl_map)
10884 f = *tcctx.cb.decl_map->get (f);
10885 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10886 sf = (tree) n->value;
10887 if (tcctx.cb.decl_map)
10888 sf = *tcctx.cb.decl_map->get (sf);
10889 src = build_simple_mem_ref_loc (loc, sarg);
10890 src = omp_build_component_ref (src, sf);
10891 dst = build_simple_mem_ref_loc (loc, arg);
10892 dst = omp_build_component_ref (dst, f);
10893 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10894 append_to_statement_list (t, &list);
10895 break;
10896 case OMP_CLAUSE_FIRSTPRIVATE:
10897 decl = OMP_CLAUSE_DECL (c);
10898 if (is_variable_sized (decl))
10899 break;
10900 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10901 if (n == NULL)
10902 break;
10903 f = (tree) n->value;
10904 if (tcctx.cb.decl_map)
10905 f = *tcctx.cb.decl_map->get (f);
10906 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10907 if (n != NULL)
10909 sf = (tree) n->value;
10910 if (tcctx.cb.decl_map)
10911 sf = *tcctx.cb.decl_map->get (sf);
10912 src = build_simple_mem_ref_loc (loc, sarg);
10913 src = omp_build_component_ref (src, sf);
10914 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
10915 src = build_simple_mem_ref_loc (loc, src);
10917 else
10918 src = decl;
10919 dst = build_simple_mem_ref_loc (loc, arg);
10920 dst = omp_build_component_ref (dst, f);
10921 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10922 append_to_statement_list (t, &list);
10923 break;
10924 case OMP_CLAUSE_PRIVATE:
10925 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10926 break;
10927 decl = OMP_CLAUSE_DECL (c);
10928 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10929 f = (tree) n->value;
10930 if (tcctx.cb.decl_map)
10931 f = *tcctx.cb.decl_map->get (f);
10932 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10933 if (n != NULL)
10935 sf = (tree) n->value;
10936 if (tcctx.cb.decl_map)
10937 sf = *tcctx.cb.decl_map->get (sf);
10938 src = build_simple_mem_ref_loc (loc, sarg);
10939 src = omp_build_component_ref (src, sf);
10940 if (use_pointer_for_field (decl, NULL))
10941 src = build_simple_mem_ref_loc (loc, src);
10943 else
10944 src = decl;
10945 dst = build_simple_mem_ref_loc (loc, arg);
10946 dst = omp_build_component_ref (dst, f);
10947 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10948 append_to_statement_list (t, &list);
10949 break;
10950 default:
10951 break;
10954 /* Last pass: handle VLA firstprivates. */
10955 if (tcctx.cb.decl_map)
10956 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10957 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10959 tree ind, ptr, df;
10961 decl = OMP_CLAUSE_DECL (c);
10962 if (!is_variable_sized (decl))
10963 continue;
10964 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10965 if (n == NULL)
10966 continue;
10967 f = (tree) n->value;
10968 f = *tcctx.cb.decl_map->get (f);
10969 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10970 ind = DECL_VALUE_EXPR (decl);
10971 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10972 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10973 n = splay_tree_lookup (ctx->sfield_map,
10974 (splay_tree_key) TREE_OPERAND (ind, 0));
10975 sf = (tree) n->value;
10976 sf = *tcctx.cb.decl_map->get (sf);
10977 src = build_simple_mem_ref_loc (loc, sarg);
10978 src = omp_build_component_ref (src, sf);
10979 src = build_simple_mem_ref_loc (loc, src);
10980 dst = build_simple_mem_ref_loc (loc, arg);
10981 dst = omp_build_component_ref (dst, f);
10982 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10983 append_to_statement_list (t, &list);
10984 n = splay_tree_lookup (ctx->field_map,
10985 (splay_tree_key) TREE_OPERAND (ind, 0));
10986 df = (tree) n->value;
10987 df = *tcctx.cb.decl_map->get (df);
10988 ptr = build_simple_mem_ref_loc (loc, arg);
10989 ptr = omp_build_component_ref (ptr, df);
10990 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
10991 build_fold_addr_expr_loc (loc, dst));
10992 append_to_statement_list (t, &list);
10995 t = build1 (RETURN_EXPR, void_type_node, NULL);
10996 append_to_statement_list (t, &list);
10998 if (tcctx.cb.decl_map)
10999 delete tcctx.cb.decl_map;
11000 pop_gimplify_context (NULL);
11001 BIND_EXPR_BODY (bind) = list;
11002 pop_cfun ();
11005 static void
11006 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
11008 tree c, clauses;
11009 gimple g;
11010 size_t n_in = 0, n_out = 0, idx = 2, i;
11012 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11013 OMP_CLAUSE_DEPEND);
11014 gcc_assert (clauses);
11015 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11016 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11017 switch (OMP_CLAUSE_DEPEND_KIND (c))
11019 case OMP_CLAUSE_DEPEND_IN:
11020 n_in++;
11021 break;
11022 case OMP_CLAUSE_DEPEND_OUT:
11023 case OMP_CLAUSE_DEPEND_INOUT:
11024 n_out++;
11025 break;
11026 default:
11027 gcc_unreachable ();
11029 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11030 tree array = create_tmp_var (type);
11031 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11032 NULL_TREE);
11033 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11034 gimple_seq_add_stmt (iseq, g);
11035 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11036 NULL_TREE);
11037 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11038 gimple_seq_add_stmt (iseq, g);
11039 for (i = 0; i < 2; i++)
11041 if ((i ? n_in : n_out) == 0)
11042 continue;
11043 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11044 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11045 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11047 tree t = OMP_CLAUSE_DECL (c);
11048 t = fold_convert (ptr_type_node, t);
11049 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11050 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11051 NULL_TREE, NULL_TREE);
11052 g = gimple_build_assign (r, t);
11053 gimple_seq_add_stmt (iseq, g);
11056 tree *p = gimple_omp_task_clauses_ptr (stmt);
11057 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11058 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11059 OMP_CLAUSE_CHAIN (c) = *p;
11060 *p = c;
11061 tree clobber = build_constructor (type, NULL);
11062 TREE_THIS_VOLATILE (clobber) = 1;
11063 g = gimple_build_assign (array, clobber);
11064 gimple_seq_add_stmt (oseq, g);
11067 /* Lower the OpenMP parallel or task directive in the current statement
11068 in GSI_P. CTX holds context information for the directive. */
11070 static void
11071 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11073 tree clauses;
11074 tree child_fn, t;
11075 gimple stmt = gsi_stmt (*gsi_p);
11076 gbind *par_bind, *bind, *dep_bind = NULL;
11077 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11078 location_t loc = gimple_location (stmt);
11080 clauses = gimple_omp_taskreg_clauses (stmt);
11081 par_bind
11082 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11083 par_body = gimple_bind_body (par_bind);
11084 child_fn = ctx->cb.dst_fn;
11085 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11086 && !gimple_omp_parallel_combined_p (stmt))
11088 struct walk_stmt_info wi;
11089 int ws_num = 0;
11091 memset (&wi, 0, sizeof (wi));
11092 wi.info = &ws_num;
11093 wi.val_only = true;
11094 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11095 if (ws_num == 1)
11096 gimple_omp_parallel_set_combined_p (stmt, true);
11098 gimple_seq dep_ilist = NULL;
11099 gimple_seq dep_olist = NULL;
11100 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11101 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11103 push_gimplify_context ();
11104 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11105 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11108 if (ctx->srecord_type)
11109 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11111 push_gimplify_context ();
11113 par_olist = NULL;
11114 par_ilist = NULL;
11115 par_rlist = NULL;
11116 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11117 lower_omp (&par_body, ctx);
11118 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11119 lower_reduction_clauses (clauses, &par_rlist, ctx);
11121 /* Declare all the variables created by mapping and the variables
11122 declared in the scope of the parallel body. */
11123 record_vars_into (ctx->block_vars, child_fn);
11124 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11126 if (ctx->record_type)
11128 ctx->sender_decl
11129 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11130 : ctx->record_type, ".omp_data_o");
11131 DECL_NAMELESS (ctx->sender_decl) = 1;
11132 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11133 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11136 olist = NULL;
11137 ilist = NULL;
11138 lower_send_clauses (clauses, &ilist, &olist, ctx);
11139 lower_send_shared_vars (&ilist, &olist, ctx);
11141 if (ctx->record_type)
11143 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11144 TREE_THIS_VOLATILE (clobber) = 1;
11145 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11146 clobber));
11149 /* Once all the expansions are done, sequence all the different
11150 fragments inside gimple_omp_body. */
11152 new_body = NULL;
11154 if (ctx->record_type)
11156 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11157 /* fixup_child_record_type might have changed receiver_decl's type. */
11158 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11159 gimple_seq_add_stmt (&new_body,
11160 gimple_build_assign (ctx->receiver_decl, t));
11163 gimple_seq_add_seq (&new_body, par_ilist);
11164 gimple_seq_add_seq (&new_body, par_body);
11165 gimple_seq_add_seq (&new_body, par_rlist);
11166 if (ctx->cancellable)
11167 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11168 gimple_seq_add_seq (&new_body, par_olist);
11169 new_body = maybe_catch_exception (new_body);
11170 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11171 gimple_omp_set_body (stmt, new_body);
11173 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11174 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11175 gimple_bind_add_seq (bind, ilist);
11176 gimple_bind_add_stmt (bind, stmt);
11177 gimple_bind_add_seq (bind, olist);
11179 pop_gimplify_context (NULL);
11181 if (dep_bind)
11183 gimple_bind_add_seq (dep_bind, dep_ilist);
11184 gimple_bind_add_stmt (dep_bind, bind);
11185 gimple_bind_add_seq (dep_bind, dep_olist);
11186 pop_gimplify_context (dep_bind);
11190 /* Lower the GIMPLE_OMP_TARGET in the current statement
11191 in GSI_P. CTX holds context information for the directive. */
11193 static void
11194 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11196 tree clauses;
11197 tree child_fn, t, c;
11198 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11199 gbind *tgt_bind, *bind;
11200 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11201 location_t loc = gimple_location (stmt);
11202 bool offloaded, data_region;
11203 unsigned int map_cnt = 0;
11205 offloaded = is_gimple_omp_offloaded (stmt);
11206 switch (gimple_omp_target_kind (stmt))
11208 case GF_OMP_TARGET_KIND_REGION:
11209 case GF_OMP_TARGET_KIND_UPDATE:
11210 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11211 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11212 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11213 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11214 data_region = false;
11215 break;
11216 case GF_OMP_TARGET_KIND_DATA:
11217 case GF_OMP_TARGET_KIND_OACC_DATA:
11218 data_region = true;
11219 break;
11220 default:
11221 gcc_unreachable ();
11224 clauses = gimple_omp_target_clauses (stmt);
11226 tgt_bind = NULL;
11227 tgt_body = NULL;
11228 if (offloaded)
11230 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11231 tgt_body = gimple_bind_body (tgt_bind);
11233 else if (data_region)
11234 tgt_body = gimple_omp_body (stmt);
11235 child_fn = ctx->cb.dst_fn;
11237 push_gimplify_context ();
11239 irlist = NULL;
11240 orlist = NULL;
11241 if (offloaded
11242 && is_gimple_omp_oacc_specifically (stmt))
11243 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11245 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11246 switch (OMP_CLAUSE_CODE (c))
11248 tree var, x;
11250 default:
11251 break;
11252 case OMP_CLAUSE_MAP:
11253 #ifdef ENABLE_CHECKING
11254 /* First check what we're prepared to handle in the following. */
11255 switch (OMP_CLAUSE_MAP_KIND (c))
11257 case OMP_CLAUSE_MAP_ALLOC:
11258 case OMP_CLAUSE_MAP_TO:
11259 case OMP_CLAUSE_MAP_FROM:
11260 case OMP_CLAUSE_MAP_TOFROM:
11261 case OMP_CLAUSE_MAP_POINTER:
11262 case OMP_CLAUSE_MAP_TO_PSET:
11263 break;
11264 case OMP_CLAUSE_MAP_FORCE_ALLOC:
11265 case OMP_CLAUSE_MAP_FORCE_TO:
11266 case OMP_CLAUSE_MAP_FORCE_FROM:
11267 case OMP_CLAUSE_MAP_FORCE_TOFROM:
11268 case OMP_CLAUSE_MAP_FORCE_PRESENT:
11269 case OMP_CLAUSE_MAP_FORCE_DEALLOC:
11270 case OMP_CLAUSE_MAP_FORCE_DEVICEPTR:
11271 gcc_assert (is_gimple_omp_oacc_specifically (stmt));
11272 break;
11273 default:
11274 gcc_unreachable ();
11276 #endif
11277 /* FALLTHRU */
11278 case OMP_CLAUSE_TO:
11279 case OMP_CLAUSE_FROM:
11280 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
11281 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_TARGET
11282 && (gimple_omp_target_kind (stmt)
11283 == GF_OMP_TARGET_KIND_UPDATE));
11284 var = OMP_CLAUSE_DECL (c);
11285 if (!DECL_P (var))
11287 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11288 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11289 map_cnt++;
11290 continue;
11293 if (DECL_SIZE (var)
11294 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11296 tree var2 = DECL_VALUE_EXPR (var);
11297 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11298 var2 = TREE_OPERAND (var2, 0);
11299 gcc_assert (DECL_P (var2));
11300 var = var2;
11303 if (!maybe_lookup_field (var, ctx))
11304 continue;
11306 if (offloaded)
11308 x = build_receiver_ref (var, true, ctx);
11309 tree new_var = lookup_decl (var, ctx);
11310 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP);
11311 gcc_assert ((OMP_CLAUSE_MAP_KIND (c)
11312 != OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
11313 || TREE_CODE (TREE_TYPE (var)) != ARRAY_TYPE);
11314 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
11315 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11316 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11317 x = build_simple_mem_ref (x);
11318 SET_DECL_VALUE_EXPR (new_var, x);
11319 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11321 map_cnt++;
11324 if (offloaded)
11326 target_nesting_level++;
11327 lower_omp (&tgt_body, ctx);
11328 target_nesting_level--;
11330 else if (data_region)
11331 lower_omp (&tgt_body, ctx);
11333 if (offloaded)
11335 /* Declare all the variables created by mapping and the variables
11336 declared in the scope of the target body. */
11337 record_vars_into (ctx->block_vars, child_fn);
11338 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11341 olist = NULL;
11342 ilist = NULL;
11343 if (ctx->record_type)
11345 ctx->sender_decl
11346 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11347 DECL_NAMELESS (ctx->sender_decl) = 1;
11348 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11349 t = make_tree_vec (3);
11350 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11351 TREE_VEC_ELT (t, 1)
11352 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11353 ".omp_data_sizes");
11354 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11355 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11356 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11357 tree tkind_type;
11358 int talign_shift;
11359 if (is_gimple_omp_oacc_specifically (stmt))
11361 tkind_type = short_unsigned_type_node;
11362 talign_shift = 8;
11364 else
11366 tkind_type = unsigned_char_type_node;
11367 talign_shift = 3;
11369 TREE_VEC_ELT (t, 2)
11370 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11371 ".omp_data_kinds");
11372 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11373 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11374 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11375 gimple_omp_target_set_data_arg (stmt, t);
11377 vec<constructor_elt, va_gc> *vsize;
11378 vec<constructor_elt, va_gc> *vkind;
11379 vec_alloc (vsize, map_cnt);
11380 vec_alloc (vkind, map_cnt);
11381 unsigned int map_idx = 0;
11383 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11384 switch (OMP_CLAUSE_CODE (c))
11386 tree ovar, nc;
11388 default:
11389 break;
11390 case OMP_CLAUSE_MAP:
11391 case OMP_CLAUSE_TO:
11392 case OMP_CLAUSE_FROM:
11393 nc = c;
11394 ovar = OMP_CLAUSE_DECL (c);
11395 if (!DECL_P (ovar))
11397 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11398 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11400 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11401 == get_base_address (ovar));
11402 nc = OMP_CLAUSE_CHAIN (c);
11403 ovar = OMP_CLAUSE_DECL (nc);
11405 else
11407 tree x = build_sender_ref (ovar, ctx);
11408 tree v
11409 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11410 gimplify_assign (x, v, &ilist);
11411 nc = NULL_TREE;
11414 else
11416 if (DECL_SIZE (ovar)
11417 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11419 tree ovar2 = DECL_VALUE_EXPR (ovar);
11420 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11421 ovar2 = TREE_OPERAND (ovar2, 0);
11422 gcc_assert (DECL_P (ovar2));
11423 ovar = ovar2;
11425 if (!maybe_lookup_field (ovar, ctx))
11426 continue;
11429 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11430 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11431 talign = DECL_ALIGN_UNIT (ovar);
11432 if (nc)
11434 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11435 tree x = build_sender_ref (ovar, ctx);
11436 gcc_assert (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11437 || (OMP_CLAUSE_MAP_KIND (c)
11438 != OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
11439 || TREE_CODE (TREE_TYPE (ovar)) != ARRAY_TYPE);
11440 if (maybe_lookup_oacc_reduction (var, ctx))
11442 gcc_assert (offloaded
11443 && is_gimple_omp_oacc_specifically (stmt));
11444 gimplify_assign (x, var, &ilist);
11446 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11447 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
11448 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11449 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11451 gcc_assert (offloaded);
11452 tree avar
11453 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11454 mark_addressable (avar);
11455 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11456 talign = DECL_ALIGN_UNIT (avar);
11457 avar = build_fold_addr_expr (avar);
11458 gimplify_assign (x, avar, &ilist);
11460 else if (is_gimple_reg (var))
11462 gcc_assert (offloaded);
11463 tree avar = create_tmp_var (TREE_TYPE (var));
11464 mark_addressable (avar);
11465 enum omp_clause_map_kind map_kind
11466 = OMP_CLAUSE_MAP_KIND (c);
11467 if ((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
11468 && (map_kind & OMP_CLAUSE_MAP_TO))
11469 || map_kind == OMP_CLAUSE_MAP_POINTER
11470 || map_kind == OMP_CLAUSE_MAP_TO_PSET
11471 || map_kind == OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
11472 gimplify_assign (avar, var, &ilist);
11473 avar = build_fold_addr_expr (avar);
11474 gimplify_assign (x, avar, &ilist);
11475 if (((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
11476 && (map_kind & OMP_CLAUSE_MAP_FROM))
11477 || map_kind == OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
11478 && !TYPE_READONLY (TREE_TYPE (var)))
11480 x = build_sender_ref (ovar, ctx);
11481 x = build_simple_mem_ref (x);
11482 gimplify_assign (var, x, &olist);
11485 else
11487 var = build_fold_addr_expr (var);
11488 gimplify_assign (x, var, &ilist);
11491 tree s = OMP_CLAUSE_SIZE (c);
11492 if (s == NULL_TREE)
11493 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11494 s = fold_convert (size_type_node, s);
11495 tree purpose = size_int (map_idx++);
11496 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11497 if (TREE_CODE (s) != INTEGER_CST)
11498 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11500 unsigned HOST_WIDE_INT tkind;
11501 switch (OMP_CLAUSE_CODE (c))
11503 case OMP_CLAUSE_MAP:
11504 tkind = OMP_CLAUSE_MAP_KIND (c);
11505 break;
11506 case OMP_CLAUSE_TO:
11507 tkind = OMP_CLAUSE_MAP_TO;
11508 break;
11509 case OMP_CLAUSE_FROM:
11510 tkind = OMP_CLAUSE_MAP_FROM;
11511 break;
11512 default:
11513 gcc_unreachable ();
11515 gcc_assert (tkind < (HOST_WIDE_INT_C (1U) << talign_shift));
11516 talign = ceil_log2 (talign);
11517 tkind |= talign << talign_shift;
11518 gcc_assert (tkind <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11519 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11520 build_int_cstu (tkind_type, tkind));
11521 if (nc && nc != c)
11522 c = nc;
11525 gcc_assert (map_idx == map_cnt);
11527 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11528 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11529 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11530 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11531 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11533 gimple_seq initlist = NULL;
11534 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11535 TREE_VEC_ELT (t, 1)),
11536 &initlist, true, NULL_TREE);
11537 gimple_seq_add_seq (&ilist, initlist);
11539 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11540 NULL);
11541 TREE_THIS_VOLATILE (clobber) = 1;
11542 gimple_seq_add_stmt (&olist,
11543 gimple_build_assign (TREE_VEC_ELT (t, 1),
11544 clobber));
11547 tree clobber = build_constructor (ctx->record_type, NULL);
11548 TREE_THIS_VOLATILE (clobber) = 1;
11549 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11550 clobber));
11553 /* Once all the expansions are done, sequence all the different
11554 fragments inside gimple_omp_body. */
11556 new_body = NULL;
11558 if (offloaded
11559 && ctx->record_type)
11561 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11562 /* fixup_child_record_type might have changed receiver_decl's type. */
11563 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11564 gimple_seq_add_stmt (&new_body,
11565 gimple_build_assign (ctx->receiver_decl, t));
11568 if (offloaded)
11570 gimple_seq_add_seq (&new_body, tgt_body);
11571 new_body = maybe_catch_exception (new_body);
11573 else if (data_region)
11574 new_body = tgt_body;
11575 if (offloaded || data_region)
11577 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11578 gimple_omp_set_body (stmt, new_body);
11581 bind = gimple_build_bind (NULL, NULL,
11582 tgt_bind ? gimple_bind_block (tgt_bind)
11583 : NULL_TREE);
11584 gsi_replace (gsi_p, bind, true);
11585 gimple_bind_add_seq (bind, irlist);
11586 gimple_bind_add_seq (bind, ilist);
11587 gimple_bind_add_stmt (bind, stmt);
11588 gimple_bind_add_seq (bind, olist);
11589 gimple_bind_add_seq (bind, orlist);
11591 pop_gimplify_context (NULL);
11594 /* Expand code for an OpenMP teams directive. */
11596 static void
11597 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11599 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11600 push_gimplify_context ();
11602 tree block = make_node (BLOCK);
11603 gbind *bind = gimple_build_bind (NULL, NULL, block);
11604 gsi_replace (gsi_p, bind, true);
11605 gimple_seq bind_body = NULL;
11606 gimple_seq dlist = NULL;
11607 gimple_seq olist = NULL;
11609 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11610 OMP_CLAUSE_NUM_TEAMS);
11611 if (num_teams == NULL_TREE)
11612 num_teams = build_int_cst (unsigned_type_node, 0);
11613 else
11615 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11616 num_teams = fold_convert (unsigned_type_node, num_teams);
11617 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11619 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11620 OMP_CLAUSE_THREAD_LIMIT);
11621 if (thread_limit == NULL_TREE)
11622 thread_limit = build_int_cst (unsigned_type_node, 0);
11623 else
11625 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11626 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11627 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11628 fb_rvalue);
11631 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11632 &bind_body, &dlist, ctx, NULL);
11633 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11634 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11635 gimple_seq_add_stmt (&bind_body, teams_stmt);
11637 location_t loc = gimple_location (teams_stmt);
11638 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11639 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11640 gimple_set_location (call, loc);
11641 gimple_seq_add_stmt (&bind_body, call);
11643 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11644 gimple_omp_set_body (teams_stmt, NULL);
11645 gimple_seq_add_seq (&bind_body, olist);
11646 gimple_seq_add_seq (&bind_body, dlist);
11647 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11648 gimple_bind_set_body (bind, bind_body);
11650 pop_gimplify_context (bind);
11652 gimple_bind_append_vars (bind, ctx->block_vars);
11653 BLOCK_VARS (block) = ctx->block_vars;
11654 if (BLOCK_VARS (block))
11655 TREE_USED (block) = 1;
11659 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11660 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11661 of OpenMP context, but with task_shared_vars set. */
11663 static tree
11664 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11665 void *data)
11667 tree t = *tp;
11669 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11670 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11671 return t;
11673 if (task_shared_vars
11674 && DECL_P (t)
11675 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11676 return t;
11678 /* If a global variable has been privatized, TREE_CONSTANT on
11679 ADDR_EXPR might be wrong. */
11680 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11681 recompute_tree_invariant_for_addr_expr (t);
11683 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11684 return NULL_TREE;
11687 static void
11688 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11690 gimple stmt = gsi_stmt (*gsi_p);
11691 struct walk_stmt_info wi;
11692 gcall *call_stmt;
11694 if (gimple_has_location (stmt))
11695 input_location = gimple_location (stmt);
11697 if (task_shared_vars)
11698 memset (&wi, '\0', sizeof (wi));
11700 /* If we have issued syntax errors, avoid doing any heavy lifting.
11701 Just replace the OpenMP directives with a NOP to avoid
11702 confusing RTL expansion. */
11703 if (seen_error () && is_gimple_omp (stmt))
11705 gsi_replace (gsi_p, gimple_build_nop (), true);
11706 return;
11709 switch (gimple_code (stmt))
11711 case GIMPLE_COND:
11713 gcond *cond_stmt = as_a <gcond *> (stmt);
11714 if ((ctx || task_shared_vars)
11715 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11716 lower_omp_regimplify_p,
11717 ctx ? NULL : &wi, NULL)
11718 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11719 lower_omp_regimplify_p,
11720 ctx ? NULL : &wi, NULL)))
11721 gimple_regimplify_operands (cond_stmt, gsi_p);
11723 break;
11724 case GIMPLE_CATCH:
11725 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11726 break;
11727 case GIMPLE_EH_FILTER:
11728 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11729 break;
11730 case GIMPLE_TRY:
11731 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11732 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11733 break;
11734 case GIMPLE_TRANSACTION:
11735 lower_omp (gimple_transaction_body_ptr (
11736 as_a <gtransaction *> (stmt)),
11737 ctx);
11738 break;
11739 case GIMPLE_BIND:
11740 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11741 break;
11742 case GIMPLE_OMP_PARALLEL:
11743 case GIMPLE_OMP_TASK:
11744 ctx = maybe_lookup_ctx (stmt);
11745 gcc_assert (ctx);
11746 if (ctx->cancellable)
11747 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11748 lower_omp_taskreg (gsi_p, ctx);
11749 break;
11750 case GIMPLE_OMP_FOR:
11751 ctx = maybe_lookup_ctx (stmt);
11752 gcc_assert (ctx);
11753 if (ctx->cancellable)
11754 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11755 lower_omp_for (gsi_p, ctx);
11756 break;
11757 case GIMPLE_OMP_SECTIONS:
11758 ctx = maybe_lookup_ctx (stmt);
11759 gcc_assert (ctx);
11760 if (ctx->cancellable)
11761 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11762 lower_omp_sections (gsi_p, ctx);
11763 break;
11764 case GIMPLE_OMP_SINGLE:
11765 ctx = maybe_lookup_ctx (stmt);
11766 gcc_assert (ctx);
11767 lower_omp_single (gsi_p, ctx);
11768 break;
11769 case GIMPLE_OMP_MASTER:
11770 ctx = maybe_lookup_ctx (stmt);
11771 gcc_assert (ctx);
11772 lower_omp_master (gsi_p, ctx);
11773 break;
11774 case GIMPLE_OMP_TASKGROUP:
11775 ctx = maybe_lookup_ctx (stmt);
11776 gcc_assert (ctx);
11777 lower_omp_taskgroup (gsi_p, ctx);
11778 break;
11779 case GIMPLE_OMP_ORDERED:
11780 ctx = maybe_lookup_ctx (stmt);
11781 gcc_assert (ctx);
11782 lower_omp_ordered (gsi_p, ctx);
11783 break;
11784 case GIMPLE_OMP_CRITICAL:
11785 ctx = maybe_lookup_ctx (stmt);
11786 gcc_assert (ctx);
11787 lower_omp_critical (gsi_p, ctx);
11788 break;
11789 case GIMPLE_OMP_ATOMIC_LOAD:
11790 if ((ctx || task_shared_vars)
11791 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11792 as_a <gomp_atomic_load *> (stmt)),
11793 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11794 gimple_regimplify_operands (stmt, gsi_p);
11795 break;
11796 case GIMPLE_OMP_TARGET:
11797 ctx = maybe_lookup_ctx (stmt);
11798 gcc_assert (ctx);
11799 if (is_gimple_omp_oacc_specifically (stmt))
11800 gcc_assert (!ctx->cancellable);
11801 lower_omp_target (gsi_p, ctx);
11802 break;
11803 case GIMPLE_OMP_TEAMS:
11804 ctx = maybe_lookup_ctx (stmt);
11805 gcc_assert (ctx);
11806 lower_omp_teams (gsi_p, ctx);
11807 break;
11808 case GIMPLE_CALL:
11809 tree fndecl;
11810 call_stmt = as_a <gcall *> (stmt);
11811 fndecl = gimple_call_fndecl (call_stmt);
11812 if (fndecl
11813 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11814 switch (DECL_FUNCTION_CODE (fndecl))
11816 case BUILT_IN_GOMP_BARRIER:
11817 if (ctx == NULL)
11818 break;
11819 /* FALLTHRU */
11820 case BUILT_IN_GOMP_CANCEL:
11821 case BUILT_IN_GOMP_CANCELLATION_POINT:
11822 omp_context *cctx;
11823 cctx = ctx;
11824 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11825 cctx = cctx->outer;
11826 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
11827 if (!cctx->cancellable)
11829 if (DECL_FUNCTION_CODE (fndecl)
11830 == BUILT_IN_GOMP_CANCELLATION_POINT)
11832 stmt = gimple_build_nop ();
11833 gsi_replace (gsi_p, stmt, false);
11835 break;
11837 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11839 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11840 gimple_call_set_fndecl (call_stmt, fndecl);
11841 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
11843 tree lhs;
11844 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
11845 gimple_call_set_lhs (call_stmt, lhs);
11846 tree fallthru_label;
11847 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11848 gimple g;
11849 g = gimple_build_label (fallthru_label);
11850 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11851 g = gimple_build_cond (NE_EXPR, lhs,
11852 fold_convert (TREE_TYPE (lhs),
11853 boolean_false_node),
11854 cctx->cancel_label, fallthru_label);
11855 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11856 break;
11857 default:
11858 break;
11860 /* FALLTHRU */
11861 default:
11862 if ((ctx || task_shared_vars)
11863 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11864 ctx ? NULL : &wi))
11866 /* Just remove clobbers, this should happen only if we have
11867 "privatized" local addressable variables in SIMD regions,
11868 the clobber isn't needed in that case and gimplifying address
11869 of the ARRAY_REF into a pointer and creating MEM_REF based
11870 clobber would create worse code than we get with the clobber
11871 dropped. */
11872 if (gimple_clobber_p (stmt))
11874 gsi_replace (gsi_p, gimple_build_nop (), true);
11875 break;
11877 gimple_regimplify_operands (stmt, gsi_p);
11879 break;
11883 static void
11884 lower_omp (gimple_seq *body, omp_context *ctx)
11886 location_t saved_location = input_location;
11887 gimple_stmt_iterator gsi;
11888 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11889 lower_omp_1 (&gsi, ctx);
11890 /* During gimplification, we haven't folded statments inside offloading
11891 regions (gimplify.c:maybe_fold_stmt); do that now. */
11892 if (target_nesting_level)
11893 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11894 fold_stmt (&gsi);
11895 input_location = saved_location;
11898 /* Main entry point. */
11900 static unsigned int
11901 execute_lower_omp (void)
11903 gimple_seq body;
11904 int i;
11905 omp_context *ctx;
11907 /* This pass always runs, to provide PROP_gimple_lomp.
11908 But often, there is nothing to do. */
11909 if (flag_openacc == 0 && flag_openmp == 0 && flag_openmp_simd == 0
11910 && flag_cilkplus == 0)
11911 return 0;
11913 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11914 delete_omp_context);
11916 body = gimple_body (current_function_decl);
11917 scan_omp (&body, NULL);
11918 gcc_assert (taskreg_nesting_level == 0);
11919 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11920 finish_taskreg_scan (ctx);
11921 taskreg_contexts.release ();
11923 if (all_contexts->root)
11925 if (task_shared_vars)
11926 push_gimplify_context ();
11927 lower_omp (&body, NULL);
11928 if (task_shared_vars)
11929 pop_gimplify_context (NULL);
11932 if (all_contexts)
11934 splay_tree_delete (all_contexts);
11935 all_contexts = NULL;
11937 BITMAP_FREE (task_shared_vars);
11938 return 0;
11941 namespace {
11943 const pass_data pass_data_lower_omp =
11945 GIMPLE_PASS, /* type */
11946 "omplower", /* name */
11947 OPTGROUP_NONE, /* optinfo_flags */
11948 TV_NONE, /* tv_id */
11949 PROP_gimple_any, /* properties_required */
11950 PROP_gimple_lomp, /* properties_provided */
11951 0, /* properties_destroyed */
11952 0, /* todo_flags_start */
11953 0, /* todo_flags_finish */
11956 class pass_lower_omp : public gimple_opt_pass
11958 public:
11959 pass_lower_omp (gcc::context *ctxt)
11960 : gimple_opt_pass (pass_data_lower_omp, ctxt)
11963 /* opt_pass methods: */
11964 virtual unsigned int execute (function *) { return execute_lower_omp (); }
11966 }; // class pass_lower_omp
11968 } // anon namespace
11970 gimple_opt_pass *
11971 make_pass_lower_omp (gcc::context *ctxt)
11973 return new pass_lower_omp (ctxt);
11976 /* The following is a utility to diagnose structured block violations.
11977 It is not part of the "omplower" pass, as that's invoked too late. It
11978 should be invoked by the respective front ends after gimplification. */
11980 static splay_tree all_labels;
11982 /* Check for mismatched contexts and generate an error if needed. Return
11983 true if an error is detected. */
11985 static bool
11986 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
11987 gimple branch_ctx, gimple label_ctx)
11989 gcc_assert (!branch_ctx || is_gimple_omp (branch_ctx));
11990 gcc_assert (!label_ctx || is_gimple_omp (label_ctx));
11992 if (label_ctx == branch_ctx)
11993 return false;
11995 const char* kind = NULL;
11997 if (flag_cilkplus)
11999 if ((branch_ctx
12000 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12001 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12002 || (label_ctx
12003 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12004 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12005 kind = "Cilk Plus";
12007 if (flag_openacc)
12009 if ((branch_ctx && is_gimple_omp_oacc_specifically (branch_ctx))
12010 || (label_ctx && is_gimple_omp_oacc_specifically (label_ctx)))
12012 gcc_assert (kind == NULL);
12013 kind = "OpenACC";
12016 if (kind == NULL)
12018 gcc_assert (flag_openmp);
12019 kind = "OpenMP";
12023 Previously we kept track of the label's entire context in diagnose_sb_[12]
12024 so we could traverse it and issue a correct "exit" or "enter" error
12025 message upon a structured block violation.
12027 We built the context by building a list with tree_cons'ing, but there is
12028 no easy counterpart in gimple tuples. It seems like far too much work
12029 for issuing exit/enter error messages. If someone really misses the
12030 distinct error message... patches welcome.
12033 #if 0
12034 /* Try to avoid confusing the user by producing and error message
12035 with correct "exit" or "enter" verbiage. We prefer "exit"
12036 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12037 if (branch_ctx == NULL)
12038 exit_p = false;
12039 else
12041 while (label_ctx)
12043 if (TREE_VALUE (label_ctx) == branch_ctx)
12045 exit_p = false;
12046 break;
12048 label_ctx = TREE_CHAIN (label_ctx);
12052 if (exit_p)
12053 error ("invalid exit from %s structured block", kind);
12054 else
12055 error ("invalid entry to %s structured block", kind);
12056 #endif
12058 /* If it's obvious we have an invalid entry, be specific about the error. */
12059 if (branch_ctx == NULL)
12060 error ("invalid entry to %s structured block", kind);
12061 else
12063 /* Otherwise, be vague and lazy, but efficient. */
12064 error ("invalid branch to/from %s structured block", kind);
12067 gsi_replace (gsi_p, gimple_build_nop (), false);
12068 return true;
12071 /* Pass 1: Create a minimal tree of structured blocks, and record
12072 where each label is found. */
12074 static tree
12075 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12076 struct walk_stmt_info *wi)
12078 gimple context = (gimple) wi->info;
12079 gimple inner_context;
12080 gimple stmt = gsi_stmt (*gsi_p);
12082 *handled_ops_p = true;
12084 switch (gimple_code (stmt))
12086 WALK_SUBSTMTS;
12088 case GIMPLE_OMP_PARALLEL:
12089 case GIMPLE_OMP_TASK:
12090 case GIMPLE_OMP_SECTIONS:
12091 case GIMPLE_OMP_SINGLE:
12092 case GIMPLE_OMP_SECTION:
12093 case GIMPLE_OMP_MASTER:
12094 case GIMPLE_OMP_ORDERED:
12095 case GIMPLE_OMP_CRITICAL:
12096 case GIMPLE_OMP_TARGET:
12097 case GIMPLE_OMP_TEAMS:
12098 case GIMPLE_OMP_TASKGROUP:
12099 /* The minimal context here is just the current construct. */
12100 inner_context = stmt;
12101 wi->info = inner_context;
12102 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12103 wi->info = context;
12104 break;
12106 case GIMPLE_OMP_FOR:
12107 inner_context = stmt;
12108 wi->info = inner_context;
12109 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12110 walk them. */
12111 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12112 diagnose_sb_1, NULL, wi);
12113 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12114 wi->info = context;
12115 break;
12117 case GIMPLE_LABEL:
12118 splay_tree_insert (all_labels,
12119 (splay_tree_key) gimple_label_label (
12120 as_a <glabel *> (stmt)),
12121 (splay_tree_value) context);
12122 break;
12124 default:
12125 break;
12128 return NULL_TREE;
12131 /* Pass 2: Check each branch and see if its context differs from that of
12132 the destination label's context. */
12134 static tree
12135 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12136 struct walk_stmt_info *wi)
12138 gimple context = (gimple) wi->info;
12139 splay_tree_node n;
12140 gimple stmt = gsi_stmt (*gsi_p);
12142 *handled_ops_p = true;
12144 switch (gimple_code (stmt))
12146 WALK_SUBSTMTS;
12148 case GIMPLE_OMP_PARALLEL:
12149 case GIMPLE_OMP_TASK:
12150 case GIMPLE_OMP_SECTIONS:
12151 case GIMPLE_OMP_SINGLE:
12152 case GIMPLE_OMP_SECTION:
12153 case GIMPLE_OMP_MASTER:
12154 case GIMPLE_OMP_ORDERED:
12155 case GIMPLE_OMP_CRITICAL:
12156 case GIMPLE_OMP_TARGET:
12157 case GIMPLE_OMP_TEAMS:
12158 case GIMPLE_OMP_TASKGROUP:
12159 wi->info = stmt;
12160 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12161 wi->info = context;
12162 break;
12164 case GIMPLE_OMP_FOR:
12165 wi->info = stmt;
12166 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12167 walk them. */
12168 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12169 diagnose_sb_2, NULL, wi);
12170 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12171 wi->info = context;
12172 break;
12174 case GIMPLE_COND:
12176 gcond *cond_stmt = as_a <gcond *> (stmt);
12177 tree lab = gimple_cond_true_label (cond_stmt);
12178 if (lab)
12180 n = splay_tree_lookup (all_labels,
12181 (splay_tree_key) lab);
12182 diagnose_sb_0 (gsi_p, context,
12183 n ? (gimple) n->value : NULL);
12185 lab = gimple_cond_false_label (cond_stmt);
12186 if (lab)
12188 n = splay_tree_lookup (all_labels,
12189 (splay_tree_key) lab);
12190 diagnose_sb_0 (gsi_p, context,
12191 n ? (gimple) n->value : NULL);
12194 break;
12196 case GIMPLE_GOTO:
12198 tree lab = gimple_goto_dest (stmt);
12199 if (TREE_CODE (lab) != LABEL_DECL)
12200 break;
12202 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12203 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12205 break;
12207 case GIMPLE_SWITCH:
12209 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12210 unsigned int i;
12211 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12213 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12214 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12215 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12216 break;
12219 break;
12221 case GIMPLE_RETURN:
12222 diagnose_sb_0 (gsi_p, context, NULL);
12223 break;
12225 default:
12226 break;
12229 return NULL_TREE;
12232 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12233 GIMPLE codes. */
12234 bool
12235 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12236 int *region_idx)
12238 gimple last = last_stmt (bb);
12239 enum gimple_code code = gimple_code (last);
12240 struct omp_region *cur_region = *region;
12241 bool fallthru = false;
12243 switch (code)
12245 case GIMPLE_OMP_PARALLEL:
12246 case GIMPLE_OMP_TASK:
12247 case GIMPLE_OMP_FOR:
12248 case GIMPLE_OMP_SINGLE:
12249 case GIMPLE_OMP_TEAMS:
12250 case GIMPLE_OMP_MASTER:
12251 case GIMPLE_OMP_TASKGROUP:
12252 case GIMPLE_OMP_ORDERED:
12253 case GIMPLE_OMP_CRITICAL:
12254 case GIMPLE_OMP_SECTION:
12255 cur_region = new_omp_region (bb, code, cur_region);
12256 fallthru = true;
12257 break;
12259 case GIMPLE_OMP_TARGET:
12260 cur_region = new_omp_region (bb, code, cur_region);
12261 fallthru = true;
12262 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE
12263 || gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_OACC_UPDATE
12264 || (gimple_omp_target_kind (last)
12265 == GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA))
12266 cur_region = cur_region->outer;
12267 break;
12269 case GIMPLE_OMP_SECTIONS:
12270 cur_region = new_omp_region (bb, code, cur_region);
12271 fallthru = true;
12272 break;
12274 case GIMPLE_OMP_SECTIONS_SWITCH:
12275 fallthru = false;
12276 break;
12278 case GIMPLE_OMP_ATOMIC_LOAD:
12279 case GIMPLE_OMP_ATOMIC_STORE:
12280 fallthru = true;
12281 break;
12283 case GIMPLE_OMP_RETURN:
12284 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12285 somewhere other than the next block. This will be
12286 created later. */
12287 cur_region->exit = bb;
12288 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12289 cur_region = cur_region->outer;
12290 break;
12292 case GIMPLE_OMP_CONTINUE:
12293 cur_region->cont = bb;
12294 switch (cur_region->type)
12296 case GIMPLE_OMP_FOR:
12297 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12298 succs edges as abnormal to prevent splitting
12299 them. */
12300 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12301 /* Make the loopback edge. */
12302 make_edge (bb, single_succ (cur_region->entry),
12303 EDGE_ABNORMAL);
12305 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12306 corresponds to the case that the body of the loop
12307 is not executed at all. */
12308 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12309 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12310 fallthru = false;
12311 break;
12313 case GIMPLE_OMP_SECTIONS:
12314 /* Wire up the edges into and out of the nested sections. */
12316 basic_block switch_bb = single_succ (cur_region->entry);
12318 struct omp_region *i;
12319 for (i = cur_region->inner; i ; i = i->next)
12321 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12322 make_edge (switch_bb, i->entry, 0);
12323 make_edge (i->exit, bb, EDGE_FALLTHRU);
12326 /* Make the loopback edge to the block with
12327 GIMPLE_OMP_SECTIONS_SWITCH. */
12328 make_edge (bb, switch_bb, 0);
12330 /* Make the edge from the switch to exit. */
12331 make_edge (switch_bb, bb->next_bb, 0);
12332 fallthru = false;
12334 break;
12336 default:
12337 gcc_unreachable ();
12339 break;
12341 default:
12342 gcc_unreachable ();
12345 if (*region != cur_region)
12347 *region = cur_region;
12348 if (cur_region)
12349 *region_idx = cur_region->entry->index;
12350 else
12351 *region_idx = 0;
12354 return fallthru;
12357 static unsigned int
12358 diagnose_omp_structured_block_errors (void)
12360 struct walk_stmt_info wi;
12361 gimple_seq body = gimple_body (current_function_decl);
12363 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12365 memset (&wi, 0, sizeof (wi));
12366 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12368 memset (&wi, 0, sizeof (wi));
12369 wi.want_locations = true;
12370 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12372 gimple_set_body (current_function_decl, body);
12374 splay_tree_delete (all_labels);
12375 all_labels = NULL;
12377 return 0;
12380 namespace {
12382 const pass_data pass_data_diagnose_omp_blocks =
12384 GIMPLE_PASS, /* type */
12385 "*diagnose_omp_blocks", /* name */
12386 OPTGROUP_NONE, /* optinfo_flags */
12387 TV_NONE, /* tv_id */
12388 PROP_gimple_any, /* properties_required */
12389 0, /* properties_provided */
12390 0, /* properties_destroyed */
12391 0, /* todo_flags_start */
12392 0, /* todo_flags_finish */
12395 class pass_diagnose_omp_blocks : public gimple_opt_pass
12397 public:
12398 pass_diagnose_omp_blocks (gcc::context *ctxt)
12399 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12402 /* opt_pass methods: */
12403 virtual bool gate (function *)
12405 return flag_openacc || flag_openmp || flag_cilkplus;
12407 virtual unsigned int execute (function *)
12409 return diagnose_omp_structured_block_errors ();
12412 }; // class pass_diagnose_omp_blocks
12414 } // anon namespace
12416 gimple_opt_pass *
12417 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12419 return new pass_diagnose_omp_blocks (ctxt);
12422 /* SIMD clone supporting code. */
12424 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12425 of arguments to reserve space for. */
12427 static struct cgraph_simd_clone *
12428 simd_clone_struct_alloc (int nargs)
12430 struct cgraph_simd_clone *clone_info;
12431 size_t len = (sizeof (struct cgraph_simd_clone)
12432 + nargs * sizeof (struct cgraph_simd_clone_arg));
12433 clone_info = (struct cgraph_simd_clone *)
12434 ggc_internal_cleared_alloc (len);
12435 return clone_info;
12438 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12440 static inline void
12441 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12442 struct cgraph_simd_clone *from)
12444 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12445 + ((from->nargs - from->inbranch)
12446 * sizeof (struct cgraph_simd_clone_arg))));
12449 /* Return vector of parameter types of function FNDECL. This uses
12450 TYPE_ARG_TYPES if available, otherwise falls back to types of
12451 DECL_ARGUMENTS types. */
12453 vec<tree>
12454 simd_clone_vector_of_formal_parm_types (tree fndecl)
12456 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12457 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12458 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12459 unsigned int i;
12460 tree arg;
12461 FOR_EACH_VEC_ELT (args, i, arg)
12462 args[i] = TREE_TYPE (args[i]);
12463 return args;
12466 /* Given a simd function in NODE, extract the simd specific
12467 information from the OMP clauses passed in CLAUSES, and return
12468 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12469 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12470 otherwise set to FALSE. */
12472 static struct cgraph_simd_clone *
12473 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12474 bool *inbranch_specified)
12476 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12477 tree t;
12478 int n;
12479 *inbranch_specified = false;
12481 n = args.length ();
12482 if (n > 0 && args.last () == void_type_node)
12483 n--;
12485 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12486 be cloned have a distinctive artificial label in addition to "omp
12487 declare simd". */
12488 bool cilk_clone
12489 = (flag_cilkplus
12490 && lookup_attribute ("cilk simd function",
12491 DECL_ATTRIBUTES (node->decl)));
12493 /* Allocate one more than needed just in case this is an in-branch
12494 clone which will require a mask argument. */
12495 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12496 clone_info->nargs = n;
12497 clone_info->cilk_elemental = cilk_clone;
12499 if (!clauses)
12501 args.release ();
12502 return clone_info;
12504 clauses = TREE_VALUE (clauses);
12505 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12506 return clone_info;
12508 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12510 switch (OMP_CLAUSE_CODE (t))
12512 case OMP_CLAUSE_INBRANCH:
12513 clone_info->inbranch = 1;
12514 *inbranch_specified = true;
12515 break;
12516 case OMP_CLAUSE_NOTINBRANCH:
12517 clone_info->inbranch = 0;
12518 *inbranch_specified = true;
12519 break;
12520 case OMP_CLAUSE_SIMDLEN:
12521 clone_info->simdlen
12522 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12523 break;
12524 case OMP_CLAUSE_LINEAR:
12526 tree decl = OMP_CLAUSE_DECL (t);
12527 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12528 int argno = TREE_INT_CST_LOW (decl);
12529 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12531 clone_info->args[argno].arg_type
12532 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12533 clone_info->args[argno].linear_step = tree_to_shwi (step);
12534 gcc_assert (clone_info->args[argno].linear_step >= 0
12535 && clone_info->args[argno].linear_step < n);
12537 else
12539 if (POINTER_TYPE_P (args[argno]))
12540 step = fold_convert (ssizetype, step);
12541 if (!tree_fits_shwi_p (step))
12543 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12544 "ignoring large linear step");
12545 args.release ();
12546 return NULL;
12548 else if (integer_zerop (step))
12550 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12551 "ignoring zero linear step");
12552 args.release ();
12553 return NULL;
12555 else
12557 clone_info->args[argno].arg_type
12558 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12559 clone_info->args[argno].linear_step = tree_to_shwi (step);
12562 break;
12564 case OMP_CLAUSE_UNIFORM:
12566 tree decl = OMP_CLAUSE_DECL (t);
12567 int argno = tree_to_uhwi (decl);
12568 clone_info->args[argno].arg_type
12569 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12570 break;
12572 case OMP_CLAUSE_ALIGNED:
12574 tree decl = OMP_CLAUSE_DECL (t);
12575 int argno = tree_to_uhwi (decl);
12576 clone_info->args[argno].alignment
12577 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12578 break;
12580 default:
12581 break;
12584 args.release ();
12585 return clone_info;
12588 /* Given a SIMD clone in NODE, calculate the characteristic data
12589 type and return the coresponding type. The characteristic data
12590 type is computed as described in the Intel Vector ABI. */
12592 static tree
12593 simd_clone_compute_base_data_type (struct cgraph_node *node,
12594 struct cgraph_simd_clone *clone_info)
12596 tree type = integer_type_node;
12597 tree fndecl = node->decl;
12599 /* a) For non-void function, the characteristic data type is the
12600 return type. */
12601 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12602 type = TREE_TYPE (TREE_TYPE (fndecl));
12604 /* b) If the function has any non-uniform, non-linear parameters,
12605 then the characteristic data type is the type of the first
12606 such parameter. */
12607 else
12609 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12610 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12611 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12613 type = map[i];
12614 break;
12616 map.release ();
12619 /* c) If the characteristic data type determined by a) or b) above
12620 is struct, union, or class type which is pass-by-value (except
12621 for the type that maps to the built-in complex data type), the
12622 characteristic data type is int. */
12623 if (RECORD_OR_UNION_TYPE_P (type)
12624 && !aggregate_value_p (type, NULL)
12625 && TREE_CODE (type) != COMPLEX_TYPE)
12626 return integer_type_node;
12628 /* d) If none of the above three classes is applicable, the
12629 characteristic data type is int. */
12631 return type;
12633 /* e) For Intel Xeon Phi native and offload compilation, if the
12634 resulting characteristic data type is 8-bit or 16-bit integer
12635 data type, the characteristic data type is int. */
12636 /* Well, we don't handle Xeon Phi yet. */
12639 static tree
12640 simd_clone_mangle (struct cgraph_node *node,
12641 struct cgraph_simd_clone *clone_info)
12643 char vecsize_mangle = clone_info->vecsize_mangle;
12644 char mask = clone_info->inbranch ? 'M' : 'N';
12645 unsigned int simdlen = clone_info->simdlen;
12646 unsigned int n;
12647 pretty_printer pp;
12649 gcc_assert (vecsize_mangle && simdlen);
12651 pp_string (&pp, "_ZGV");
12652 pp_character (&pp, vecsize_mangle);
12653 pp_character (&pp, mask);
12654 pp_decimal_int (&pp, simdlen);
12656 for (n = 0; n < clone_info->nargs; ++n)
12658 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12660 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12661 pp_character (&pp, 'u');
12662 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12664 gcc_assert (arg.linear_step != 0);
12665 pp_character (&pp, 'l');
12666 if (arg.linear_step > 1)
12667 pp_unsigned_wide_integer (&pp, arg.linear_step);
12668 else if (arg.linear_step < 0)
12670 pp_character (&pp, 'n');
12671 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12672 arg.linear_step));
12675 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12677 pp_character (&pp, 's');
12678 pp_unsigned_wide_integer (&pp, arg.linear_step);
12680 else
12681 pp_character (&pp, 'v');
12682 if (arg.alignment)
12684 pp_character (&pp, 'a');
12685 pp_decimal_int (&pp, arg.alignment);
12689 pp_underscore (&pp);
12690 pp_string (&pp,
12691 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
12692 const char *str = pp_formatted_text (&pp);
12694 /* If there already is a SIMD clone with the same mangled name, don't
12695 add another one. This can happen e.g. for
12696 #pragma omp declare simd
12697 #pragma omp declare simd simdlen(8)
12698 int foo (int, int);
12699 if the simdlen is assumed to be 8 for the first one, etc. */
12700 for (struct cgraph_node *clone = node->simd_clones; clone;
12701 clone = clone->simdclone->next_clone)
12702 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12703 str) == 0)
12704 return NULL_TREE;
12706 return get_identifier (str);
12709 /* Create a simd clone of OLD_NODE and return it. */
12711 static struct cgraph_node *
12712 simd_clone_create (struct cgraph_node *old_node)
12714 struct cgraph_node *new_node;
12715 if (old_node->definition)
12717 if (!old_node->has_gimple_body_p ())
12718 return NULL;
12719 old_node->get_body ();
12720 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12721 false, NULL, NULL,
12722 "simdclone");
12724 else
12726 tree old_decl = old_node->decl;
12727 tree new_decl = copy_node (old_node->decl);
12728 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12729 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12730 SET_DECL_RTL (new_decl, NULL);
12731 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12732 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12733 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12734 symtab->call_cgraph_insertion_hooks (new_node);
12736 if (new_node == NULL)
12737 return new_node;
12739 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12741 /* The function cgraph_function_versioning () will force the new
12742 symbol local. Undo this, and inherit external visability from
12743 the old node. */
12744 new_node->local.local = old_node->local.local;
12745 new_node->externally_visible = old_node->externally_visible;
12747 return new_node;
12750 /* Adjust the return type of the given function to its appropriate
12751 vector counterpart. Returns a simd array to be used throughout the
12752 function as a return value. */
12754 static tree
12755 simd_clone_adjust_return_type (struct cgraph_node *node)
12757 tree fndecl = node->decl;
12758 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12759 unsigned int veclen;
12760 tree t;
12762 /* Adjust the function return type. */
12763 if (orig_rettype == void_type_node)
12764 return NULL_TREE;
12765 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12766 t = TREE_TYPE (TREE_TYPE (fndecl));
12767 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12768 veclen = node->simdclone->vecsize_int;
12769 else
12770 veclen = node->simdclone->vecsize_float;
12771 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12772 if (veclen > node->simdclone->simdlen)
12773 veclen = node->simdclone->simdlen;
12774 if (POINTER_TYPE_P (t))
12775 t = pointer_sized_int_node;
12776 if (veclen == node->simdclone->simdlen)
12777 t = build_vector_type (t, node->simdclone->simdlen);
12778 else
12780 t = build_vector_type (t, veclen);
12781 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
12783 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12784 if (!node->definition)
12785 return NULL_TREE;
12787 t = DECL_RESULT (fndecl);
12788 /* Adjust the DECL_RESULT. */
12789 gcc_assert (TREE_TYPE (t) != void_type_node);
12790 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12791 relayout_decl (t);
12793 tree atype = build_array_type_nelts (orig_rettype,
12794 node->simdclone->simdlen);
12795 if (veclen != node->simdclone->simdlen)
12796 return build1 (VIEW_CONVERT_EXPR, atype, t);
12798 /* Set up a SIMD array to use as the return value. */
12799 tree retval = create_tmp_var_raw (atype, "retval");
12800 gimple_add_tmp_var (retval);
12801 return retval;
12804 /* Each vector argument has a corresponding array to be used locally
12805 as part of the eventual loop. Create such temporary array and
12806 return it.
12808 PREFIX is the prefix to be used for the temporary.
12810 TYPE is the inner element type.
12812 SIMDLEN is the number of elements. */
12814 static tree
12815 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12817 tree atype = build_array_type_nelts (type, simdlen);
12818 tree avar = create_tmp_var_raw (atype, prefix);
12819 gimple_add_tmp_var (avar);
12820 return avar;
12823 /* Modify the function argument types to their corresponding vector
12824 counterparts if appropriate. Also, create one array for each simd
12825 argument to be used locally when using the function arguments as
12826 part of the loop.
12828 NODE is the function whose arguments are to be adjusted.
12830 Returns an adjustment vector that will be filled describing how the
12831 argument types will be adjusted. */
12833 static ipa_parm_adjustment_vec
12834 simd_clone_adjust_argument_types (struct cgraph_node *node)
12836 vec<tree> args;
12837 ipa_parm_adjustment_vec adjustments;
12839 if (node->definition)
12840 args = ipa_get_vector_of_formal_parms (node->decl);
12841 else
12842 args = simd_clone_vector_of_formal_parm_types (node->decl);
12843 adjustments.create (args.length ());
12844 unsigned i, j, veclen;
12845 struct ipa_parm_adjustment adj;
12846 for (i = 0; i < node->simdclone->nargs; ++i)
12848 memset (&adj, 0, sizeof (adj));
12849 tree parm = args[i];
12850 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12851 adj.base_index = i;
12852 adj.base = parm;
12854 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12855 node->simdclone->args[i].orig_type = parm_type;
12857 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12859 /* No adjustment necessary for scalar arguments. */
12860 adj.op = IPA_PARM_OP_COPY;
12862 else
12864 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12865 veclen = node->simdclone->vecsize_int;
12866 else
12867 veclen = node->simdclone->vecsize_float;
12868 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12869 if (veclen > node->simdclone->simdlen)
12870 veclen = node->simdclone->simdlen;
12871 adj.arg_prefix = "simd";
12872 if (POINTER_TYPE_P (parm_type))
12873 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12874 else
12875 adj.type = build_vector_type (parm_type, veclen);
12876 node->simdclone->args[i].vector_type = adj.type;
12877 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12879 adjustments.safe_push (adj);
12880 if (j == veclen)
12882 memset (&adj, 0, sizeof (adj));
12883 adj.op = IPA_PARM_OP_NEW;
12884 adj.arg_prefix = "simd";
12885 adj.base_index = i;
12886 adj.type = node->simdclone->args[i].vector_type;
12890 if (node->definition)
12891 node->simdclone->args[i].simd_array
12892 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12893 parm_type, node->simdclone->simdlen);
12895 adjustments.safe_push (adj);
12898 if (node->simdclone->inbranch)
12900 tree base_type
12901 = simd_clone_compute_base_data_type (node->simdclone->origin,
12902 node->simdclone);
12904 memset (&adj, 0, sizeof (adj));
12905 adj.op = IPA_PARM_OP_NEW;
12906 adj.arg_prefix = "mask";
12908 adj.base_index = i;
12909 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12910 veclen = node->simdclone->vecsize_int;
12911 else
12912 veclen = node->simdclone->vecsize_float;
12913 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12914 if (veclen > node->simdclone->simdlen)
12915 veclen = node->simdclone->simdlen;
12916 if (POINTER_TYPE_P (base_type))
12917 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12918 else
12919 adj.type = build_vector_type (base_type, veclen);
12920 adjustments.safe_push (adj);
12922 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12923 adjustments.safe_push (adj);
12925 /* We have previously allocated one extra entry for the mask. Use
12926 it and fill it. */
12927 struct cgraph_simd_clone *sc = node->simdclone;
12928 sc->nargs++;
12929 if (node->definition)
12931 sc->args[i].orig_arg
12932 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12933 sc->args[i].simd_array
12934 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12936 sc->args[i].orig_type = base_type;
12937 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12940 if (node->definition)
12941 ipa_modify_formal_parameters (node->decl, adjustments);
12942 else
12944 tree new_arg_types = NULL_TREE, new_reversed;
12945 bool last_parm_void = false;
12946 if (args.length () > 0 && args.last () == void_type_node)
12947 last_parm_void = true;
12949 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12950 j = adjustments.length ();
12951 for (i = 0; i < j; i++)
12953 struct ipa_parm_adjustment *adj = &adjustments[i];
12954 tree ptype;
12955 if (adj->op == IPA_PARM_OP_COPY)
12956 ptype = args[adj->base_index];
12957 else
12958 ptype = adj->type;
12959 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12961 new_reversed = nreverse (new_arg_types);
12962 if (last_parm_void)
12964 if (new_reversed)
12965 TREE_CHAIN (new_arg_types) = void_list_node;
12966 else
12967 new_reversed = void_list_node;
12970 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
12971 TYPE_ARG_TYPES (new_type) = new_reversed;
12972 TREE_TYPE (node->decl) = new_type;
12974 adjustments.release ();
12976 args.release ();
12977 return adjustments;
12980 /* Initialize and copy the function arguments in NODE to their
12981 corresponding local simd arrays. Returns a fresh gimple_seq with
12982 the instruction sequence generated. */
12984 static gimple_seq
12985 simd_clone_init_simd_arrays (struct cgraph_node *node,
12986 ipa_parm_adjustment_vec adjustments)
12988 gimple_seq seq = NULL;
12989 unsigned i = 0, j = 0, k;
12991 for (tree arg = DECL_ARGUMENTS (node->decl);
12992 arg;
12993 arg = DECL_CHAIN (arg), i++, j++)
12995 if (adjustments[j].op == IPA_PARM_OP_COPY)
12996 continue;
12998 node->simdclone->args[i].vector_arg = arg;
13000 tree array = node->simdclone->args[i].simd_array;
13001 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13003 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13004 tree ptr = build_fold_addr_expr (array);
13005 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13006 build_int_cst (ptype, 0));
13007 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13008 gimplify_and_add (t, &seq);
13010 else
13012 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13013 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13014 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13016 tree ptr = build_fold_addr_expr (array);
13017 int elemsize;
13018 if (k)
13020 arg = DECL_CHAIN (arg);
13021 j++;
13023 elemsize
13024 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13025 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13026 build_int_cst (ptype, k * elemsize));
13027 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13028 gimplify_and_add (t, &seq);
13032 return seq;
13035 /* Callback info for ipa_simd_modify_stmt_ops below. */
13037 struct modify_stmt_info {
13038 ipa_parm_adjustment_vec adjustments;
13039 gimple stmt;
13040 /* True if the parent statement was modified by
13041 ipa_simd_modify_stmt_ops. */
13042 bool modified;
13045 /* Callback for walk_gimple_op.
13047 Adjust operands from a given statement as specified in the
13048 adjustments vector in the callback data. */
13050 static tree
13051 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13053 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13054 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13055 tree *orig_tp = tp;
13056 if (TREE_CODE (*tp) == ADDR_EXPR)
13057 tp = &TREE_OPERAND (*tp, 0);
13058 struct ipa_parm_adjustment *cand = NULL;
13059 if (TREE_CODE (*tp) == PARM_DECL)
13060 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13061 else
13063 if (TYPE_P (*tp))
13064 *walk_subtrees = 0;
13067 tree repl = NULL_TREE;
13068 if (cand)
13069 repl = unshare_expr (cand->new_decl);
13070 else
13072 if (tp != orig_tp)
13074 *walk_subtrees = 0;
13075 bool modified = info->modified;
13076 info->modified = false;
13077 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13078 if (!info->modified)
13080 info->modified = modified;
13081 return NULL_TREE;
13083 info->modified = modified;
13084 repl = *tp;
13086 else
13087 return NULL_TREE;
13090 if (tp != orig_tp)
13092 repl = build_fold_addr_expr (repl);
13093 gimple stmt;
13094 if (is_gimple_debug (info->stmt))
13096 tree vexpr = make_node (DEBUG_EXPR_DECL);
13097 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13098 DECL_ARTIFICIAL (vexpr) = 1;
13099 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13100 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13101 repl = vexpr;
13103 else
13105 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13106 repl = gimple_assign_lhs (stmt);
13108 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13109 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13110 *orig_tp = repl;
13112 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13114 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13115 *tp = vce;
13117 else
13118 *tp = repl;
13120 info->modified = true;
13121 return NULL_TREE;
13124 /* Traverse the function body and perform all modifications as
13125 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13126 modified such that the replacement/reduction value will now be an
13127 offset into the corresponding simd_array.
13129 This function will replace all function argument uses with their
13130 corresponding simd array elements, and ajust the return values
13131 accordingly. */
13133 static void
13134 ipa_simd_modify_function_body (struct cgraph_node *node,
13135 ipa_parm_adjustment_vec adjustments,
13136 tree retval_array, tree iter)
13138 basic_block bb;
13139 unsigned int i, j, l;
13141 /* Re-use the adjustments array, but this time use it to replace
13142 every function argument use to an offset into the corresponding
13143 simd_array. */
13144 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13146 if (!node->simdclone->args[i].vector_arg)
13147 continue;
13149 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13150 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13151 adjustments[j].new_decl
13152 = build4 (ARRAY_REF,
13153 basetype,
13154 node->simdclone->args[i].simd_array,
13155 iter,
13156 NULL_TREE, NULL_TREE);
13157 if (adjustments[j].op == IPA_PARM_OP_NONE
13158 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13159 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13162 l = adjustments.length ();
13163 for (i = 1; i < num_ssa_names; i++)
13165 tree name = ssa_name (i);
13166 if (name
13167 && SSA_NAME_VAR (name)
13168 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13170 for (j = 0; j < l; j++)
13171 if (SSA_NAME_VAR (name) == adjustments[j].base
13172 && adjustments[j].new_decl)
13174 tree base_var;
13175 if (adjustments[j].new_ssa_base == NULL_TREE)
13177 base_var
13178 = copy_var_decl (adjustments[j].base,
13179 DECL_NAME (adjustments[j].base),
13180 TREE_TYPE (adjustments[j].base));
13181 adjustments[j].new_ssa_base = base_var;
13183 else
13184 base_var = adjustments[j].new_ssa_base;
13185 if (SSA_NAME_IS_DEFAULT_DEF (name))
13187 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13188 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13189 tree new_decl = unshare_expr (adjustments[j].new_decl);
13190 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13191 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13192 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13193 gimple stmt = gimple_build_assign (name, new_decl);
13194 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13196 else
13197 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13202 struct modify_stmt_info info;
13203 info.adjustments = adjustments;
13205 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13207 gimple_stmt_iterator gsi;
13209 gsi = gsi_start_bb (bb);
13210 while (!gsi_end_p (gsi))
13212 gimple stmt = gsi_stmt (gsi);
13213 info.stmt = stmt;
13214 struct walk_stmt_info wi;
13216 memset (&wi, 0, sizeof (wi));
13217 info.modified = false;
13218 wi.info = &info;
13219 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13221 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13223 tree retval = gimple_return_retval (return_stmt);
13224 if (!retval)
13226 gsi_remove (&gsi, true);
13227 continue;
13230 /* Replace `return foo' with `retval_array[iter] = foo'. */
13231 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13232 retval_array, iter, NULL, NULL);
13233 stmt = gimple_build_assign (ref, retval);
13234 gsi_replace (&gsi, stmt, true);
13235 info.modified = true;
13238 if (info.modified)
13240 update_stmt (stmt);
13241 if (maybe_clean_eh_stmt (stmt))
13242 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13244 gsi_next (&gsi);
13249 /* Adjust the argument types in NODE to their appropriate vector
13250 counterparts. */
13252 static void
13253 simd_clone_adjust (struct cgraph_node *node)
13255 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13257 targetm.simd_clone.adjust (node);
13259 tree retval = simd_clone_adjust_return_type (node);
13260 ipa_parm_adjustment_vec adjustments
13261 = simd_clone_adjust_argument_types (node);
13263 push_gimplify_context ();
13265 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13267 /* Adjust all uses of vector arguments accordingly. Adjust all
13268 return values accordingly. */
13269 tree iter = create_tmp_var (unsigned_type_node, "iter");
13270 tree iter1 = make_ssa_name (iter);
13271 tree iter2 = make_ssa_name (iter);
13272 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13274 /* Initialize the iteration variable. */
13275 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13276 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13277 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13278 /* Insert the SIMD array and iv initialization at function
13279 entry. */
13280 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13282 pop_gimplify_context (NULL);
13284 /* Create a new BB right before the original exit BB, to hold the
13285 iteration increment and the condition/branch. */
13286 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13287 basic_block incr_bb = create_empty_bb (orig_exit);
13288 add_bb_to_loop (incr_bb, body_bb->loop_father);
13289 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13290 flag. Set it now to be a FALLTHRU_EDGE. */
13291 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13292 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13293 for (unsigned i = 0;
13294 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13296 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13297 redirect_edge_succ (e, incr_bb);
13299 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13300 e->probability = REG_BR_PROB_BASE;
13301 gsi = gsi_last_bb (incr_bb);
13302 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13303 build_int_cst (unsigned_type_node, 1));
13304 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13306 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13307 struct loop *loop = alloc_loop ();
13308 cfun->has_force_vectorize_loops = true;
13309 loop->safelen = node->simdclone->simdlen;
13310 loop->force_vectorize = true;
13311 loop->header = body_bb;
13313 /* Branch around the body if the mask applies. */
13314 if (node->simdclone->inbranch)
13316 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13317 tree mask_array
13318 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13319 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13320 tree aref = build4 (ARRAY_REF,
13321 TREE_TYPE (TREE_TYPE (mask_array)),
13322 mask_array, iter1,
13323 NULL, NULL);
13324 g = gimple_build_assign (mask, aref);
13325 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13326 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13327 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13329 aref = build1 (VIEW_CONVERT_EXPR,
13330 build_nonstandard_integer_type (bitsize, 0), mask);
13331 mask = make_ssa_name (TREE_TYPE (aref));
13332 g = gimple_build_assign (mask, aref);
13333 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13336 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13337 NULL, NULL);
13338 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13339 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13340 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13343 /* Generate the condition. */
13344 g = gimple_build_cond (LT_EXPR,
13345 iter2,
13346 build_int_cst (unsigned_type_node,
13347 node->simdclone->simdlen),
13348 NULL, NULL);
13349 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13350 e = split_block (incr_bb, gsi_stmt (gsi));
13351 basic_block latch_bb = e->dest;
13352 basic_block new_exit_bb;
13353 new_exit_bb = split_block (latch_bb, NULL)->dest;
13354 loop->latch = latch_bb;
13356 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13358 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13359 /* The successor of incr_bb is already pointing to latch_bb; just
13360 change the flags.
13361 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13362 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13364 gphi *phi = create_phi_node (iter1, body_bb);
13365 edge preheader_edge = find_edge (entry_bb, body_bb);
13366 edge latch_edge = single_succ_edge (latch_bb);
13367 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13368 UNKNOWN_LOCATION);
13369 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13371 /* Generate the new return. */
13372 gsi = gsi_last_bb (new_exit_bb);
13373 if (retval
13374 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13375 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13376 retval = TREE_OPERAND (retval, 0);
13377 else if (retval)
13379 retval = build1 (VIEW_CONVERT_EXPR,
13380 TREE_TYPE (TREE_TYPE (node->decl)),
13381 retval);
13382 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13383 false, GSI_CONTINUE_LINKING);
13385 g = gimple_build_return (retval);
13386 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13388 /* Handle aligned clauses by replacing default defs of the aligned
13389 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13390 lhs. Handle linear by adding PHIs. */
13391 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13392 if (node->simdclone->args[i].alignment
13393 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13394 && (node->simdclone->args[i].alignment
13395 & (node->simdclone->args[i].alignment - 1)) == 0
13396 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13397 == POINTER_TYPE)
13399 unsigned int alignment = node->simdclone->args[i].alignment;
13400 tree orig_arg = node->simdclone->args[i].orig_arg;
13401 tree def = ssa_default_def (cfun, orig_arg);
13402 if (def && !has_zero_uses (def))
13404 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13405 gimple_seq seq = NULL;
13406 bool need_cvt = false;
13407 gcall *call
13408 = gimple_build_call (fn, 2, def, size_int (alignment));
13409 g = call;
13410 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13411 ptr_type_node))
13412 need_cvt = true;
13413 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13414 gimple_call_set_lhs (g, t);
13415 gimple_seq_add_stmt_without_update (&seq, g);
13416 if (need_cvt)
13418 t = make_ssa_name (orig_arg);
13419 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13420 gimple_seq_add_stmt_without_update (&seq, g);
13422 gsi_insert_seq_on_edge_immediate
13423 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13425 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13426 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13427 entry_bb);
13428 node->create_edge (cgraph_node::get_create (fn),
13429 call, entry_bb->count, freq);
13431 imm_use_iterator iter;
13432 use_operand_p use_p;
13433 gimple use_stmt;
13434 tree repl = gimple_get_lhs (g);
13435 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13436 if (is_gimple_debug (use_stmt) || use_stmt == call)
13437 continue;
13438 else
13439 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13440 SET_USE (use_p, repl);
13443 else if (node->simdclone->args[i].arg_type
13444 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13446 tree orig_arg = node->simdclone->args[i].orig_arg;
13447 tree def = ssa_default_def (cfun, orig_arg);
13448 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13449 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13450 if (def && !has_zero_uses (def))
13452 iter1 = make_ssa_name (orig_arg);
13453 iter2 = make_ssa_name (orig_arg);
13454 phi = create_phi_node (iter1, body_bb);
13455 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13456 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13457 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13458 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13459 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13460 ? TREE_TYPE (orig_arg) : sizetype;
13461 tree addcst
13462 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13463 g = gimple_build_assign (iter2, code, iter1, addcst);
13464 gsi = gsi_last_bb (incr_bb);
13465 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13467 imm_use_iterator iter;
13468 use_operand_p use_p;
13469 gimple use_stmt;
13470 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13471 if (use_stmt == phi)
13472 continue;
13473 else
13474 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13475 SET_USE (use_p, iter1);
13479 calculate_dominance_info (CDI_DOMINATORS);
13480 add_loop (loop, loop->header->loop_father);
13481 update_ssa (TODO_update_ssa);
13483 pop_cfun ();
13486 /* If the function in NODE is tagged as an elemental SIMD function,
13487 create the appropriate SIMD clones. */
13489 static void
13490 expand_simd_clones (struct cgraph_node *node)
13492 tree attr = lookup_attribute ("omp declare simd",
13493 DECL_ATTRIBUTES (node->decl));
13494 if (attr == NULL_TREE
13495 || node->global.inlined_to
13496 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13497 return;
13499 /* Ignore
13500 #pragma omp declare simd
13501 extern int foo ();
13502 in C, there we don't know the argument types at all. */
13503 if (!node->definition
13504 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13505 return;
13509 /* Start with parsing the "omp declare simd" attribute(s). */
13510 bool inbranch_clause_specified;
13511 struct cgraph_simd_clone *clone_info
13512 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13513 &inbranch_clause_specified);
13514 if (clone_info == NULL)
13515 continue;
13517 int orig_simdlen = clone_info->simdlen;
13518 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13519 /* The target can return 0 (no simd clones should be created),
13520 1 (just one ISA of simd clones should be created) or higher
13521 count of ISA variants. In that case, clone_info is initialized
13522 for the first ISA variant. */
13523 int count
13524 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13525 base_type, 0);
13526 if (count == 0)
13527 continue;
13529 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13530 also create one inbranch and one !inbranch clone of it. */
13531 for (int i = 0; i < count * 2; i++)
13533 struct cgraph_simd_clone *clone = clone_info;
13534 if (inbranch_clause_specified && (i & 1) != 0)
13535 continue;
13537 if (i != 0)
13539 clone = simd_clone_struct_alloc (clone_info->nargs
13540 + ((i & 1) != 0));
13541 simd_clone_struct_copy (clone, clone_info);
13542 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13543 and simd_clone_adjust_argument_types did to the first
13544 clone's info. */
13545 clone->nargs -= clone_info->inbranch;
13546 clone->simdlen = orig_simdlen;
13547 /* And call the target hook again to get the right ISA. */
13548 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13549 base_type,
13550 i / 2);
13551 if ((i & 1) != 0)
13552 clone->inbranch = 1;
13555 /* simd_clone_mangle might fail if such a clone has been created
13556 already. */
13557 tree id = simd_clone_mangle (node, clone);
13558 if (id == NULL_TREE)
13559 continue;
13561 /* Only when we are sure we want to create the clone actually
13562 clone the function (or definitions) or create another
13563 extern FUNCTION_DECL (for prototypes without definitions). */
13564 struct cgraph_node *n = simd_clone_create (node);
13565 if (n == NULL)
13566 continue;
13568 n->simdclone = clone;
13569 clone->origin = node;
13570 clone->next_clone = NULL;
13571 if (node->simd_clones == NULL)
13573 clone->prev_clone = n;
13574 node->simd_clones = n;
13576 else
13578 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13579 clone->prev_clone->simdclone->next_clone = n;
13580 node->simd_clones->simdclone->prev_clone = n;
13582 symtab->change_decl_assembler_name (n->decl, id);
13583 /* And finally adjust the return type, parameters and for
13584 definitions also function body. */
13585 if (node->definition)
13586 simd_clone_adjust (n);
13587 else
13589 simd_clone_adjust_return_type (n);
13590 simd_clone_adjust_argument_types (n);
13594 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13597 /* Entry point for IPA simd clone creation pass. */
13599 static unsigned int
13600 ipa_omp_simd_clone (void)
13602 struct cgraph_node *node;
13603 FOR_EACH_FUNCTION (node)
13604 expand_simd_clones (node);
13605 return 0;
13608 namespace {
13610 const pass_data pass_data_omp_simd_clone =
13612 SIMPLE_IPA_PASS, /* type */
13613 "simdclone", /* name */
13614 OPTGROUP_NONE, /* optinfo_flags */
13615 TV_NONE, /* tv_id */
13616 ( PROP_ssa | PROP_cfg ), /* properties_required */
13617 0, /* properties_provided */
13618 0, /* properties_destroyed */
13619 0, /* todo_flags_start */
13620 0, /* todo_flags_finish */
13623 class pass_omp_simd_clone : public simple_ipa_opt_pass
13625 public:
13626 pass_omp_simd_clone(gcc::context *ctxt)
13627 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13630 /* opt_pass methods: */
13631 virtual bool gate (function *);
13632 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13635 bool
13636 pass_omp_simd_clone::gate (function *)
13638 return ((flag_openmp || flag_openmp_simd
13639 || flag_cilkplus
13640 || (in_lto_p && !flag_wpa))
13641 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13644 } // anon namespace
13646 simple_ipa_opt_pass *
13647 make_pass_omp_simd_clone (gcc::context *ctxt)
13649 return new pass_omp_simd_clone (ctxt);
13652 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13653 adds their addresses and sizes to constructor-vector V_CTOR. */
13654 static void
13655 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13656 vec<constructor_elt, va_gc> *v_ctor)
13658 unsigned len = vec_safe_length (v_decls);
13659 for (unsigned i = 0; i < len; i++)
13661 tree it = (*v_decls)[i];
13662 bool is_function = TREE_CODE (it) != VAR_DECL;
13664 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13665 if (!is_function)
13666 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13667 fold_convert (const_ptr_type_node,
13668 DECL_SIZE_UNIT (it)));
13672 /* Create new symbols containing (address, size) pairs for global variables,
13673 marked with "omp declare target" attribute, as well as addresses for the
13674 functions, which are outlined offloading regions. */
13675 void
13676 omp_finish_file (void)
13678 unsigned num_funcs = vec_safe_length (offload_funcs);
13679 unsigned num_vars = vec_safe_length (offload_vars);
13681 if (num_funcs == 0 && num_vars == 0)
13682 return;
13684 if (targetm_common.have_named_sections)
13686 vec<constructor_elt, va_gc> *v_f, *v_v;
13687 vec_alloc (v_f, num_funcs);
13688 vec_alloc (v_v, num_vars * 2);
13690 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13691 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13693 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13694 num_vars * 2);
13695 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13696 num_funcs);
13697 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13698 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13699 tree ctor_v = build_constructor (vars_decl_type, v_v);
13700 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13701 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13702 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13703 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13704 get_identifier (".offload_func_table"),
13705 funcs_decl_type);
13706 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13707 get_identifier (".offload_var_table"),
13708 vars_decl_type);
13709 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13710 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13711 otherwise a joint table in a binary will contain padding between
13712 tables from multiple object files. */
13713 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13714 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13715 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13716 DECL_INITIAL (funcs_decl) = ctor_f;
13717 DECL_INITIAL (vars_decl) = ctor_v;
13718 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13719 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13721 varpool_node::finalize_decl (vars_decl);
13722 varpool_node::finalize_decl (funcs_decl);
13724 else
13726 for (unsigned i = 0; i < num_funcs; i++)
13728 tree it = (*offload_funcs)[i];
13729 targetm.record_offload_symbol (it);
13731 for (unsigned i = 0; i < num_vars; i++)
13733 tree it = (*offload_vars)[i];
13734 targetm.record_offload_symbol (it);
13739 #include "gt-omp-low.h"